Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(roll): roll Playwright to v1.50 #3100

Merged
merged 3 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->131.0.6778.33<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Chromium <!-- GEN:chromium-version -->133.0.6943.16<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| WebKit <!-- GEN:webkit-version -->18.2<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->132.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->134.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**.

Expand Down
2 changes: 1 addition & 1 deletion src/Common/Version.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyVersion>1.50.0</AssemblyVersion>
<PackageVersion>$(AssemblyVersion)-beta-2</PackageVersion>
<DriverVersion>1.49.0</DriverVersion>
<DriverVersion>1.50.0-beta-1737762224000</DriverVersion>
<ReleaseVersion>$(AssemblyVersion)</ReleaseVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<NoDefaultExcludes>true</NoDefaultExcludes>
Expand Down
6 changes: 5 additions & 1 deletion src/Playwright.TestingHarnessTest/tests/mstest/basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ test('should be able to parse LaunchOptions.Proxy from runsettings', async ({ ru
}).listen(3128);

const waitForProxyRequest = new Promise<[string, string]>((resolve) => {
proxyServer.once('proxyReq', (proxyReq, req, res, options) => {
proxyServer.on('proxyReq', (proxyReq, req, res, options) => {
if (req.url.includes('google.com')) // Telemetry requests.
{
return;
}
const authHeader = proxyReq.getHeader('authorization') as string;
const auth = Buffer.from(authHeader.split(' ')[1], 'base64').toString();
resolve([req.url, auth]);
Expand Down
63 changes: 63 additions & 0 deletions src/Playwright.Tests/Assertions/LocatorAssertionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,32 @@ public async Task ShouldSupportToBeChecked()
StringAssert.Contains("LocatorAssertions.ToBeCheckedAsync with timeout 300ms", exception.Message);
}

[PlaywrightTest("tests/page/expect-boolean.spec.ts", "with indeterminate:true")]
public async Task WithIndeterminateTrue()
{
await Page.SetContentAsync("<input type=checkbox></input>");
await Page.Locator("input").EvaluateAsync("e => e.indeterminate = true");
await Expect(Page.Locator("input")).ToBeCheckedAsync(new() { Indeterminate = true });
}

[PlaywrightTest("tests/page/expect-boolean.spec.ts", "with indeterminate:true and checked")]
public async Task WithIndeterminateTrueAndChecked()
{
await Page.SetContentAsync("<input type=checkbox></input>");
await Page.Locator("input").EvaluateAsync("e => e.indeterminate = true");
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => Expect(Page.Locator("input")).ToBeCheckedAsync(new() { Indeterminate = true, Checked = false }));
StringAssert.Contains("Can't assert indeterminate and checked at the same time", exception.Message);
}

[PlaywrightTest("tests/page/expect-boolean.spec.ts", "fail with indeterminate: true")]
public async Task FailWithIndeterminateTrue()
{
await Page.SetContentAsync("<input type=checkbox></input>");
var locator = Page.Locator("input");
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => Expect(locator).ToBeCheckedAsync(new() { Indeterminate = true, Timeout = 1000 }));
StringAssert.Contains("LocatorAssertions.ToBeCheckedAsync with timeout 1000ms", exception.Message);
}

[PlaywrightTest("playwright-test/playwright.expect.spec.ts", "should be able to set default timeout")]
public async Task ShouldBeAbleToSetDefaultTimeout()
{
Expand Down Expand Up @@ -720,6 +746,43 @@ public async Task ToHaveAccessibleDescription()
await Expect(Page.Locator("div")).ToHaveAccessibleDescriptionAsync(new Regex("hello"), new() { IgnoreCase = true });
}

[PlaywrightTest("page/expect-misc.spec.ts", "toHaveAccessibleErrorMessage")]
public async Task ToHaveAccessibleErrorMessage()
{
await Page.SetContentAsync(@"
<form>
<input role=""textbox"" aria-invalid=""true"" aria-errormessage=""error-message"" />
<div id=""error-message"">Hello</div>
<div id=""irrelevant-error"">This should not be considered.</div>
</form>");
var locator = Page.Locator("input[role=\"textbox\"]");
await Expect(locator).ToHaveAccessibleErrorMessageAsync("Hello");
await Expect(locator).Not.ToHaveAccessibleErrorMessageAsync("hello");
await Expect(locator).ToHaveAccessibleErrorMessageAsync("hello", new() { IgnoreCase = true });
await Expect(locator).ToHaveAccessibleErrorMessageAsync(new Regex(@"ell\w"));
await Expect(locator).Not.ToHaveAccessibleErrorMessageAsync(new Regex("hello"));
await Expect(locator).ToHaveAccessibleErrorMessageAsync(new Regex("hello"), new() { IgnoreCase = true });
await Expect(locator).Not.ToHaveAccessibleErrorMessageAsync("This should not be considered.");
}


[PlaywrightTest("page/expect-misc.spec.ts", "toHaveAccessibleErrorMessage should handle multiple aria-errormessage reference")]
public async Task ToHaveAccessibleErrorMessageShouldHandleMultipleAriaErrormessageReference()
{
await Page.SetContentAsync(@"
<form>
<input role=""textbox"" aria-invalid=""true"" aria-errormessage=""error1 error2"" />
<div id=""error1"">First error message.</div>
<div id=""error2"">Second error message.</div>
<div id=""irrelevant-error"">This should not be considered.</div>
</form>");
var locator = Page.Locator("input[role=\"textbox\"]");
await Expect(locator).ToHaveAccessibleErrorMessageAsync("First error message. Second error message.");
await Expect(locator).ToHaveAccessibleErrorMessageAsync(new Regex("first error message.", RegexOptions.IgnoreCase));
await Expect(locator).ToHaveAccessibleErrorMessageAsync(new Regex("second error message.", RegexOptions.IgnoreCase));
await Expect(locator).Not.ToHaveAccessibleErrorMessageAsync(new Regex("This should not be considered.", RegexOptions.IgnoreCase));
}

[PlaywrightTest("page/expect-misc.spec.ts", "toHaveRole")]
public async Task ToHaveRole()
{
Expand Down
14 changes: 8 additions & 6 deletions src/Playwright/API/Generated/IBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ public partial interface IBrowser
/// browser and disconnects from the browser server.
/// </para>
/// <para>
/// This is similar to force quitting the browser. Therefore, you should call <see cref="IBrowserContext.CloseAsync"/>
/// on any <see cref="IBrowserContext"/>'s you explicitly created earlier with <see
/// cref="IBrowser.NewContextAsync"/> **before** calling <see cref="IBrowser.CloseAsync"/>.
/// This is similar to force-quitting the browser. To close pages gracefully and ensure
/// you receive page close events, call <see cref="IBrowserContext.CloseAsync"/> on
/// any <see cref="IBrowserContext"/> instances you explicitly created earlier using
/// <see cref="IBrowser.NewContextAsync"/> **before** calling <see cref="IBrowser.CloseAsync"/>.
/// </para>
/// <para>
/// The <see cref="IBrowser"/> object itself is considered to be disposed and cannot
Expand All @@ -84,9 +85,10 @@ public partial interface IBrowser
/// </summary>
/// <remarks>
/// <para>
/// This is similar to force quitting the browser. Therefore, you should call <see cref="IBrowserContext.CloseAsync"/>
/// on any <see cref="IBrowserContext"/>'s you explicitly created earlier with <see
/// cref="IBrowser.NewContextAsync"/> **before** calling <see cref="IBrowser.CloseAsync"/>.
/// This is similar to force-quitting the browser. To close pages gracefully and ensure
/// you receive page close events, call <see cref="IBrowserContext.CloseAsync"/> on
/// any <see cref="IBrowserContext"/> instances you explicitly created earlier using
/// <see cref="IBrowser.NewContextAsync"/> **before** calling <see cref="IBrowser.CloseAsync"/>.
///
/// </para>
/// </remarks>
Expand Down
9 changes: 5 additions & 4 deletions src/Playwright/API/Generated/IBrowserContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,12 @@ public partial interface IBrowserContext
/// </para>
/// </summary>
/// <param name="permissions">
/// A permission or an array of permissions to grant. Permissions can be one of the
/// following values:
/// A list of permissions to grant.
/// Supported permissions differ between browsers, and even between different versions
/// of the same browser. Any permission may stop working after an update.
/// Here are some permissions that may be supported by some browsers:
/// <list type="bullet">
/// <item><description><c>'accelerometer'</c></description></item>
/// <item><description><c>'accessibility-events'</c></description></item>
/// <item><description><c>'ambient-light-sensor'</c></description></item>
/// <item><description><c>'background-sync'</c></description></item>
/// <item><description><c>'camera'</c></description></item>
Expand Down Expand Up @@ -862,7 +863,7 @@ public partial interface IBrowserContext
/// <see cref="IBrowserContext.SetDefaultTimeout"/>.
/// </para>
/// </remarks>
/// <param name="timeout">Maximum time in milliseconds</param>
/// <param name="timeout">Maximum time in milliseconds. Pass <c>0</c> to disable timeout.</param>
void SetDefaultTimeout(float timeout);

/// <summary>
Expand Down
12 changes: 12 additions & 0 deletions src/Playwright/API/Generated/IClock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ public partial interface IClock
/// await page.Clock.PauseAtAsync(DateTime.Parse("2020-02-02"));<br/>
/// await page.Clock.PauseAtAsync("2020-02-02");
/// </code>
/// <para>
/// For best results, install the clock before navigating the page and set it to a time
/// slightly before the intended test time. This ensures that all timers run normally
/// during page loading, preventing the page from getting stuck. Once the page has fully
/// loaded, you can safely use <see cref="IClock.PauseAtAsync"/> to pause the clock.
/// </para>
/// </summary>
/// <param name="time">Time to pause at.</param>
Task PauseAtAsync(DateTime time);
Expand All @@ -168,6 +174,12 @@ public partial interface IClock
/// await page.Clock.PauseAtAsync(DateTime.Parse("2020-02-02"));<br/>
/// await page.Clock.PauseAtAsync("2020-02-02");
/// </code>
/// <para>
/// For best results, install the clock before navigating the page and set it to a time
/// slightly before the intended test time. This ensures that all timers run normally
/// during page loading, preventing the page from getting stuck. Once the page has fully
/// loaded, you can safely use <see cref="IClock.PauseAtAsync"/> to pause the clock.
/// </para>
/// </summary>
/// <param name="time">Time to pause at.</param>
Task PauseAtAsync(string time);
Expand Down
27 changes: 23 additions & 4 deletions src/Playwright/API/Generated/ILocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,12 @@ public partial interface ILocator
Task<bool> IsDisabledAsync(LocatorIsDisabledOptions? options = default);

/// <summary>
/// <para>Returns whether the element is <a href="https://playwright.dev/dotnet/docs/actionability#editable">editable</a>.</para>
/// <para>
/// Returns whether the element is <a href="https://playwright.dev/dotnet/docs/actionability#editable">editable</a>.
/// If the target element is not an <c>&lt;input&gt;</c>, <c>&lt;textarea&gt;</c>, <c>&lt;select&gt;</c>,
/// <c>[contenteditable]</c> and does not have a role allowing <c>[aria-readonly]</c>,
/// this method throws an error.
/// </para>
/// <para>
/// If you need to assert that an element is editable, prefer <see cref="ILocatorAssertions.ToBeEditableAsync"/>
/// to avoid flakiness. See <a href="https://playwright.dev/dotnet/docs/test-assertions">assertions
Expand Down Expand Up @@ -1157,24 +1162,38 @@ public partial interface ILocator
/// <para>Creates a locator matching all elements that match one or both of the two locators.</para>
/// <para>
/// Note that when both locators match something, the resulting locator will have multiple
/// matches and violate <a href="https://playwright.dev/dotnet/docs/locators#strictness">locator
/// strictness</a> guidelines.
/// matches, potentially causing a <a href="https://playwright.dev/dotnet/docs/locators#strictness">locator
/// strictness</a> violation.
/// </para>
/// <para>**Usage**</para>
/// <para>
/// Consider a scenario where you'd like to click on a "New email" button, but sometimes
/// a security settings dialog shows up instead. In this case, you can wait for either
/// a "New email" button, or a dialog and act accordingly.
/// </para>
/// <para>
/// If both "New email" button and security dialog appear on screen, the "or" locator
/// will match both of them, possibly throwing the <a href="https://playwright.dev/dotnet/docs/locators#strictness">"strict
/// mode violation" error</a>. In this case, you can use <see cref="ILocator.First"/>
/// to only match one of them.
/// </para>
/// <code>
/// var newEmail = page.GetByRole(AriaRole.Button, new() { Name = "New" });<br/>
/// var dialog = page.GetByText("Confirm security settings");<br/>
/// await Expect(newEmail.Or(dialog)).ToBeVisibleAsync();<br/>
/// await Expect(newEmail.Or(dialog).First).ToBeVisibleAsync();<br/>
/// if (await dialog.IsVisibleAsync())<br/>
/// await page.GetByRole(AriaRole.Button, new() { Name = "Dismiss" }).ClickAsync();<br/>
/// await newEmail.ClickAsync();
/// </code>
/// </summary>
/// <remarks>
/// <para>
/// If both "New email" button and security dialog appear on screen, the "or" locator
/// will match both of them, possibly throwing the <a href="https://playwright.dev/dotnet/docs/locators#strictness">"strict
/// mode violation" error</a>. In this case, you can use <see cref="ILocator.First"/>
/// to only match one of them.
/// </para>
/// </remarks>
/// <param name="locator">Alternative locator to match.</param>
ILocator Or(ILocator locator);

Expand Down
Loading
Loading