Skip to content
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 -->109.0.5414.46<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Chromium <!-- GEN:chromium-version -->110.0.5481.38<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| WebKit <!-- GEN:webkit-version -->16.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->107.0<!-- GEN:stop --> | ✅ | ✅ | ✅ |
| Firefox <!-- GEN:firefox-version -->108.0.2<!-- 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.29.0</AssemblyVersion>
<PackageVersion>$(AssemblyVersion)</PackageVersion>
<DriverVersion>1.29.1</DriverVersion>
<DriverVersion>1.30.0-beta-1674276599000</DriverVersion>
<ReleaseVersion>$(AssemblyVersion)</ReleaseVersion>
<FileVersion>$(AssemblyVersion)</FileVersion>
<NoDefaultExcludes>true</NoDefaultExcludes>
Expand Down
4 changes: 2 additions & 2 deletions src/Playwright.Tests/GlobalFetchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ public async Task ShouldSupportGlobalUserAgentOption()
[PlaywrightTest("global-fetch.spec.ts", "should support global timeout option")]
public async Task ShouldSupportGlobalTimeoutOption()
{
var request = await Playwright.APIRequest.NewContextAsync(new() { Timeout = 1 });
var request = await Playwright.APIRequest.NewContextAsync(new() { Timeout = 100 });
Server.SetRoute("/empty.html", async request => await Task.Delay(5_000));
var exception = Assert.ThrowsAsync<PlaywrightException>(() => request.GetAsync(Server.EmptyPage));
StringAssert.Contains("Request timed out after 1ms", exception.Message);
StringAssert.Contains("Request timed out after 100ms", exception.Message);
}

[PlaywrightTest("global-fetch.spec.ts", "should propagate extra http headers with redirects")]
Expand Down
3 changes: 1 addition & 2 deletions src/Playwright.Tests/PageWaitForSelector1Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public async Task ElementHandleWaitForSelectorShouldThrowOnNavigation()

await Page.GotoAsync(Server.EmptyPage);
var exception = await PlaywrightAssert.ThrowsAsync<PlaywrightException>(() => task);
StringAssert.Contains("Error: frame navigated while waiting for Locator(\"span\")", exception.Message);
StringAssert.Contains("waiting for Locator(\"span\") to be visible", exception.Message);
}

[PlaywrightTest("page-wait-for-selector-1.spec.ts", "should work with removed MutationObserver")]
Expand Down Expand Up @@ -146,7 +146,6 @@ await frame.EvaluateAsync(@"() => {
StringAssert.Contains("Timeout 5000ms", exception.Message);
StringAssert.Contains("waiting for Locator(\"div\") to be visible", exception.Message);
StringAssert.Contains("locator resolved to hidden <div id=\"mydiv\" class=\"foo bar\" foo=\"1234567890123456…>abcdefghijklmnopqrstuvwyxzabcdefghijklmnopqrstuvw…</div>", exception.Message);
StringAssert.Contains("locator did not resolve to any element", exception.Message);
StringAssert.Contains("locator resolved to hidden <div class=\"another\"></div>", exception.Message);
}

Expand Down
4 changes: 4 additions & 0 deletions src/Playwright.Tests/PermissionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,11 @@ await Page.EvaluateAsync(@"() => {
new[] { "prompt", "denied", "granted" },
await Page.EvaluateAsync<string[]>("window.events"));
await Context.ClearPermissionsAsync();

// Note: Chromium 110 stopped triggering "onchange" when clearing permissions.
Assert.AreEqual(
(BrowserName == "chromium" && BrowserMajorVersion >= 110) ?
new[] { "prompt", "denied", "granted" } :
new[] { "prompt", "denied", "granted", "prompt" },
await Page.EvaluateAsync<string[]>("window.events"));
}
Expand Down
157 changes: 104 additions & 53 deletions src/Playwright/API/Generated/IFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -534,60 +534,76 @@ public partial interface IFrame
Task<string?> GetAttributeAsync(string selector, string name, FrameGetAttributeOptions? options = default);

/// <summary>
/// <para>
/// Allows locating elements by their alt text. For example, this method will find the
/// image by alt text "Castle":
/// </para>
/// <para>Allows locating elements by their alt text.</para>
/// <para>**Usage**</para>
/// <para>For example, this method will find the image by alt text "Playwright logo":</para>
/// <code>await page.GetByAltText("Playwright logo").ClickAsync();</code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByAltText(string text, FrameGetByAltTextOptions? options = default);

/// <summary>
/// <para>
/// Allows locating elements by their alt text. For example, this method will find the
/// image by alt text "Castle":
/// </para>
/// <para>Allows locating elements by their alt text.</para>
/// <para>**Usage**</para>
/// <para>For example, this method will find the image by alt text "Playwright logo":</para>
/// <code>await page.GetByAltText("Playwright logo").ClickAsync();</code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByAltText(Regex text, FrameGetByAltTextOptions? options = default);

