Python version of the Playwright testing and automation library.
New option mask_color
for methods Page.screenshot()
and Locator.screenshot()
to change default masking color.
New uninstall
CLI command to uninstall browser binaries:
$ playwright uninstall # remove browsers installed by this installation
$ playwright 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.
button = page.get_by_role("button").and_(page.get_by_title("Subscribe"))
Its now possible to set a global expect timeout and change the 5 second default:
from playwright.sync_api import expect
expect.set_options(timeout=10_000)
New events BrowserContext.on("console")
and BrowserContext.on("dialog")
to subscribe to any dialogs
and console messages from any page from the given browser context. Use the new properties 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:
new_email = page.get_by_role("button", name="New email")
dialog = page.get_by_text("Confirm security settings")
expect(new_email.or_(dialog)).is_visible()
if (dialog.is_visible())
page.get_by_role("button", name="Dismiss").click()
new_email.click()
Use new options has_not
and has_not_text
in Locator.filter
to find elements that do not match certain conditions.
row_locator = page.locator("tr")
row_locator
.filter(has_not_text="text in column 1")
.filter(has_not=page.get_by_role("button", name="column 2 button"))
.screenshot()
Use new web-first assertion expect(locator).to_be_attached()
to ensure that the element
is present in the page's DOM. Do not confuse with the expect(locator).to_be_visible()
that ensures that
element is both attached & visible.
Locator.or
has_not
in Locator.filter
has_not_text
in Locator.filter
expect(locator).to_be_attached
timeout
in method: Route.fetch
mcr.microsoft.com/playwright/python:v1.33.0
now serves a Playwright image based on Ubuntu Jammy.
To use the focal-based image, please use mcr.microsoft.com/playwright/python:v1.33.0-focal
instead.This version was also tested against the following stable channels:
update_mode
and update_content
in page.route_from_har()
and browser_context.route_from_har()
.name
in method tracing.start_chunk()
.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).to_be_in_viewport()
ensures that locator points to an element that intersects viewport, according to the intersection observer API.
from playwright.sync_api import expect
locator = page.get_by_role("button")
# Make sure at least some part of element intersects viewport.
expect(locator).to_be_in_viewport()
# Make sure element is fully outside of viewport.
expect(locator).not_to_be_in_viewport()
# Make sure that at least half of the element intersects viewport.
expect(locator).to_be_in_viewport(ratio=0.5)
max_redirects
for method Route.fetch
.This version was also tested against the following stable channels:
New method Route.fetch
and new option json
for Route.fulfill
:
def handle_route(route: Route):
# Fetch original settings.
response = route.fetch()
# Force settings theme to a predefined value.
json = response.json()
json["theme"] = "Solorized"
# Fulfill with modified data.
route.fulfill(json=json)
page.route("**/api/settings", handle_route)
New method Locator.all
to iterate over all matching elements:
# Check all checkboxes!
checkboxes = page.get_by_role("checkbox")
for checkbox in checkboxes.all():
checkbox.check()
Locator.select_option
matches now by value or label:
<select multiple>
<option value="red">Red</div>
<option value="green">Green</div>
<option value="blue">Blue</div>
</select>
element.select_option("Red")
postData
in method Route.continue
now supports any values.This version was also tested against the following stable channels: