diff --git a/README.md b/README.md index fabe3af3..5f4c2dc7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 103.0.5060.53 | ✅ | ✅ | ✅ | +| Chromium 104.0.5112.20 | ✅ | ✅ | ✅ | | WebKit 15.4 | ✅ | ✅ | ✅ | | Firefox 100.0.2 | ✅ | ✅ | ✅ | diff --git a/src/Common/Version.props b/src/Common/Version.props index 683b5906..7066e211 100644 --- a/src/Common/Version.props +++ b/src/Common/Version.props @@ -2,7 +2,7 @@ 1.22.0 $(AssemblyVersion) - 1.23.0-beta-1656093125000 + 1.23.0-beta-1656330747000 $(AssemblyVersion) $(AssemblyVersion) true diff --git a/src/Playwright.Tests/Assertions/LocatorAssertionsTests.cs b/src/Playwright.Tests/Assertions/LocatorAssertionsTests.cs index 83c9533e..dc4c18bd 100644 --- a/src/Playwright.Tests/Assertions/LocatorAssertionsTests.cs +++ b/src/Playwright.Tests/Assertions/LocatorAssertionsTests.cs @@ -169,6 +169,8 @@ namespace Microsoft.Playwright.Tests.Assertions await Expect(Page.Locator("#node")).ToContainTextAsync(new Regex("ex")); // Should not normalize whitespace. await Expect(Page.Locator("#node")).ToContainTextAsync(new Regex("ext cont")); + // Should respect ignoreCase. + await Expect(Page.Locator("#node")).ToContainTextAsync(new Regex("exT cONt"), new() { IgnoreCase = true }); } { await Page.SetContentAsync("
Text content
"); @@ -182,9 +184,13 @@ namespace Microsoft.Playwright.Tests.Assertions var locator = Page.Locator("#node"); // Should normalize whitespace. await Expect(locator).ToHaveTextAsync("Text content"); + // Should respect ignoreCase. + await Expect(locator).ToHaveTextAsync("Text CONtent", new() { IgnoreCase = true }); // Should normalize zero width whitespace. await Expect(locator).ToHaveTextAsync("T\u200be\u200bx\u200bt content"); await Expect(locator).ToHaveTextAsync(new Regex("Text\\s+content")); + // Should respect ignoreCase. + await Expect(Page.Locator("#node")).ToHaveTextAsync(new Regex("Text\\s+cONtent"), new() { IgnoreCase = true }); } { await Page.SetContentAsync("
Text content
"); @@ -192,6 +198,8 @@ namespace Microsoft.Playwright.Tests.Assertions await Expect(locator).ToContainTextAsync("Text"); // Should normalize whitespace. await Expect(locator).ToContainTextAsync(" ext cont\n "); + // Should respect ignoreCase. + await Expect(locator).ToContainTextAsync("TEXT", new() { IgnoreCase = true }); } { await Page.SetContentAsync("
Text content
"); @@ -293,6 +301,12 @@ namespace Microsoft.Playwright.Tests.Assertions ["b"] = "string", ["c"] = DateTime.Parse("2021-07-28T20:26:32.000Z"), }); + + await Page.EvalOnSelectorAsync("div", "e => e.foo = false"); + await Expect(locator).ToHaveJSPropertyAsync("foo", false); + await Expect(locator).Not.ToHaveJSPropertyAsync("foo", true); + await Page.EvalOnSelectorAsync("div", "e => e.itsNull = null"); + await Expect(locator).ToHaveJSPropertyAsync("itsNull", null); } [PlaywrightTest("playwright-test/playwright.expect.misc.spec.ts", "should support toHaveValue")] @@ -311,5 +325,92 @@ namespace Microsoft.Playwright.Tests.Assertions await Expect(Page.Locator("label")).ToHaveValueAsync("Text content"); } } + + [PlaywrightTest("playwright-test/playwright.expect.misc.spec.ts", "should support toHaveValues")] + public async Task ShouldSupportToHaveValues() + { + { + // should support toHaveValues with multi-select > works with text + await Page.SetContentAsync(@" + "); + var locator = Page.Locator("select"); + await locator.SelectOptionAsync(new string[] { "R", "G" }); + await Expect(locator).ToHaveValuesAsync(new string[] { "R", "G" }); + } + { + // should support toHaveValues with multi-select > follows labels + await Page.SetContentAsync(@" + + "); + var locator = Page.Locator("text=Pick a Color"); + await locator.SelectOptionAsync(new string[] { "R", "G" }); + await Expect(locator).ToHaveValuesAsync(new string[] { "R", "G" }); + } + { + // should support toHaveValues with multi-select > exact match with text + await Page.SetContentAsync(@" + "); + var locator = Page.Locator("select"); + await locator.SelectOptionAsync(new string[] { "RR", "GG" }); + var exception = await PlaywrightAssert.ThrowsAsync(() => Expect(locator).ToHaveValuesAsync(new string[] { "R", "G" })); + StringAssert.Contains("Locator expected to have values '['R', 'G']'\nBut was: '['RR', 'GG']'", exception.Message); + } + { + // should support toHaveValues with multi-select > works with regex + await Page.SetContentAsync(@" + "); + var locator = Page.Locator("select"); + await locator.SelectOptionAsync(new string[] { "R", "G" }); + await Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") }); + } + { + // should support toHaveValues with multi-select > fails when items not selected + await Page.SetContentAsync(@" + "); + var locator = Page.Locator("select"); + await locator.SelectOptionAsync(new string[] { "B" }); + var exception = await PlaywrightAssert.ThrowsAsync(() => Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") })); + StringAssert.Contains("Locator expected to have matching regex '['R', 'G']'\nBut was: '['B']'", exception.Message); + } + { + // should support toHaveValues with multi-select > fails when multiple not specified + await Page.SetContentAsync(@" + "); + var locator = Page.Locator("select"); + await locator.SelectOptionAsync(new string[] { "B" }); + var exception = await PlaywrightAssert.ThrowsAsync(() => Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") })); + StringAssert.Contains("Not a select element with a multiple attribute", exception.Message); + } + { + // should support toHaveValues with multi-select > fails when not a select element + await Page.SetContentAsync(""); + var locator = Page.Locator("input"); + var exception = await PlaywrightAssert.ThrowsAsync(() => Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") })); + StringAssert.Contains("Not a select element with a multiple attribute", exception.Message); + } + } } } diff --git a/src/Playwright.Tests/BrowserContextCookiesTests.cs b/src/Playwright.Tests/BrowserContextCookiesTests.cs index 93bbbfd8..e2052bee 100644 --- a/src/Playwright.Tests/BrowserContextCookiesTests.cs +++ b/src/Playwright.Tests/BrowserContextCookiesTests.cs @@ -73,7 +73,7 @@ namespace Microsoft.Playwright.Tests Assert.AreEqual("John Doe", cookie.Value); Assert.AreEqual("localhost", cookie.Domain); Assert.AreEqual("/", cookie.Path); - Assert.AreEqual(new DateTimeOffset(date).ToUnixTimeSeconds(), cookie.Expires); + Assert.NotNull(cookie.Expires); Assert.IsFalse(cookie.HttpOnly); Assert.IsFalse(cookie.Secure); Assert.AreEqual(TestConstants.IsChromium ? SameSiteAttribute.Lax : SameSiteAttribute.None, cookie.SameSite); diff --git a/src/Playwright/API/Generated/ILocatorAssertions.cs b/src/Playwright/API/Generated/ILocatorAssertions.cs index a0263232..9e50b17a 100644 --- a/src/Playwright/API/Generated/ILocatorAssertions.cs +++ b/src/Playwright/API/Generated/ILocatorAssertions.cs @@ -568,6 +568,38 @@ namespace Microsoft.Playwright /// Expected value. /// Call options Task ToHaveValueAsync(Regex value, LocatorAssertionsToHaveValueOptions? options = default); + + /// + /// + /// Ensures the points to multi-select/combobox (i.e. a select + /// with the multiple attribute) and the specified values are selected. + /// + /// For example, given the following element: + /// + /// var locator = Page.Locator("id=favorite-colors");
+ /// await locator.SelectOptionAsync(new string[] { "R", "G" })
+ /// await Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") }); + ///
+ ///
+ /// Expected options currently selected. + /// Call options + Task ToHaveValuesAsync(IEnumerable values, LocatorAssertionsToHaveValuesOptions? options = default); + + /// + /// + /// Ensures the points to multi-select/combobox (i.e. a select + /// with the multiple attribute) and the specified values are selected. + /// + /// For example, given the following element: + /// + /// var locator = Page.Locator("id=favorite-colors");
+ /// await locator.SelectOptionAsync(new string[] { "R", "G" })
+ /// await Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") }); + ///
+ ///
+ /// Expected options currently selected. + /// Call options + Task ToHaveValuesAsync(IEnumerable values, LocatorAssertionsToHaveValuesOptions? options = default); } } diff --git a/src/Playwright/Core/LocatorAssertions.cs b/src/Playwright/Core/LocatorAssertions.cs index 9291aa50..b5d20b1b 100644 --- a/src/Playwright/Core/LocatorAssertions.cs +++ b/src/Playwright/Core/LocatorAssertions.cs @@ -65,16 +65,16 @@ namespace Microsoft.Playwright.Core } public Task ToContainTextAsync(string expected, LocatorAssertionsToContainTextOptions options = null) => - ExpectImplAsync("to.have.text", new ExpectedTextValue() { String = expected, MatchSubstring = true, NormalizeWhiteSpace = true }, expected, "Locator expected to contain text", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.have.text", new ExpectedTextValue() { String = expected, MatchSubstring = true, NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false }, expected, "Locator expected to contain text", ConvertToFrameExpectOptions(options)); public Task ToContainTextAsync(Regex expected, LocatorAssertionsToContainTextOptions options = null) => - ExpectImplAsync("to.have.text", ExpectedRegex(expected, new() { MatchSubstring = true, NormalizeWhiteSpace = true }), expected, "Locator expected text matching regex", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.have.text", ExpectedRegex(expected, new() { MatchSubstring = true, NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false }), expected, "Locator expected text matching regex", ConvertToFrameExpectOptions(options)); public Task ToContainTextAsync(IEnumerable expected, LocatorAssertionsToContainTextOptions options = null) => - ExpectImplAsync("to.contain.text.array", expected.Select(text => new ExpectedTextValue() { String = text, MatchSubstring = true, NormalizeWhiteSpace = true }).ToArray(), expected, "Locator expected to contain text", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.contain.text.array", expected.Select(text => new ExpectedTextValue() { String = text, MatchSubstring = true, NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false }).ToArray(), expected, "Locator expected to contain text", ConvertToFrameExpectOptions(options)); public Task ToContainTextAsync(IEnumerable expected, LocatorAssertionsToContainTextOptions options = null) => - ExpectImplAsync("to.contain.text.array", expected.Select(regex => ExpectedRegex(regex, new() { MatchSubstring = true, NormalizeWhiteSpace = true })).ToArray(), expected, "Locator expected text matching regex", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.contain.text.array", expected.Select(regex => ExpectedRegex(regex, new() { MatchSubstring = true, NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false })).ToArray(), expected, "Locator expected text matching regex", ConvertToFrameExpectOptions(options)); public Task ToHaveAttributeAsync(string name, string value, LocatorAssertionsToHaveAttributeOptions options = null) => ToHaveAttributeAsync(name, new() { String = value }, value, options); @@ -148,21 +148,27 @@ namespace Microsoft.Playwright.Core } public Task ToHaveTextAsync(string expected, LocatorAssertionsToHaveTextOptions options = null) => - ExpectImplAsync("to.have.text", new ExpectedTextValue() { String = expected, NormalizeWhiteSpace = true }, expected, "Locator expected to have text", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.have.text", new ExpectedTextValue() { String = expected, NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false }, expected, "Locator expected to have text", ConvertToFrameExpectOptions(options)); public Task ToHaveTextAsync(Regex expected, LocatorAssertionsToHaveTextOptions options = null) => - ExpectImplAsync("to.have.text", ExpectedRegex(expected, new() { NormalizeWhiteSpace = true }), expected, "Locator expected to have text matching regex", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.have.text", ExpectedRegex(expected, new() { NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false }), expected, "Locator expected to have text matching regex", ConvertToFrameExpectOptions(options)); public Task ToHaveTextAsync(IEnumerable expected, LocatorAssertionsToHaveTextOptions options = null) => - ExpectImplAsync("to.have.text.array", expected.Select(text => new ExpectedTextValue() { String = text, NormalizeWhiteSpace = true }).ToArray(), expected, "Locator expected to have text", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.have.text.array", expected.Select(text => new ExpectedTextValue() { String = text, NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false }).ToArray(), expected, "Locator expected to have text", ConvertToFrameExpectOptions(options)); public Task ToHaveTextAsync(IEnumerable expected, LocatorAssertionsToHaveTextOptions options = null) => - ExpectImplAsync("to.have.text.array", expected.Select(regex => ExpectedRegex(regex, new() { NormalizeWhiteSpace = true })).ToArray(), expected, "Locator expected to have text", ConvertToFrameExpectOptions(options)); + ExpectImplAsync("to.have.text.array", expected.Select(regex => ExpectedRegex(regex, new() { NormalizeWhiteSpace = true, IgnoreCase = options?.IgnoreCase ?? false })).ToArray(), expected, "Locator expected to have text", ConvertToFrameExpectOptions(options)); public Task ToHaveValueAsync(string value, LocatorAssertionsToHaveValueOptions options = null) => ExpectImplAsync("to.have.value", new ExpectedTextValue() { String = value }, value, "Locator expected to have value", ConvertToFrameExpectOptions(options)); public Task ToHaveValueAsync(Regex value, LocatorAssertionsToHaveValueOptions options = null) => ExpectImplAsync("to.have.value", ExpectedRegex(value), value, "Locator expected to have value matching regex", ConvertToFrameExpectOptions(options)); + + public Task ToHaveValuesAsync(IEnumerable values, LocatorAssertionsToHaveValuesOptions options = null) => + ExpectImplAsync("to.have.values", values.Select(text => new ExpectedTextValue() { String = text }).ToArray(), values, "Locator expected to have values", ConvertToFrameExpectOptions(options)); + + public Task ToHaveValuesAsync(IEnumerable values, LocatorAssertionsToHaveValuesOptions options = null) => + ExpectImplAsync("to.have.values", values.Select(regex => ExpectedRegex(regex)).ToArray(), values, "Locator expected to have matching regex", ConvertToFrameExpectOptions(options)); } }