From f545f6a16a6349f26ffa145460aa8d6b8f6d4afe Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 13 Jul 2023 19:35:46 +0200 Subject: [PATCH] chore(roll): roll Playwright to v1.36.0 (#2634) --- README.md | 6 +-- src/Common/Version.props | 2 +- .../BrowserContextCSPTests.cs | 9 ++--- .../BrowserContextRouteTests.cs | 16 -------- src/Playwright.Tests/InterceptionTests.cs | 13 +++++-- src/Playwright.Tests/PageEvaluateTests.cs | 8 ++++ src/Playwright.Tests/PageGotoTests.cs | 4 +- src/Playwright.Tests/PageRouteTests.cs | 38 +++++++++++-------- src/Playwright.Tests/TestUtils.cs | 16 -------- .../API/Generated/IAPIRequestContext.cs | 6 +-- src/Playwright/API/Generated/IBrowserType.cs | 2 +- src/Playwright/API/Generated/IFrame.cs | 20 +++++----- src/Playwright/API/Generated/IFrameLocator.cs | 20 +++++----- src/Playwright/API/Generated/IJSHandle.cs | 2 +- src/Playwright/API/Generated/ILocator.cs | 24 ++++++------ .../API/Generated/ILocatorAssertions.cs | 4 +- src/Playwright/API/Generated/IPage.cs | 24 ++++++------ src/Playwright/API/Generated/IRoute.cs | 4 +- src/Playwright/API/Generated/ITracing.cs | 20 +++++----- src/Playwright/Helpers/StringExtensions.cs | 23 ++++++----- .../EvaluateArgumentValueConverter.cs | 11 ++++++ .../Protocol/Generated/SerializedValue.cs | 3 ++ 22 files changed, 138 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index 843f06f3db..4edfeb2451 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 115.0.5790.24 | ✅ | ✅ | ✅ | -| WebKit 16.4 | ✅ | ✅ | ✅ | -| Firefox 113.0 | ✅ | ✅ | ✅ | +| Chromium 115.0.5790.75 | ✅ | ✅ | ✅ | +| WebKit 17.0 | ✅ | ✅ | ✅ | +| Firefox 115.0 | ✅ | ✅ | ✅ | Playwright for .NET is the official language port of [Playwright](https://playwright.dev), the library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**. diff --git a/src/Common/Version.props b/src/Common/Version.props index 2657e25526..eb65181c8c 100644 --- a/src/Common/Version.props +++ b/src/Common/Version.props @@ -2,7 +2,7 @@ 1.36.0 $(AssemblyVersion)-beta-1 - 1.35.0 + 1.36.0 $(AssemblyVersion) $(AssemblyVersion) true diff --git a/src/Playwright.Tests/BrowserContextCSPTests.cs b/src/Playwright.Tests/BrowserContextCSPTests.cs index 20120173ae..13162f5986 100644 --- a/src/Playwright.Tests/BrowserContextCSPTests.cs +++ b/src/Playwright.Tests/BrowserContextCSPTests.cs @@ -34,8 +34,7 @@ public async Task ShouldBypassCSPMetatag() { var page = await context.NewPageAsync(); await page.GotoAsync(Server.Prefix + "/csp.html"); - var exception = await PlaywrightAssert.ThrowsAsync(() => page.AddScriptTagAsync(new() { Content = "window.__injected = 42;" })); - TestUtils.AssertCSPError(exception.Message); + await PlaywrightAssert.ThrowsAsync(() => page.AddScriptTagAsync(new() { Content = "window.__injected = 42;" })); Assert.Null(await page.EvaluateAsync("window.__injected")); } // By-pass CSP and try one more time. @@ -58,8 +57,7 @@ public async Task ShouldBypassCSPHeader() { var page = await context.NewPageAsync(); await page.GotoAsync(Server.EmptyPage); - var exception = await PlaywrightAssert.ThrowsAsync(() => page.AddScriptTagAsync(new() { Content = "window.__injected = 42;" })); - TestUtils.AssertCSPError(exception.Message); + await PlaywrightAssert.ThrowsAsync(() => page.AddScriptTagAsync(new() { Content = "window.__injected = 42;" })); Assert.Null(await page.EvaluateAsync("window.__injected")); } @@ -97,8 +95,7 @@ public async Task ShouldBypassCSPInIframesAsWell() // Make sure CSP prohibits addScriptTag in an iframe. var frame = await FrameUtils.AttachFrameAsync(page, "frame1", Server.Prefix + "/csp.html"); - var exception = await PlaywrightAssert.ThrowsAsync(() => frame.AddScriptTagAsync(new() { Content = "window.__injected = 42;" })); - TestUtils.AssertCSPError(exception.Message); + await PlaywrightAssert.ThrowsAsync(() => frame.AddScriptTagAsync(new() { Content = "window.__injected = 42;" })); Assert.Null(await frame.EvaluateAsync("() => window.__injected")); } diff --git a/src/Playwright.Tests/BrowserContextRouteTests.cs b/src/Playwright.Tests/BrowserContextRouteTests.cs index 7b1b49cc36..d0abe17f12 100644 --- a/src/Playwright.Tests/BrowserContextRouteTests.cs +++ b/src/Playwright.Tests/BrowserContextRouteTests.cs @@ -179,22 +179,6 @@ await page.RouteAsync("**/non-empty.html", (route) => Assert.AreEqual("context", await response.TextAsync()); } - [PlaywrightTest] - public async Task ShouldThrowOnInvalidRouteUrl() - { - await using var context = await Browser.NewContextAsync(); - - var regexParseExceptionType = typeof(System.Text.RegularExpressions.Regex).Assembly - .GetType("System.Text.RegularExpressions.RegexParseException", throwOnError: true); - - Assert.Throws(regexParseExceptionType, () => - context.RouteAsync("[", route => - { - route.ContinueAsync(); - }) - ); - } - [PlaywrightTest("browsercontext-route.spec.ts", "should support the times parameter with route matching")] public async Task ShouldSupportTheTimesParameterWithRouteMatching() { diff --git a/src/Playwright.Tests/InterceptionTests.cs b/src/Playwright.Tests/InterceptionTests.cs index 87d1cb5ca2..05c4ad1126 100644 --- a/src/Playwright.Tests/InterceptionTests.cs +++ b/src/Playwright.Tests/InterceptionTests.cs @@ -33,22 +33,29 @@ public class GlobTests : PageTestEx public void ShouldWorkWithGlob() { Assert.That("https://localhost:8080/foo.js", Does.Match(StringExtensions.GlobToRegex("**/*.js"))); + Assert.That("https://localhost:8080/foo.js", Does.Not.Match(StringExtensions.GlobToRegex("**/*.css"))); + Assert.That("https://localhost:8080/foo.js", Does.Not.Match(StringExtensions.GlobToRegex("*.js"))); Assert.That("https://localhost:8080/foo.js", Does.Match(StringExtensions.GlobToRegex("https://**/*.js"))); Assert.That("http://localhost:8080/simple/path.js", Does.Match(StringExtensions.GlobToRegex("http://localhost:8080/simple/path.js"))); Assert.That("http://localhost:8080/Simple/path.js", Does.Match(StringExtensions.GlobToRegex("http://localhost:8080/?imple/path.js"))); Assert.That("https://localhost:8080/a.js", Does.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); Assert.That("https://localhost:8080/b.js", Does.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); + Assert.That("https://localhost:8080/c.js", Does.Not.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); Assert.That("https://localhost:8080/c.jpg", Does.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); Assert.That("https://localhost:8080/c.jpeg", Does.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); Assert.That("https://localhost:8080/c.png", Does.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); Assert.That("https://localhost:8080/c.css", Does.Not.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); - Assert.That("https://localhost:8080/foo.js", Does.Not.Match(StringExtensions.GlobToRegex("**/*.css"))); - Assert.That("https://localhost:8080/foo.js", Does.Not.Match(StringExtensions.GlobToRegex("*.js"))); - Assert.That("https://localhost:8080/c.js", Does.Not.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); Assert.That("foo.js", Does.Match(StringExtensions.GlobToRegex("foo*"))); Assert.That("foo/bar.js", Does.Not.Match(StringExtensions.GlobToRegex("foo*"))); Assert.That("http://localhost:3000/signin-oidc/foo", Does.Not.Match(StringExtensions.GlobToRegex("http://localhost:3000/signin-oidc*"))); Assert.That("http://localhost:3000/signin-oidcnice", Does.Match(StringExtensions.GlobToRegex("http://localhost:3000/signin-oidc*"))); + + Assert.AreEqual("^\\?$", StringExtensions.GlobToRegex("\\?")); + Assert.AreEqual("^\\\\$", StringExtensions.GlobToRegex("\\")); + Assert.AreEqual("^\\\\$", StringExtensions.GlobToRegex("\\\\")); + Assert.AreEqual("^\\[$", StringExtensions.GlobToRegex("\\[")); + Assert.AreEqual("^\\[$", StringExtensions.GlobToRegex("[")); + Assert.AreEqual("^\\$\\^\\+\\.\\*\\(\\)\\|\\?\\{\\}\\[\\]$", StringExtensions.GlobToRegex("$^+.\\*()|\\?\\{\\}[]")); } [PlaywrightTest("interception.spec.ts", "should work with ignoreHTTPSErrors")] diff --git a/src/Playwright.Tests/PageEvaluateTests.cs b/src/Playwright.Tests/PageEvaluateTests.cs index 8dc924baea..95ff3c3870 100644 --- a/src/Playwright.Tests/PageEvaluateTests.cs +++ b/src/Playwright.Tests/PageEvaluateTests.cs @@ -24,6 +24,7 @@ using System.ComponentModel; using System.Dynamic; +using System.Numerics; using System.Text.Json; using System.Text.RegularExpressions; @@ -72,6 +73,13 @@ public async Task ShouldTransferNegativeInfinity() Assert.AreEqual(double.NegativeInfinity, result); } + [PlaywrightTest("page-evaluate.spec.ts", "should transfer bigint")] + public async Task ShouldTransferBigInt() + { + Assert.AreEqual(new BigInteger(42), await Page.EvaluateAsync("() => 42n")); + Assert.AreEqual(new BigInteger(17), await Page.EvaluateAsync("a => a", new BigInteger(17))); + } + [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip unserializable values")] public async Task ShouldRoundtripUnserializableValues() { diff --git a/src/Playwright.Tests/PageGotoTests.cs b/src/Playwright.Tests/PageGotoTests.cs index 3f6ed45859..dd13f050bb 100644 --- a/src/Playwright.Tests/PageGotoTests.cs +++ b/src/Playwright.Tests/PageGotoTests.cs @@ -391,12 +391,12 @@ public async Task ShouldFailWhenReplacedByAnotherNavigation() } else if (TestConstants.IsWebKit) { - StringAssert.Contains("Navigation interrupted by another one", exception.Message); + StringAssert.Contains("is interrupted by another navigation to", exception.Message); } else { // Firefox might yield either NS_BINDING_ABORTED or 'navigation interrupted by another one' - Assert.True(exception.Message.Contains("NS_BINDING_ABORTED") || exception.Message.Contains("Navigation interrupted by another one")); + Assert.True(exception.Message.Contains("NS_BINDING_ABORTED") || exception.Message.Contains("is interrupted by another navigation to")); } } diff --git a/src/Playwright.Tests/PageRouteTests.cs b/src/Playwright.Tests/PageRouteTests.cs index b236082251..dcb436074e 100644 --- a/src/Playwright.Tests/PageRouteTests.cs +++ b/src/Playwright.Tests/PageRouteTests.cs @@ -102,6 +102,29 @@ await Page.RouteAsync("**/empty.html", (route) => Assert.AreEqual(new[] { 1 }, intercepted.ToArray()); } + [PlaywrightTest("page-route.spec.ts", "should support ? in glob pattern")] + public async Task ShouldSupportInGlobPattern() + { + Server.SetRoute("/index", context => context.Response.WriteAsync("index-no-hello")); + Server.SetRoute("/index123hello", context => context.Response.WriteAsync("index123hello")); + Server.SetRoute("/index?hello", context => context.Response.WriteAsync("index?hello")); + + await Page.RouteAsync("**/index?hello", (route) => route.FulfillAsync(new() { Body = "intercepted any character" })); + await Page.RouteAsync("**/index\\?hello", (route) => route.FulfillAsync(new() { Body = "intercepted question mark" })); + + await Page.GotoAsync(Server.Prefix + "/index?hello"); + StringAssert.Contains("intercepted question mark", await Page.ContentAsync()); + + await Page.GotoAsync(Server.Prefix + "/index"); + StringAssert.Contains("index-no-hello", await Page.ContentAsync()); + + await Page.GotoAsync(Server.Prefix + "/index1hello"); + StringAssert.Contains("intercepted any character", await Page.ContentAsync()); + + await Page.GotoAsync(Server.Prefix + "/index123hello"); + StringAssert.Contains("index123hello", await Page.ContentAsync()); + } + [PlaywrightTest("page-route.spec.ts", "should work when POST is redirected with 302")] public async Task ShouldWorkWhenPostIsRedirectedWith302() { @@ -688,21 +711,6 @@ await Page.RouteAsync("**/cars*", (route) => Assert.AreEqual(new[] { "DELETE", "electric", "cars" }, resp); } - [PlaywrightTest] - public void ShouldThrowOnInvalidRouteUrl() - { - var regexParseExceptionType = typeof(Regex).Assembly - .GetType("System.Text.RegularExpressions.RegexParseException", throwOnError: true); - - - Assert.Throws(regexParseExceptionType, () => - Page.RouteAsync("[", route => - { - route.ContinueAsync(); - }) - ); - } - [PlaywrightTest("page-route.spec.ts", "should support the times parameter with route matching")] public async Task ShouldSupportTheTimesParameterWithRouteMatching() { diff --git a/src/Playwright.Tests/TestUtils.cs b/src/Playwright.Tests/TestUtils.cs index 3e1b8ac8a6..e6a337b6f1 100644 --- a/src/Playwright.Tests/TestUtils.cs +++ b/src/Playwright.Tests/TestUtils.cs @@ -62,22 +62,6 @@ internal static void AssertSSLError(string errorMessage) } } - internal static void AssertCSPError(string errorMessage) - { - if (TestConstants.IsWebKit) - { - StringAssert.StartsWith("Refused to execute a script because its hash, its nonce, or 'unsafe-inline' appears in neither the script-src directive nor the default-src directive of the Content Security Policy.", errorMessage); - } - else if (TestConstants.IsFirefox) - { - StringAssert.StartsWith("[JavaScript Error: \"Content Security Policy: The page’s settings blocked the loading of a resource at inline (“default-src”).\"", errorMessage); - } - else - { - StringAssert.StartsWith("Refused to execute inline script because it violates the following Content Security Policy directive: \"default-src 'self'\".", errorMessage); - } - } - /// /// Removes as much whitespace as possible from a given string. Whitespace /// that separates letters and/or digits is collapsed to a space character. diff --git a/src/Playwright/API/Generated/IAPIRequestContext.cs b/src/Playwright/API/Generated/IAPIRequestContext.cs index 5b5d64b250..b33a5e02bd 100644 --- a/src/Playwright/API/Generated/IAPIRequestContext.cs +++ b/src/Playwright/API/Generated/IAPIRequestContext.cs @@ -163,12 +163,12 @@ public partial interface IAPIRequestContext /// into the URL search parameters: /// /// - /// var params = new Dictionary<string, object>()
+ /// var queryParams = new Dictionary<string, object>()
/// {
/// { "isbn", "1234" },
/// { "page", 23 },
- /// }
- /// await request.GetAsync("https://example.com/api/getText", new() { Params = params }); + /// };
+ /// await request.GetAsync("https://example.com/api/getText", new() { Params = queryParams }); ///
///
/// Target URL. diff --git a/src/Playwright/API/Generated/IBrowserType.cs b/src/Playwright/API/Generated/IBrowserType.cs index 3dc24d46db..8cd32386aa 100644 --- a/src/Playwright/API/Generated/IBrowserType.cs +++ b/src/Playwright/API/Generated/IBrowserType.cs @@ -106,7 +106,7 @@ public partial interface IBrowserType /// /// var browser = await playwright.Chromium.LaunchAsync(new() {
/// IgnoreDefaultArgs = new[] { "--mute-audio" }
- /// }) + /// }); ///
/// /// > **Chromium-only** Playwright can also be used to control the Google Chrome or diff --git a/src/Playwright/API/Generated/IFrame.cs b/src/Playwright/API/Generated/IFrame.cs index cfb869919c..3bd1428bbd 100644 --- a/src/Playwright/API/Generated/IFrame.cs +++ b/src/Playwright/API/Generated/IFrame.cs @@ -703,19 +703,19 @@ public partial interface IFrame /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// @@ -744,19 +744,19 @@ public partial interface IFrame /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// diff --git a/src/Playwright/API/Generated/IFrameLocator.cs b/src/Playwright/API/Generated/IFrameLocator.cs index 22ce5a346c..407118c2ea 100644 --- a/src/Playwright/API/Generated/IFrameLocator.cs +++ b/src/Playwright/API/Generated/IFrameLocator.cs @@ -243,19 +243,19 @@ public partial interface IFrameLocator /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// @@ -284,19 +284,19 @@ public partial interface IFrameLocator /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// diff --git a/src/Playwright/API/Generated/IJSHandle.cs b/src/Playwright/API/Generated/IJSHandle.cs index 95a8f90a68..31c95994a7 100644 --- a/src/Playwright/API/Generated/IJSHandle.cs +++ b/src/Playwright/API/Generated/IJSHandle.cs @@ -103,7 +103,7 @@ public partial interface IJSHandle /// /// **Usage** /// - /// var handle = await page.EvaluateHandleAsync("() => ({window, document}");
+ /// var handle = await page.EvaluateHandleAsync("() => ({ window, document }");
/// var properties = await handle.GetPropertiesAsync();
/// var windowHandle = properties["window"];
/// var documentHandle = properties["document"];
diff --git a/src/Playwright/API/Generated/ILocator.cs b/src/Playwright/API/Generated/ILocator.cs index 665c1ca4e7..8fad965d9f 100644 --- a/src/Playwright/API/Generated/ILocator.cs +++ b/src/Playwright/API/Generated/ILocator.cs @@ -48,7 +48,7 @@ public partial interface ILocator ///
/// **Usage** /// - /// foreach (var li in await page.GetByRole('listitem').AllAsync())
+ /// foreach (var li in await page.GetByRole("listitem").AllAsync())
/// await li.ClickAsync(); ///
/// @@ -692,19 +692,19 @@ public partial interface ILocator /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// @@ -733,19 +733,19 @@ public partial interface ILocator /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// @@ -858,7 +858,7 @@ public partial interface ILocator /// or radio input. /// /// **Usage** - /// Boolean checked = await page.GetByRole(AriaRole.Checkbox).IsCheckedAsync(); + /// var isChecked = await page.GetByRole(AriaRole.Checkbox).IsCheckedAsync(); /// /// Call options Task IsCheckedAsync(LocatorIsCheckedOptions? options = default); diff --git a/src/Playwright/API/Generated/ILocatorAssertions.cs b/src/Playwright/API/Generated/ILocatorAssertions.cs index ad9479a9ac..48d779b6dc 100644 --- a/src/Playwright/API/Generated/ILocatorAssertions.cs +++ b/src/Playwright/API/Generated/ILocatorAssertions.cs @@ -765,7 +765,7 @@ public partial interface ILocatorAssertions /// For example, given the following element: /// /// var locator = Page.Locator("id=favorite-colors");
- /// await locator.SelectOptionAsync(new string[] { "R", "G" })
+ /// await locator.SelectOptionAsync(new string[] { "R", "G" });
/// await Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") }); ///
/// @@ -782,7 +782,7 @@ public partial interface ILocatorAssertions /// For example, given the following element: /// /// var locator = Page.Locator("id=favorite-colors");
- /// await locator.SelectOptionAsync(new string[] { "R", "G" })
+ /// await locator.SelectOptionAsync(new string[] { "R", "G" });
/// await Expect(locator).ToHaveValuesAsync(new Regex[] { new Regex("R"), new Regex("G") }); ///
/// diff --git a/src/Playwright/API/Generated/IPage.cs b/src/Playwright/API/Generated/IPage.cs index 959c31af64..0c85dc7a85 100644 --- a/src/Playwright/API/Generated/IPage.cs +++ b/src/Playwright/API/Generated/IPage.cs @@ -769,7 +769,7 @@ public partial interface IPage /// using var playwright = await Playwright.CreateAsync();
/// await using var browser = await playwright.Webkit.LaunchAsync(new()
/// {
- /// Headless: false
+ /// Headless = false,
/// });
/// var page = await browser.NewPageAsync();
///
@@ -834,7 +834,7 @@ public partial interface IPage /// using var playwright = await Playwright.CreateAsync();
/// await using var browser = await playwright.Webkit.LaunchAsync(new()
/// {
- /// Headless: false
+ /// Headless = false
/// });
/// var page = await browser.NewPageAsync();
///
@@ -1147,19 +1147,19 @@ public partial interface IPage /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// @@ -1188,19 +1188,19 @@ public partial interface IPage /// You can locate by text substring, exact string, or a regular expression: /// /// // Matches <span>
- /// page.GetByText("world")
+ /// page.GetByText("world");
///
/// // Matches first <div>
- /// page.GetByText("Hello world")
+ /// page.GetByText("Hello world");
///
/// // Matches second <div>
- /// page.GetByText("Hello", new() { Exact: true })
+ /// page.GetByText("Hello", new() { Exact = true });
///
/// // Matches both <div>s
- /// page.GetByText(new Regex("Hello"))
+ /// page.GetByText(new Regex("Hello"));
///
/// // Matches second <div>
- /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)) + /// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase)); ///
/// **Details** /// diff --git a/src/Playwright/API/Generated/IRoute.cs b/src/Playwright/API/Generated/IRoute.cs index 631af6088e..c3fa8e6b81 100644 --- a/src/Playwright/API/Generated/IRoute.cs +++ b/src/Playwright/API/Generated/IRoute.cs @@ -197,8 +197,8 @@ public partial interface IRoute /// {
/// Status = 404,
/// ContentType = "text/plain",
- /// Body = "Not Found!")
- /// }); + /// Body = "Not Found!"
+ /// })); ///
/// An example of serving static file: /// await page.RouteAsync("**/xhr_endpoint", route => route.FulfillAsync(new() { Path = "mock_data.json" })); diff --git a/src/Playwright/API/Generated/ITracing.cs b/src/Playwright/API/Generated/ITracing.cs index 31b856aab4..d53d27dc3b 100644 --- a/src/Playwright/API/Generated/ITracing.cs +++ b/src/Playwright/API/Generated/ITracing.cs @@ -43,14 +43,14 @@ namespace Microsoft.Playwright; /// await using var context = await browser.NewContextAsync();
/// await context.Tracing.StartAsync(new()
/// {
-/// Screenshots: true,
-/// Snapshots: true
+/// Screenshots = true,
+/// Snapshots = true
/// });
/// var page = context.NewPageAsync();
/// await page.GotoAsync("https://playwright.dev");
/// await context.Tracing.StopAsync(new()
/// {
-/// Path: "trace.zip"
+/// Path = "trace.zip"
/// }); /// /// @@ -64,14 +64,14 @@ public partial interface ITracing /// await using var context = await browser.NewContextAsync();
/// await context.Tracing.StartAsync(new()
/// {
- /// Screenshots: true,
- /// Snapshots: true
+ /// Screenshots = true,
+ /// Snapshots = true
/// });
/// var page = context.NewPageAsync();
/// await page.GotoAsync("https://playwright.dev");
/// await context.Tracing.StopAsync(new()
/// {
- /// Path: "trace.zip"
+ /// Path = "trace.zip"
/// }); /// /// @@ -90,8 +90,8 @@ public partial interface ITracing /// await using var context = await browser.NewContextAsync();
/// await context.Tracing.StartAsync(new()
/// {
- /// Screenshots: true,
- /// Snapshots: true
+ /// Screenshots = true,
+ /// Snapshots = true
/// });
/// var page = context.NewPageAsync();
/// await page.GotoAsync("https://playwright.dev");
@@ -101,7 +101,7 @@ public partial interface ITracing /// // Everything between StartChunkAsync and StopChunkAsync will be recorded in the trace.
/// await context.Tracing.StopChunkAsync(new()
/// {
- /// Path: "trace1.zip"
+ /// Path = "trace1.zip"
/// });
///
/// await context.Tracing.StartChunkAsync();
@@ -109,7 +109,7 @@ public partial interface ITracing /// // Save a second trace file with different actions.
/// await context.Tracing.StopChunkAsync(new()
/// {
- /// Path: "trace2.zip"
+ /// Path = "trace2.zip"
/// }); /// /// diff --git a/src/Playwright/Helpers/StringExtensions.cs b/src/Playwright/Helpers/StringExtensions.cs index b96bafda19..d5773b913a 100644 --- a/src/Playwright/Helpers/StringExtensions.cs +++ b/src/Playwright/Helpers/StringExtensions.cs @@ -37,7 +37,8 @@ namespace Microsoft.Playwright.Helpers; /// internal static class StringExtensions { - private static readonly char[] _escapeGlobChars = new[] { '/', '$', '^', '+', '.', '(', ')', '=', '!', '|' }; + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping + private static readonly char[] _escapeGlobChars = new[] { '$', '^', '+', '.', '*', '(', ')', '|', '\\', '?', '{', '}', '[', ']' }; private static readonly IDictionary _mappings = new Dictionary(StringComparer.InvariantCultureIgnoreCase) { @@ -643,31 +644,30 @@ public static string GlobToRegex(this string glob) return null; } - List tokens = new List { "^" }; + List tokens = new() { "^" }; bool inGroup = false; for (int i = 0; i < glob.Length; ++i) { - char c = glob[i]; - if (_escapeGlobChars.Contains(c)) + var c = glob[i]; + if (c == '\\' && i + 1 < glob.Length) { - tokens.Add("\\" + c); + var @char = glob[++i]; + tokens.Add(_escapeGlobChars.Contains(@char) ? "\\" + @char : @char.ToString()); continue; } - if (c == '*') { - char? beforeDeep = i == 0 ? (char?)null : glob[i - 1]; + char? beforeDeep = i == 0 ? null : glob[i - 1]; int starCount = 1; - while (i < glob.Length - 1 && glob[i + 1] == '*') { starCount++; i++; } - char? afterDeep = i >= glob.Length - 1 ? (char?)null : glob[i + 1]; - bool isDeep = starCount > 1 && + char? afterDeep = i >= glob.Length - 1 ? null : glob[i + 1]; + var isDeep = starCount > 1 && (beforeDeep == '/' || beforeDeep == null) && (afterDeep == '/' || afterDeep == null); if (isDeep) @@ -679,7 +679,6 @@ public static string GlobToRegex(this string glob) { tokens.Add("([^/]*)"); } - continue; } @@ -706,7 +705,7 @@ public static string GlobToRegex(this string glob) tokens.Add("\\" + c); break; default: - tokens.Add(c.ToString()); + tokens.Add(_escapeGlobChars.Contains(c) ? "\\" + c : c.ToString()); break; } } diff --git a/src/Playwright/Transport/Converters/EvaluateArgumentValueConverter.cs b/src/Playwright/Transport/Converters/EvaluateArgumentValueConverter.cs index 0585ac6b60..5b9a89a055 100644 --- a/src/Playwright/Transport/Converters/EvaluateArgumentValueConverter.cs +++ b/src/Playwright/Transport/Converters/EvaluateArgumentValueConverter.cs @@ -29,6 +29,7 @@ using System.Dynamic; using System.Globalization; using System.Linq; +using System.Numerics; using System.Runtime.Serialization; using System.Text.Json; using System.Text.RegularExpressions; @@ -113,6 +114,11 @@ internal static object Serialize(object value, List return new { u = uri.ToString() }; } + if (value is BigInteger bigInteger) + { + return new { bi = bigInteger.ToString() }; + } + if (value is Regex regex) { return new { r = new { p = regex.ToString(), f = regex.Options.GetInlineFlags() } }; @@ -319,6 +325,11 @@ private static object ParseEvaluateResultToExpando(JsonElement result, IDictiona return url.ToObject(); } + if (result.TryGetProperty("bi", out var bigInt)) + { + return BigInteger.Parse(bigInt.ToObject()); + } + if (result.TryGetProperty("r", out var regex)) { return new Regex(regex.GetProperty("p").ToString(), RegexOptionsExtensions.FromInlineFlags(regex.GetProperty("f").ToString())); diff --git a/src/Playwright/Transport/Protocol/Generated/SerializedValue.cs b/src/Playwright/Transport/Protocol/Generated/SerializedValue.cs index 69ea7a7b02..c92233be26 100644 --- a/src/Playwright/Transport/Protocol/Generated/SerializedValue.cs +++ b/src/Playwright/Transport/Protocol/Generated/SerializedValue.cs @@ -47,6 +47,9 @@ internal class SerializedValue [JsonPropertyName("u")] public string U { get; set; } + [JsonPropertyName("bi")] + public string Bi { get; set; } + [JsonPropertyName("r")] public SerializedValueR R { get; set; }