/// <summary>
/// <para>Allows locating input elements by the text of the associated label.</para>
/// <para>**Usage**</para>
/// <para>
/// Allows locating input elements by the text of the associated label. For example,
/// this method will find the input by label text "Password" in the following DOM:
/// For example, this method will find the input by label text "Password" in the following
/// DOM:
/// </para>
/// <code>await page.GetByLabel("Password").FillAsync("secret");</code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByLabel(string text, FrameGetByLabelOptions? options = default);

/// <summary>
/// <para>Allows locating input elements by the text of the associated label.</para>
/// <para>**Usage**</para>
/// <para>
/// Allows locating input elements by the text of the associated label. For example,
/// this method will find the input by label text "Password" in the following DOM:
/// For example, this method will find the input by label text "Password" in the following
/// DOM:
/// </para>
/// <code>await page.GetByLabel("Password").FillAsync("secret");</code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByLabel(Regex text, FrameGetByLabelOptions? options = default);

/// <summary>
/// <para>
/// Allows locating input elements by the placeholder text. For example, this method
/// will find the input by placeholder "Country":
/// </para>
/// <para>Allows locating input elements by the placeholder text.</para>
/// <para>**Usage**</para>
/// <para>For example, consider the following DOM structure.</para>
/// <para>You can fill the input after locating it by the placeholder text:</para>
/// <code>
/// await page<br/>
/// .GetByPlaceholder("name@example.com")<br/>
/// .FillAsync("playwright@microsoft.com");
/// </code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByPlaceholder(string text, FrameGetByPlaceholderOptions? options = default);

/// <summary>
/// <para>
/// Allows locating input elements by the placeholder text. For example, this method
/// will find the input by placeholder "Country":
/// </para>
/// <para>Allows locating input elements by the placeholder text.</para>
/// <para>**Usage**</para>
/// <para>For example, consider the following DOM structure.</para>
/// <para>You can fill the input after locating it by the placeholder text:</para>
/// <code>
/// await page<br/>
/// .GetByPlaceholder("name@example.com")<br/>
/// .FillAsync("playwright@microsoft.com");
/// </code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
Expand All @@ -598,11 +614,32 @@ public partial interface IFrame
/// Allows locating elements by their <a href="https://www.w3.org/TR/wai-aria-1.2/#roles">ARIA
/// role</a>, <a href="https://www.w3.org/TR/wai-aria-1.2/#aria-attributes">ARIA attributes</a>
/// and <a href="https://w3c.github.io/accname/#dfn-accessible-name">accessible name</a>.
/// Note that role selector **does not replace** accessibility audits and conformance
/// tests, but rather gives early feedback about the ARIA guidelines.
/// </para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure.</para>
/// <para>You can locate each element by it's implicit role:</para>
/// <code>
/// await Expect(page<br/>
/// .GetByRole(AriaRole.Heading, new() { Name = "Sign up" }))<br/>
/// .ToBeVisibleAsync();<br/>
/// <br/>
/// await page<br/>
/// .GetByRole(AriaRole.Checkbox, new() { Name = "Subscribe" })<br/>
/// .CheckAsync();<br/>
/// <br/>
/// await page<br/>
/// .GetByRole(AriaRole.Button, new() {<br/>
/// NameRegex = new Regex("submit", RegexOptions.IgnoreCase)<br/>
/// })<br/>
/// .ClickAsync();
/// </code>
/// <para>**Details**</para>
/// <para>
/// Note that many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
/// Role selector **does not replace** accessibility audits and conformance tests, but
/// rather gives early feedback about the ARIA guidelines.
/// </para>
/// <para>
/// Many html elements have an implicitly <a href="https://w3c.github.io/html-aam/#html-element-role-mappings">defined
/// role</a> that is recognized by the role selector. You can find all the <a href="https://www.w3.org/TR/wai-aria-1.2/#role_definitions">supported
/// roles here</a>. ARIA guidelines **do not recommend** duplicating implicit roles
/// and attributes by setting <c>role</c> and/or <c>aria-*</c> attributes to default
Expand All @@ -614,27 +651,43 @@ public partial interface IFrame
ILocator GetByRole(AriaRole role, FrameGetByRoleOptions? options = default);

/// <summary>
/// <para>Locate element by the test id.</para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure.</para>
/// <para>You can locate the element by it's test id:</para>
/// <code>await page.GetByTestId("directions").ClickAsync();</code>
/// <para>**Details**</para>
/// <para>
/// Locate element by the test id. By default, the <c>data-testid</c> attribute is used
/// as a test id. Use <see cref="ISelectors.SetTestIdAttribute"/> to configure a different
/// test id attribute if necessary.
/// By default, the <c>data-testid</c> attribute is used as a test id. Use <see cref="ISelectors.SetTestIdAttribute"/>
/// to configure a different test id attribute if necessary.
/// </para>
/// </summary>
/// <param name="testId">Id to locate the element by.</param>
ILocator GetByTestId(string testId);

