.NET version of the Playwright testing and automation library.
Playwright now supports Debian 12 Bookworm on both x86_64 and arm64 for Chromium, Firefox and WebKit. Let us know if you encounter any issues!
Linux support looks like this:
Ubuntu 20.04 | Ubuntu 22.04 | Debian 11 | Debian 12 | |
---|---|---|---|---|
Chromium | ✅ | ✅ | ✅ | ✅ |
WebKit | ✅ | ✅ | ✅ | ✅ |
Firefox | ✅ | ✅ | ✅ | ✅ |
This version was also tested against the following stable channels:
New option MaskColor
for methods Page.screenshot()
and Locator.screenshot()
to change default masking color.
New uninstall
CLI command to uninstall browser binaries:
$ pwsh bin/Debug/netX/playwright.ps1 uninstall # remove browsers installed by this installation
$ pwsh bin/Debug/netX/playwright.ps1 uninstall --all # remove all ever-install Playwright browsers
This version was also tested against the following stable channels:
New Locator.And
to create a locator that matches both locators.
var button = page.GetByRole(AriaRole.Button).And(page.GetByTitle("Subscribe"));
New events BrowserContext.Console
and BrowserContext.Dialog
to subscribe to any dialogs
and console messages from any page from the given browser context. Use the new methods ConsoleMessage.Page
and Dialog.Page
to pin-point event source.
This version was also tested against the following stable channels:
Use Locator.Or
to create a locator that matches either of the two locators.
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:
var newEmail = page.GetByRole(AriaRole.Button, new() { Name = "New" });
var dialog = page.GetByText("Confirm security settings");
await Expect(newEmail.Or(dialog)).ToBeVisibleAsync();
if (await dialog.IsVisibleAsync())
await page.GetByRole(AriaRole.Button, new() { Name = "Dismiss" }).ClickAsync();
await newEmail.ClickAsync();
Use new options HasNot
and HasNotText
in Locator.Filter
to find elements that do not match certain conditions.
var rowLocator = page.Locator("tr");
await rowLocator
.Filter(new() { HasNotText = "text in column 1" })
.Filter(new() { HasNot = page.GetByRole(AriaRole.Button, new() { Name = "column 2 button" }))
.ScreenshotAsync();
Use new web-first assertion Expect().ToBeAttachedAsync()
to ensure that the element
is present in the page's DOM. Do not confuse with the Expect().ToBeVisibleAsync()
that ensures that
element is both attached & visible.
Locator.Or
HasNot
in Locator.Filter
HasNotText
in Locator.Filter
Expect().ToBeAttachedAsync
Timeout
in Route.FetchAsync
mcr.microsoft.com/playwright/dotnet:v1.33.0
now serves a Playwright image based on Ubuntu Jammy.
To use the focal-based image, please use mcr.microsoft.com/playwright/dotnet:v1.33.0-focal
instead.This version was also tested against the following stable channels:
UpdateMode
and UpdateContent
in Page.RouteFromHARAsync()
and BrowserContext.RouteFromHARAsync()
.Name
in method Tracing.StartChunkAsync()
.This version was also tested against the following stable channels:
https://github.com/microsoft/playwright/issues/21093 - [Regression v1.31] Headless Windows shows cascading cmd windows
This version was also tested against the following stable channels:
New assertion Expect(locator).ToBeInViewportAsync()
ensures that locator points to an element that intersects viewport, according to the intersection observer API.
var locator = Page.GetByRole(AriaRole.Button);
// Make sure at least some part of element intersects viewport.
await Expect(locator).ToBeInViewportAsync();
// Make sure element is fully outside of viewport.
await Expect(locator).Not.ToBeInViewportAsync();
// Make sure that at least half of the element intersects viewport.
await Expect(locator).ToBeInViewportAsync(new() { Ratio = 0.5 });
New methods BrowserContext.NewCDPSessionAsync(Page)
and Browser.NewBrowserCDPSessionAsync()
create a Chrome DevTools Protocol session for the page and browser respectively.
MaxRedirects
for method Route.FetchAsync
.This version was also tested against the following stable channels:
New method Route.FetchAsync
and new option Json
for Route.FulfillAsync
:
await Page.RouteAsync("**/api/settings", async route => {
// Fetch original settings.
var response = await route.FetchAsync();
// Force settings theme to a predefined value.
var json = await response.JsonAsync<MyDataType>();
json.Theme = "Solarized";
// Fulfill with modified data.
await route.FulfillAsync(new() {
Json = json
});
});
New method Locator.AllAsync
to iterate over all matching elements:
// Check all checkboxes!
var checkboxes = Page.Locator("role=checkbox");
foreach (var checkbox in await checkboxes.AllAsync())
await checkbox.CheckAsync();
Locator.SelectOptionAsync
matches now by value or label:
<select multiple>
<option value="red">Red</div>
<option value="green">Green</div>
<option value="blue">Blue</div>
</select>
await element.SelectOptionAsync("Red");
This version was also tested against the following stable channels: