--- id: release-notes title: "Release notes" toc_max_heading_level: 2 --- ## Version 1.26 ### Assertions - New option `enabled` for [`method: LocatorAssertions.toBeEnabled`]. - [`method: LocatorAssertions.toHaveText`] now pierces open shadow roots. - New option `editable` for [`method: LocatorAssertions.toBeEditable`]. - New option `visible` for [`method: LocatorAssertions.toBeVisible`]. ### Other highlights - New option `max_redirects` for [`method: APIRequestContext.get`] and others to limit redirect count. - Python 3.11 is now supported. ### Behavior Change A bunch of Playwright APIs already support the `wait_until: "domcontentloaded"` option. For example: ```python page.goto("https://playwright.dev", wait_until="domcontentloaded") ``` Prior to 1.26, this would wait for all iframes to fire the `DOMContentLoaded` event. To align with web specification, the `'domcontentloaded'` value only waits for the target frame to fire the `'DOMContentLoaded'` event. Use `wait_until="load"` to wait for all iframes. ### Browser Versions * Chromium 106.0.5249.30 * Mozilla Firefox 104.0 * WebKit 16.0 This version was also tested against the following stable channels: * Google Chrome 105 * Microsoft Edge 105 ## Version 1.25 ### Announcements * 🎁 We now ship Ubuntu 22.04 Jammy Jellyfish docker image: `mcr.microsoft.com/playwright/python:v1.27.0-jammy`. * ðŸŠĶ This is the last release with macOS 10.15 support (deprecated as of 1.21). * ⚠ïļ Ubuntu 18 is now deprecated and will not be supported as of Dec 2022. ### Browser Versions * Chromium 105.0.5195.19 * Mozilla Firefox 103.0 * WebKit 16.0 This version was also tested against the following stable channels: * Google Chrome 104 * Microsoft Edge 104 ## Version 1.24
### 🐂 Debian 11 Bullseye Support Playwright now supports Debian 11 Bullseye on x86_64 for Chromium, Firefox and WebKit. Let us know if you encounter any issues! Linux support looks like this: | | Ubuntu 18.04 | Ubuntu 20.04 | Ubuntu 22.04 | Debian 11 | :--- | :---: | :---: | :---: | :---: | | Chromium | ✅ | ✅ | ✅ | ✅ | | WebKit | ✅ | ✅ | ✅ | ✅ | | Firefox | ✅ | ✅ | ✅ | ✅ | ### New introduction docs We rewrote our Getting Started docs to be more end-to-end testing focused. Check them out on [playwright.dev](https://playwright.dev/python/docs/intro). ## Version 1.23 ### Network Replay Now you can record network traffic into a HAR file and re-use this traffic in your tests. To record network into HAR file: ```bash npx playwright open --save-har=github.har.zip https://github.com/microsoft ``` Alternatively, you can record HAR programmatically: ```python async context = await browser.new_context(record_har_path="github.har.zip") # ... do stuff ... await context.close() ``` ```python sync context = browser.new_context(record_har_path="github.har.zip") # ... do stuff ... context.close() ``` Use the new methods [`method: Page.routeFromHAR`] or [`method: BrowserContext.routeFromHAR`] to serve matching responses from the [HAR](http://www.softwareishard.com/blog/har-12-spec/) file: ```python async await context.route_from_har("github.har.zip") ``` ```python sync context.route_from_har("github.har.zip") ``` Read more in [our documentation](./network#record-and-replay-requests). ### Advanced Routing You can now use [`method: Route.fallback`] to defer routing to other handlers. Consider the following example: ```python async # Remove a header from all requests async def remove_header_handler(route: Route) -> None: headers = await route.request.all_headers() if "if-none-match" in headers: del headers["if-none-match"] await route.fallback(headers=headers) await page.route("**/*", remove_header_handler) # Abort all images async def abort_images_handler(route: Route) -> None: if route.request.resource_type == "image": await route.abort() else: await route.fallback() await page.route("**/*", abort_images_handler) ``` ```python sync # Remove a header from all requests def remove_header_handler(route: Route) -> None: headers = route.request.all_headers() if "if-none-match" in headers: del headers["if-none-match"] route.fallback(headers=headers) page.route("**/*", remove_header_handler) # Abort all images def abort_images_handler(route: Route) -> None: if route.request.resource_type == "image": route.abort() else: route.fallback() page.route("**/*", abort_images_handler) ``` Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserContext.routeFromHAR`] also participate in routing and could be deferred to. ### Web-First Assertions Update * New method [`method: LocatorAssertions.toHaveValues`] that asserts all selected values of `