/// <summary>
/// <para>Locate element by the test id.</para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure.</para>
/// <para>You can locate the element by it's test id:</para>
/// <code>await page.GetByTestId("directions").ClickAsync();</code>
/// <para>**Details**</para>
/// <para>
/// Locate element by the test id. By default, the <c>data-testid</c> attribute is used
/// as a test id. Use <see cref="ISelectors.SetTestIdAttribute"/> to configure a different
/// test id attribute if necessary.
/// By default, the <c>data-testid</c> attribute is used as a test id. Use <see cref="ISelectors.SetTestIdAttribute"/>
/// to configure a different test id attribute if necessary.
/// </para>
/// </summary>
/// <param name="testId">Id to locate the element by.</param>
ILocator GetByTestId(Regex testId);

/// <summary>
/// <para>Allows locating elements that contain given text. Consider the following DOM structure:</para>
/// <para>Allows locating elements that contain given text.</para>
/// <para>
/// See also <see cref="ILocator.Filter"/> that allows to match by another criteria,
/// like an accessible role, and then filter by the text content.
/// </para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure:</para>
/// <para>You can locate by text substring, exact string, or a regular expression:</para>
/// <code>
/// // Matches &lt;span&gt;<br/>
Expand All @@ -652,12 +705,7 @@ public partial interface IFrame
/// // Matches second &lt;div&gt;<br/>
/// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase))
/// </code>
/// <para>
/// See also <see cref="ILocator.Filter"/> that allows to match by another criteria,
/// like an accessible role, and then filter by the text content.
/// </para>
/// </summary>
/// <remarks>
/// <para>**Details**</para>
/// <para>
/// Matching by text always normalizes whitespace, even with exact match. For example,
/// it turns multiple spaces into one, turns line breaks into spaces and ignores leading
Expand All @@ -668,13 +716,19 @@ public partial interface IFrame
/// <c>value</c> instead of the text content. For example, locating by text <c>"Log
/// in"</c> matches <c>&lt;input type=button value="Log in"&gt;</c>.
/// </para>
/// </remarks>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByText(string text, FrameGetByTextOptions? options = default);

/// <summary>
/// <para>Allows locating elements that contain given text. Consider the following DOM structure:</para>
/// <para>Allows locating elements that contain given text.</para>
/// <para>
/// See also <see cref="ILocator.Filter"/> that allows to match by another criteria,
/// like an accessible role, and then filter by the text content.
/// </para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure:</para>
/// <para>You can locate by text substring, exact string, or a regular expression:</para>
/// <code>
/// // Matches &lt;span&gt;<br/>
Expand All @@ -692,12 +746,7 @@ public partial interface IFrame
/// // Matches second &lt;div&gt;<br/>
/// page.GetByText(new Regex("^hello$", RegexOptions.IgnoreCase))
/// </code>
/// <para>
/// See also <see cref="ILocator.Filter"/> that allows to match by another criteria,
/// like an accessible role, and then filter by the text content.
/// </para>
/// </summary>
/// <remarks>
/// <para>**Details**</para>
/// <para>
/// Matching by text always normalizes whitespace, even with exact match. For example,
/// it turns multiple spaces into one, turns line breaks into spaces and ignores leading
Expand All @@ -708,26 +757,28 @@ public partial interface IFrame
/// <c>value</c> instead of the text content. For example, locating by text <c>"Log
/// in"</c> matches <c>&lt;input type=button value="Log in"&gt;</c>.
/// </para>
/// </remarks>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByText(Regex text, FrameGetByTextOptions? options = default);

/// <summary>
/// <para>
/// Allows locating elements by their title. For example, this method will find the
/// button by its title "Place the order":
/// </para>
/// <para>Allows locating elements by their title attribute.</para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure.</para>
/// <para>You can check the issues count after locating it by the title text:</para>
/// <code>await Expect(page.GetByTitle("Issues count")).toHaveText("25 issues");</code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
ILocator GetByTitle(string text, FrameGetByTitleOptions? options = default);

/// <summary>
/// <para>
/// Allows locating elements by their title. For example, this method will find the
/// button by its title "Place the order":
/// </para>
/// <para>Allows locating elements by their title attribute.</para>
/// <para>**Usage**</para>
/// <para>Consider the following DOM structure.</para>
/// <para>You can check the issues count after locating it by the title text:</para>
/// <code>await Expect(page.GetByTitle("Issues count")).toHaveText("25 issues");</code>
/// </summary>
/// <param name="text">Text to locate the element for.</param>
/// <param name="options">Call options</param>
Expand Down
Loading