chore(roll): roll Playwright to v1.47.0 (#3000)

This commit is contained in:
Max Schmitt
2024-09-09 15:52:34 +02:00
committed by GitHub
parent 08ad1569ff
commit ff667e445d
24 changed files with 178 additions and 101 deletions
+2 -2
View File
@@ -3,9 +3,9 @@
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->128.0.6613.18<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Chromium <!-- GEN:chromium-version -->129.0.6668.29<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| WebKit <!-- GEN:webkit-version -->18.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->128.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->130.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
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**.
+1 -1
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyVersion>1.46.0</AssemblyVersion>
<PackageVersion>$(AssemblyVersion)</PackageVersion>
<DriverVersion>1.46.0</DriverVersion>
<DriverVersion>1.47.0</DriverVersion>
<ReleaseVersion>$(AssemblyVersion)</ReleaseVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<NoDefaultExcludes>true</NoDefaultExcludes>
@@ -103,22 +103,35 @@ public class BrowserContextFetchTests : PageTestEx
Assert.AreEqual("username=John Doe", cookieHeader);
}
[PlaywrightTest("browsercontext-fetch.spec.ts", "should support queryParams")]
public async Task ShouldSupportQueryParams()
[PlaywrightTest("browsercontext-fetch.spec.ts", "should support paras passed as object")]
public async Task ShouldSupportParamsPassedAsObject()
{
var queryString = new QueryString();
queryString.Add("p1", "v1");
queryString.Add("парам2", "знач2");
var requestOptions = new APIRequestContextOptions() { Params = new Dictionary<string, object>() { { "p1", "v1" }, { "парам2", "знач2" } } };
var requestOptions = new APIRequestContextOptions() { Params = new Dictionary<string, object>() { { "param1", "value1" }, { "парам2", "знач2" } } };
await ForAllMethods(Context.APIRequest, async responseTask =>
{
var (receivedQueryString, _) = await TaskUtils.WhenAll(
Server.WaitForRequest("/empty.html", request => request.Query),
responseTask
);
Assert.AreEqual("v1", receivedQueryString["p1"].First());
CollectionAssert.AreEquivalent(new[] { "value1", "value2" }, receivedQueryString["param1"]);
Assert.AreEqual("знач2", receivedQueryString["парам2"].First());
}, Server.Prefix + "/empty.html?" + queryString.ToString(), requestOptions);
}, Server.Prefix + "/empty.html?param1=value2", requestOptions);
}
[PlaywrightTest("browsercontext-fetch.spec.ts", "should support params passed as string")]
public async Task ShouldSupportParamsPassedAsString()
{
var queryParams = "?param1=value1&param1=value2&парам2=знач2";
var requestOptions = new APIRequestContextOptions() { ParamsString = queryParams };
await ForAllMethods(Context.APIRequest, async responseTask =>
{
var (receivedQueryString, _) = await TaskUtils.WhenAll(
Server.WaitForRequest("/empty.html", request => request.Query),
responseTask
);
CollectionAssert.AreEquivalent(new[] { "value1", "value2" }, receivedQueryString["param1"]);
Assert.AreEqual("знач2", string.Join(",", receivedQueryString["парам2"]));
}, Server.Prefix + "/empty.html", requestOptions);
}
[PlaywrightTest("browsercontext-fetch.spec.ts", "should support failOnStatusCode")]
@@ -147,6 +147,40 @@ public class ClientCertificatesTests : BrowserTestEx
await context.CloseAsync();
}
[PlaywrightTest("", "")]
public async Task ShouldWorkWithNewContextAndCertificateAsContent()
{
var context = await Browser.NewContextAsync(new()
{
IgnoreHTTPSErrors = true,
ClientCertificates =
[
new()
{
Origin = "https://localhost:10000",
Cert = File.ReadAllBytes(TestUtils.GetAsset("client-certificates/client/trusted/cert.pem")),
Key = File.ReadAllBytes(TestUtils.GetAsset("client-certificates/client/trusted/key.pem")),
}
]
});
var page = await context.NewPageAsync();
{
await page.GotoAsync("https://127.0.0.1:10000");
await Expect(page.GetByTestId("message")).ToHaveTextAsync("Sorry, but you need to provide a client certificate to continue.");
var response = await page.APIRequest.GetAsync("https://127.0.0.1:10000");
StringAssert.Contains("Sorry, but you need to provide a client certificate to continue", await response.TextAsync());
}
{
await page.GotoAsync("https://localhost:10000");
await Expect(page.GetByText("Hello CN=Alice")).ToBeVisibleAsync();
var response = await page.APIRequest.GetAsync("https://localhost:10000");
StringAssert.Contains("Hello CN=Alice", await response.TextAsync());
}
await context.CloseAsync();
}
[PlaywrightTest("", "")]
public async Task ShouldWorkWithNewPage()
{
+1 -1
View File
@@ -46,7 +46,7 @@ public partial interface IAPIResponse
/// <summary>
/// <para>
/// An array with all the request HTTP headers associated with this response. Header
/// An array with all the response HTTP headers associated with this response. Header
/// names are not lower-cased. Headers with multiple entries, such as <c>Set-Cookie</c>,
/// appear in the array multiple times.
/// </para>
@@ -38,8 +38,8 @@ namespace Microsoft.Playwright;
/// belong to the parent page's browser context.
/// </para>
/// <para>
/// Playwright allows creating "incognito" browser contexts with <see cref="IBrowser.NewContextAsync"/>
/// method. "Incognito" browser contexts don't write any browsing data to disk.
/// Playwright allows creating isolated non-persistent browser contexts with <see cref="IBrowser.NewContextAsync"/>
/// method. Non-persistent browser contexts don't write any browsing data to disk.
/// </para>
/// <code>
/// using var playwright = await Playwright.CreateAsync();<br/>
@@ -60,14 +60,14 @@ public partial interface IPageAssertions
/// Makes the assertion check for the opposite condition. For example, this code tests
/// that the page URL doesn't contain <c>"error"</c>:
/// </para>
/// <code>await Expect(Page).Not.ToHaveURL("error");</code>
/// <code>await Expect(Page).Not.ToHaveURLAsync("error");</code>
/// </summary>
public IPageAssertions Not { get; }
/// <summary>
/// <para>Ensures the page has the given title.</para>
/// <para>**Usage**</para>
/// <code>await Expect(Page).ToHaveTitle("Playwright");</code>
/// <code>await Expect(Page).ToHaveTitleAsync("Playwright");</code>
/// </summary>
/// <param name="titleOrRegExp">Expected title or RegExp.</param>
/// <param name="options">Call options</param>
@@ -76,7 +76,7 @@ public partial interface IPageAssertions
/// <summary>
/// <para>Ensures the page has the given title.</para>
/// <para>**Usage**</para>
/// <code>await Expect(Page).ToHaveTitle("Playwright");</code>
/// <code>await Expect(Page).ToHaveTitleAsync("Playwright");</code>
/// </summary>
/// <param name="titleOrRegExp">Expected title or RegExp.</param>
/// <param name="options">Call options</param>
@@ -85,7 +85,7 @@ public partial interface IPageAssertions
/// <summary>
/// <para>Ensures the page is navigated to the given URL.</para>
/// <para>**Usage**</para>
/// <code>await Expect(Page).ToHaveURL(new Regex(".*checkout"));</code>
/// <code>await Expect(Page).ToHaveURLAsync(new Regex(".*checkout"));</code>
/// </summary>
/// <param name="urlOrRegExp">Expected URL string or RegExp.</param>
/// <param name="options">Call options</param>
@@ -94,7 +94,7 @@ public partial interface IPageAssertions
/// <summary>
/// <para>Ensures the page is navigated to the given URL.</para>
/// <para>**Usage**</para>
/// <code>await Expect(Page).ToHaveURL(new Regex(".*checkout"));</code>
/// <code>await Expect(Page).ToHaveURLAsync(new Regex(".*checkout"));</code>
/// </summary>
/// <param name="urlOrRegExp">Expected URL string or RegExp.</param>
/// <param name="options">Call options</param>
+16 -2
View File
@@ -73,7 +73,7 @@ public partial interface IRoute
Task AbortAsync(string? errorCode = default);
/// <summary>
/// <para>Continues route's request with optional overrides.</para>
/// <para>Sends route's request to the network with optional overrides.</para>
/// <para>**Usage**</para>
/// <code>
/// await page.RouteAsync("**/*", async route =&gt;<br/>
@@ -91,19 +91,29 @@ public partial interface IRoute
/// through redirects, use the combination of <see cref="IRoute.FetchAsync"/> and <see
/// cref="IRoute.FulfillAsync"/> instead.
/// </para>
/// <para>
/// <see cref="IRoute.ContinueAsync"/> will immediately send the request to the network,
/// other matching handlers won't be invoked. Use <see cref="IRoute.FallbackAsync"/>
/// If you want next matching handler in the chain to be invoked.
/// </para>
/// </summary>
/// <param name="options">Call options</param>
Task ContinueAsync(RouteContinueOptions? options = default);
/// <summary>
/// <para>
/// Continues route's request with optional overrides. The method is similar to <see
/// cref="IRoute.ContinueAsync"/> with the difference that other matching handlers will
/// be invoked before sending the request.
/// </para>
/// <para>**Usage**</para>
/// <para>
/// When several routes match the given pattern, they run in the order opposite to their
/// registration. That way the last registered route can always override all the previous
/// ones. In the example below, request will be handled by the bottom-most handler first,
/// then it'll fall back to the previous one and in the end will be aborted by the first
/// registered route.
/// </para>
/// <para>**Usage**</para>
/// <code>
/// await page.RouteAsync("**/*", route =&gt; {<br/>
/// // Runs last.<br/>
@@ -158,6 +168,10 @@ public partial interface IRoute
/// await route.FallbackAsync(new() { Headers = headers });<br/>
/// });
/// </code>
/// <para>
/// Use <see cref="IRoute.ContinueAsync"/> to immediately send the request to the network,
/// other matching handlers won't be invoked in that case.
/// </para>
/// </summary>
/// <param name="options">Call options</param>
Task FallbackAsync(RouteFallbackOptions? options = default);
@@ -53,6 +53,7 @@ public class APIRequestContextOptions
Method = clone.Method;
Multipart = clone.Multipart;
Params = clone.Params;
ParamsString = clone.ParamsString;
Timeout = clone.Timeout;
}
@@ -181,6 +182,10 @@ public class APIRequestContextOptions
[JsonPropertyName("params")]
public IEnumerable<KeyValuePair<string, object>>? Params { get; set; }
/// <summary><para>Query parameters to be sent with the URL.</para></summary>
[JsonPropertyName("paramsString")]
public string? ParamsString { get; set; }
/// <summary>
/// <para>
/// Request timeout in milliseconds. Defaults to <c>30000</c> (30 seconds). Pass <c>0</c>
@@ -83,11 +83,12 @@ public class APIRequestNewContextOptions
/// </para>
/// <para>**Details**</para>
/// <para>
/// An array of client certificates to be used. Each certificate object must have both
/// <c>certPath</c> and <c>keyPath</c> or a single <c>pfxPath</c> to load the client
/// certificate. Optionally, <c>passphrase</c> property should be provided if the certficiate
/// is encrypted. The <c>origin</c> property should be provided with an exact match
/// to the request origin that the certificate is valid for.
/// An array of client certificates to be used. Each certificate object must have either
/// both <c>certPath</c> and <c>keyPath</c>, a single <c>pfxPath</c>, or their corresponding
/// direct value equivalents (<c>cert</c> and <c>key</c>, or <c>pfx</c>). Optionally,
/// <c>passphrase</c> property should be provided if the certificate is encrypted. The
/// <c>origin</c> property should be provided with an exact match to the request origin
/// that the certificate is valid for.
/// </para>
/// </summary>
/// <remarks>
@@ -124,11 +124,12 @@ public class BrowserNewContextOptions
/// </para>
/// <para>**Details**</para>
/// <para>
/// An array of client certificates to be used. Each certificate object must have both
/// <c>certPath</c> and <c>keyPath</c> or a single <c>pfxPath</c> to load the client
/// certificate. Optionally, <c>passphrase</c> property should be provided if the certficiate
/// is encrypted. The <c>origin</c> property should be provided with an exact match
/// to the request origin that the certificate is valid for.
/// An array of client certificates to be used. Each certificate object must have either
/// both <c>certPath</c> and <c>keyPath</c>, a single <c>pfxPath</c>, or their corresponding
/// direct value equivalents (<c>cert</c> and <c>key</c>, or <c>pfx</c>). Optionally,
/// <c>passphrase</c> property should be provided if the certificate is encrypted. The
/// <c>origin</c> property should be provided with an exact match to the request origin
/// that the certificate is valid for.
/// </para>
/// </summary>
/// <remarks>
@@ -259,14 +260,6 @@ public class BrowserNewContextOptions
public IEnumerable<string>? Permissions { get; set; }
/// <summary><para>Network proxy settings to use with this context. Defaults to none.</para></summary>
/// <remarks>
/// <para>
/// For Chromium on Windows the browser needs to be launched with the global proxy for
/// this option to work. If all contexts override the proxy, global proxy will be never
/// used and can be any string, for example <c>launch({ proxy: { server: 'http://per-context'
/// } })</c>.
/// </para>
/// </remarks>
[JsonPropertyName("proxy")]
public Proxy? Proxy { get; set; }
@@ -124,11 +124,12 @@ public class BrowserNewPageOptions
/// </para>
/// <para>**Details**</para>
/// <para>
/// An array of client certificates to be used. Each certificate object must have both
/// <c>certPath</c> and <c>keyPath</c> or a single <c>pfxPath</c> to load the client
/// certificate. Optionally, <c>passphrase</c> property should be provided if the certficiate
/// is encrypted. The <c>origin</c> property should be provided with an exact match
/// to the request origin that the certificate is valid for.
/// An array of client certificates to be used. Each certificate object must have either
/// both <c>certPath</c> and <c>keyPath</c>, a single <c>pfxPath</c>, or their corresponding
/// direct value equivalents (<c>cert</c> and <c>key</c>, or <c>pfx</c>). Optionally,
/// <c>passphrase</c> property should be provided if the certificate is encrypted. The
/// <c>origin</c> property should be provided with an exact match to the request origin
/// that the certificate is valid for.
/// </para>
/// </summary>
/// <remarks>
@@ -259,14 +260,6 @@ public class BrowserNewPageOptions
public IEnumerable<string>? Permissions { get; set; }
/// <summary><para>Network proxy settings to use with this context. Defaults to none.</para></summary>
/// <remarks>
/// <para>
/// For Chromium on Windows the browser needs to be launched with the global proxy for
/// this option to work. If all contexts override the proxy, global proxy will be never
/// used and can be any string, for example <c>launch({ proxy: { server: 'http://per-context'
/// } })</c>.
/// </para>
/// </remarks>
[JsonPropertyName("proxy")]
public Proxy? Proxy { get; set; }
@@ -164,11 +164,12 @@ public class BrowserTypeLaunchPersistentContextOptions
/// </para>
/// <para>**Details**</para>
/// <para>
/// An array of client certificates to be used. Each certificate object must have both
/// <c>certPath</c> and <c>keyPath</c> or a single <c>pfxPath</c> to load the client
/// certificate. Optionally, <c>passphrase</c> property should be provided if the certficiate
/// is encrypted. The <c>origin</c> property should be provided with an exact match
/// to the request origin that the certificate is valid for.
/// An array of client certificates to be used. Each certificate object must have either
/// both <c>certPath</c> and <c>keyPath</c>, a single <c>pfxPath</c>, or their corresponding
/// direct value equivalents (<c>cert</c> and <c>key</c>, or <c>pfx</c>). Optionally,
/// <c>passphrase</c> property should be provided if the certificate is encrypted. The
/// <c>origin</c> property should be provided with an exact match to the request origin
/// that the certificate is valid for.
/// </para>
/// </summary>
/// <remarks>
@@ -54,13 +54,8 @@ public class ElementHandleSelectOptionOptions
public bool? Force { get; set; }
/// <summary>
/// <para>**DEPRECATED** This option will default to <c>true</c> in the future.</para>
/// <para>
/// Actions that initiate navigations are waiting for these navigations to happen and
/// for pages to start loading. You can opt out of waiting via setting this flag. You
/// would only need this option in the exceptional cases such as navigating to inaccessible
/// pages. Defaults to <c>false</c>.
/// </para>
/// <para>**DEPRECATED** This option has no effect.</para>
/// <para>This option has no effect.</para>
/// </summary>
[JsonPropertyName("noWaitAfter")]
[System.Obsolete]
@@ -55,13 +55,8 @@ public class FrameSelectOptionOptions
public bool? Force { get; set; }
/// <summary>
/// <para>**DEPRECATED** This option will default to <c>true</c> in the future.</para>
/// <para>
/// Actions that initiate navigations are waiting for these navigations to happen and
/// for pages to start loading. You can opt out of waiting via setting this flag. You
/// would only need this option in the exceptional cases such as navigating to inaccessible
/// pages. Defaults to <c>false</c>.
/// </para>
/// <para>**DEPRECATED** This option has no effect.</para>
/// <para>This option has no effect.</para>
/// </summary>
[JsonPropertyName("noWaitAfter")]
[System.Obsolete]
@@ -54,13 +54,8 @@ public class LocatorSelectOptionOptions
public bool? Force { get; set; }
/// <summary>
/// <para>**DEPRECATED** This option will default to <c>true</c> in the future.</para>
/// <para>
/// Actions that initiate navigations are waiting for these navigations to happen and
/// for pages to start loading. You can opt out of waiting via setting this flag. You
/// would only need this option in the exceptional cases such as navigating to inaccessible
/// pages. Defaults to <c>false</c>.
/// </para>
/// <para>**DEPRECATED** This option has no effect.</para>
/// <para>This option has no effect.</para>
/// </summary>
[JsonPropertyName("noWaitAfter")]
[System.Obsolete]
@@ -83,7 +83,7 @@ public class PageRouteFromHAROptions
/// <para>
/// When set to <c>minimal</c>, only record information necessary for routing from HAR.
/// This omits sizes, timing, page, cookies, security and other types of HAR information
/// that are not used when replaying from HAR. Defaults to <c>full</c>.
/// that are not used when replaying from HAR. Defaults to <c>minimal</c>.
/// </para>
/// </summary>
[JsonPropertyName("updateMode")]
@@ -55,13 +55,8 @@ public class PageSelectOptionOptions
public bool? Force { get; set; }
/// <summary>
/// <para>**DEPRECATED** This option will default to <c>true</c> in the future.</para>
/// <para>
/// Actions that initiate navigations are waiting for these navigations to happen and
/// for pages to start loading. You can opt out of waiting via setting this flag. You
/// would only need this option in the exceptional cases such as navigating to inaccessible
/// pages. Defaults to <c>false</c>.
/// </para>
/// <para>**DEPRECATED** This option has no effect.</para>
/// <para>This option has no effect.</para>
/// </summary>
[JsonPropertyName("noWaitAfter")]
[System.Obsolete]
@@ -45,14 +45,26 @@ public partial class ClientCertificate
[JsonPropertyName("certPath")]
public string? CertPath { get; set; }
/// <summary><para>Direct value of the certificate in PEM format.</para></summary>
[JsonPropertyName("cert")]
public byte[]? Cert { get; set; }
/// <summary><para>Path to the file with the private key in PEM format.</para></summary>
[JsonPropertyName("keyPath")]
public string? KeyPath { get; set; }
/// <summary><para>Direct value of the private key in PEM format.</para></summary>
[JsonPropertyName("key")]
public byte[]? Key { get; set; }
/// <summary><para>Path to the PFX or PKCS12 encoded private key and certificate chain.</para></summary>
[JsonPropertyName("pfxPath")]
public string? PfxPath { get; set; }
/// <summary><para>Direct value of the PFX or PKCS12 encoded private key and certificate chain.</para></summary>
[JsonPropertyName("pfx")]
public byte[]? Pfx { get; set; }
/// <summary><para>Passphrase for the private key (PEM or PFX).</para></summary>
[JsonPropertyName("passphrase")]
public string? Passphrase { get; set; }
+24 -7
View File
@@ -29,6 +29,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Playwright.Helpers;
using Microsoft.Playwright.Transport;
using Microsoft.Playwright.Transport.Protocol;
@@ -114,12 +115,6 @@ internal class APIRequestContext : ChannelOwner, IAPIRequestContext
{
throw new PlaywrightException("Only one of 'data', 'form' or 'multipart' can be specified");
}
var queryParams = new Dictionary<string, string>();
if (options.Params != null)
{
queryParams = options.Params.ToDictionary(x => x.Key, x => x.Value.ToString());
}
byte[] postData = null;
object jsonData = null;
string dataString = !string.IsNullOrEmpty(options.Data) ? options.Data : options.DataString;
@@ -152,7 +147,7 @@ internal class APIRequestContext : ChannelOwner, IAPIRequestContext
["maxRedirects"] = options?.MaxRedirects,
["maxRetries"] = options?.MaxRetries,
["timeout"] = options.Timeout,
["params"] = queryParams?.ToProtocol(),
["params"] = QueryParamsToProtocol(options.Params, options.ParamsString),
["headers"] = options.Headers?.ToProtocol(),
["jsonData"] = jsonData,
["postData"] = postData != null ? Convert.ToBase64String(postData) : null,
@@ -164,6 +159,28 @@ internal class APIRequestContext : ChannelOwner, IAPIRequestContext
return new APIResponse(this, response?.GetProperty("response").ToObject<Transport.Protocol.APIResponse>());
}
private static IEnumerable<NameValue> QueryParamsToProtocol(IEnumerable<KeyValuePair<string, object>> @params, string paramsString)
{
if (@params != null)
{
return @params.ToDictionary(x => x.Key, x => x.Value.ToString()).ToProtocol();
}
if (string.IsNullOrEmpty(paramsString))
{
return null;
}
var result = new List<NameValue>();
var paramsCollection = HttpUtility.ParseQueryString(paramsString);
foreach (var key in paramsCollection.AllKeys)
{
foreach (var value in paramsCollection.GetValues(key))
{
result.Add(new NameValue { Name = key, Value = value });
}
}
return result;
}
private bool IsJsonContentType(IDictionary<string, string> headers)
{
if (headers == null)
+16 -3
View File
@@ -329,12 +329,25 @@ internal class Browser : ChannelOwner, IBrowser
{
["origin"] = clientCertificate.Origin,
["passphrase"] = clientCertificate.Passphrase,
["cert"] = clientCertificate.CertPath != null ? Convert.ToBase64String(File.ReadAllBytes(clientCertificate.CertPath)) : null,
["key"] = clientCertificate.KeyPath != null ? Convert.ToBase64String(File.ReadAllBytes(clientCertificate.KeyPath)) : null,
["pfx"] = clientCertificate.PfxPath != null ? Convert.ToBase64String(File.ReadAllBytes(clientCertificate.PfxPath)) : null,
["cert"] = ReadClientCertificateFile(clientCertificate.CertPath, clientCertificate.Cert),
["key"] = ReadClientCertificateFile(clientCertificate.KeyPath, clientCertificate.Key),
["pfx"] = ReadClientCertificateFile(clientCertificate.PfxPath, clientCertificate.Pfx),
}
.Where(kv => kv.Value != null)
.ToDictionary(kv => kv.Key, kv => kv.Value))
.ToArray();
}
private static string ReadClientCertificateFile(string path, byte[] value)
{
if (value != null)
{
return Convert.ToBase64String(value);
}
if (path != null)
{
return Convert.ToBase64String(File.ReadAllBytes(path));
}
return null;
}
}
-2
View File
@@ -346,7 +346,6 @@ internal class ElementHandle : JSHandle, IElementHandle
return (await SendMessageToServerAsync("selectOption", new Dictionary<string, object>
{
["options"] = values,
["noWaitAfter"] = noWaitAfter,
["force"] = force,
["timeout"] = timeout,
}).ConfigureAwait(false))?.GetProperty("values").ToObject<string[]>();
@@ -357,7 +356,6 @@ internal class ElementHandle : JSHandle, IElementHandle
return (await SendMessageToServerAsync("selectOption", new Dictionary<string, object>
{
["elements"] = values,
["noWaitAfter"] = noWaitAfter,
["force"] = force,
["timeout"] = timeout,
}).ConfigureAwait(false))?.GetProperty("values").ToObject<string[]>();
-3
View File
@@ -179,9 +179,6 @@ internal class Frame : ChannelOwner, IFrame
{
["selector"] = selector,
["elements"] = values.Select(x => x as ElementHandle),
#pragma warning disable CS0612 // Type or member is obsolete
["noWaitAfter"] = options?.NoWaitAfter,
#pragma warning restore CS0612 // Type or member is obsolete
["strict"] = options?.Strict,
["force"] = options?.Force,
["timeout"] = options?.Timeout,
@@ -37,6 +37,12 @@ internal class PlaywrightInitializer
[JsonPropertyName("webkit")]
public Core.BrowserType Webkit { get; set; }
[JsonPropertyName("bidiChromium")]
public Core.BrowserType BidiChromium { get; set; }
[JsonPropertyName("bidiFirefox")]
public Core.BrowserType BidiFirefox { get; set; }
[JsonPropertyName("utils")]
public Core.LocalUtils Utils { get; set; }