diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 369dd995e0b04..5b4fc45fe0a04 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -442,6 +442,23 @@ Expected options currently selected. ### option: LocatorAssertions.NotToHaveValues.timeout = %%-csharp-java-python-assertions-timeout-%% * since: v1.23 +## async method: LocatorAssertions.NotToMatchAriaSnapshot +* since: v1.49 +* langs: python + +The opposite of [`method: LocatorAssertions.toMatchAriaSnapshot`]. + +### param: LocatorAssertions.NotToMatchAriaSnapshot.expected +* since: v1.49 +- `expected` + +### option: LocatorAssertions.NotToMatchAriaSnapshot.timeout = %%-js-assertions-timeout-%% +* since: v1.49 + +### option: LocatorAssertions.NotToMatchAriaSnapshot.timeout = %%-csharp-java-python-assertions-timeout-%% +* since: v1.49 + + ## async method: LocatorAssertions.toBeAttached * since: v1.33 @@ -2122,7 +2139,7 @@ await expect(page.locator('body')).toMatchAriaSnapshot(` ``` ```python async -await page.goto('https://demo.playwright.dev/todomvc/') +await page.goto("https://demo.playwright.dev/todomvc/") await expect(page.locator('body')).to_match_aria_snapshot(''' - heading "todos" - textbox "What needs to be done?" @@ -2130,7 +2147,7 @@ await expect(page.locator('body')).to_match_aria_snapshot(''' ``` ```python sync -page.goto('https://demo.playwright.dev/todomvc/') +page.goto("https://demo.playwright.dev/todomvc/") expect(page.locator('body')).to_match_aria_snapshot(''' - heading "todos" - textbox "What needs to be done?" diff --git a/docs/src/api/class-tracing.md b/docs/src/api/class-tracing.md index 5a89dbdac1f3a..3b0011c7b1d3d 100644 --- a/docs/src/api/class-tracing.md +++ b/docs/src/api/class-tracing.md @@ -302,10 +302,10 @@ await test.step('Log in', async () => { ```java // All actions between group and groupEnd // will be shown in the trace viewer as a group. -page.context().tracing.group("Open Playwright.dev > API"); +page.context().tracing().group("Open Playwright.dev > API"); page.navigate("https://playwright.dev/"); page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click(); -page.context().tracing.groupEnd(); +page.context().tracing().groupEnd(); ``` ```python sync @@ -329,10 +329,10 @@ await page.context.tracing.group_end() ```csharp // All actions between GroupAsync and GroupEndAsync // will be shown in the trace viewer as a group. -await Page.Context().Tracing.GroupAsync("Open Playwright.dev > API"); +await Page.Context.Tracing.GroupAsync("Open Playwright.dev > API"); await Page.GotoAsync("https://playwright.dev/"); await Page.GetByRole(AriaRole.Link, new() { Name = "API" }).ClickAsync(); -await Page.Context().Tracing.GroupEndAsync(); +await Page.Context.Tracing.GroupEndAsync(); ``` ### param: Tracing.group.name diff --git a/docs/src/api/params.md b/docs/src/api/params.md index 9b8d3de31b81f..e059fffe46067 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -1001,7 +1001,11 @@ Additional arguments to pass to the browser instance. The list of Chromium flags ## browser-option-channel - `channel` <[string]> -Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using [Google Chrome and Microsoft Edge](../browsers.md#google-chrome--microsoft-edge). +Browser distribution channel. + +Use "chromium" to [opt in to new headless mode](../browsers.md#opt-in-to-new-headless-mode). + +Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to use branded [Google Chrome and Microsoft Edge](../browsers.md#google-chrome--microsoft-edge). ## browser-option-chromiumsandbox - `chromiumSandbox` <[boolean]> diff --git a/docs/src/aria-snapshots.md b/docs/src/aria-snapshots.md index d781907c0a3e3..c26178bbe8e50 100644 --- a/docs/src/aria-snapshots.md +++ b/docs/src/aria-snapshots.md @@ -2,6 +2,7 @@ id: aria-snapshots title: "Aria snapshots" --- +import LiteYouTube from '@site/src/components/LiteYouTube'; ## Overview @@ -9,6 +10,11 @@ In Playwright, aria snapshots provide a YAML representation of the accessibility These snapshots can be stored and compared later to verify if the page structure remains consistent or meets defined expectations. + + The YAML format describes the hierarchical structure of accessible elements on the page, detailing **roles**, **attributes**, **values**, and **text content**. The structure follows a tree-like syntax, where each node represents an accessible element, and indentation indicates nested elements. @@ -61,19 +67,19 @@ await expect(page.locator('body')).toMatchAriaSnapshot(` ``` ```python sync -page.locator("body").to_match_aria_snapshot(""" +expect(page.locator("body")).to_match_aria_snapshot(""" - heading "title" """) ``` ```python async -await page.locator("body").to_match_aria_snapshot(""" +await expect(page.locator("body")).to_match_aria_snapshot(""" - heading "title" """) ``` ```java -page.locator("body").expect().toMatchAriaSnapshot(""" +assertThat(page.locator("body")).matchesAriaSnapshot(""" - heading "title" """); ``` @@ -179,7 +185,7 @@ interactive interface: - **"Assert snapshot" Action**: In the code generator, you can use the "Assert snapshot" action to automatically create a snapshot assertion for the selected elements. This is a quick way to capture the aria snapshot as part of your recorded test flow. - + - **"Aria snapshot" Tab**: The "Aria snapshot" tab within the code generator interface visually represents the aria snapshot for a selected locator, letting you explore, inspect, and verify element roles, attributes, and accessible names to aid snapshot creation and review. diff --git a/docs/src/browsers.md b/docs/src/browsers.md index 1321ed85493bd..83ea0f60c30e1 100644 --- a/docs/src/browsers.md +++ b/docs/src/browsers.md @@ -423,7 +423,7 @@ dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel= While Playwright can download and use the recent Chromium build, it can operate against the branded Google Chrome and Microsoft Edge browsers available on the machine (note that Playwright doesn't install them by default). In particular, the current Playwright version will support Stable and Beta channels of these browsers. -Available channels are `chrome`, `msedge`, `chrome-beta`, `msedge-beta` or `msedge-dev`. +Available channels are `chrome`, `msedge`, `chrome-beta`, `msedge-beta`, `chrome-dev`, `msedge-dev`, `chrome-canary`, `msedge-canary`. :::warning Certain Enterprise Browser Policies may impact Playwright's ability to launch and control Google Chrome and Microsoft Edge. Running in an environment with browser policies is outside of the Playwright project's scope. diff --git a/docs/src/chrome-extensions-js-python.md b/docs/src/chrome-extensions-js-python.md index f34ecf8e9de7c..1142e9b3a76a6 100644 --- a/docs/src/chrome-extensions-js-python.md +++ b/docs/src/chrome-extensions-js-python.md @@ -214,16 +214,15 @@ def test_popup_page(page: Page, extension_id: str) -> None: ## Headless mode -By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using the following code: +By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using [channel `chromium`](./browsers.md#opt-in-to-new-headless-mode): ```js title="fixtures.ts" // ... const pathToExtension = path.join(__dirname, 'my-extension'); const context = await chromium.launchPersistentContext('', { - headless: false, + channel: 'chromium', args: [ - `--headless=new`, `--disable-extensions-except=${pathToExtension}`, `--load-extension=${pathToExtension}`, ], @@ -235,9 +234,8 @@ const context = await chromium.launchPersistentContext('', { path_to_extension = Path(__file__).parent.joinpath("my-extension") context = playwright.chromium.launch_persistent_context( "", - headless=False, + channel="chromium", args=[ - "--headless=new", f"--disable-extensions-except={path_to_extension}", f"--load-extension={path_to_extension}", ], diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index 130b9d4a7168c..286d2c3d90730 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -5,6 +5,91 @@ toc_max_heading_level: 2 --- +## Version 1.49 + +### Aria snapshots + +New assertion [`method: LocatorAssertions.toMatchAriaSnapshot`] verifies page structure by comparing to an expected accessibility tree, represented as YAML. + +```csharp +await page.GotoAsync("https://playwright.dev"); +await Expect(page.Locator("body")).ToMatchAriaSnapshotAsync(@" + - banner: + - heading /Playwright enables reliable/ [level=1] + - link ""Get started"" + - link ""Star microsoft/playwright on GitHub"" + - main: + - img ""Browsers (Chromium, Firefox, WebKit)"" + - heading ""Any browser • Any platform • One API"" +"); +``` + +You can generate this assertion with [Test Generator](./codegen) or by calling [`method: Locator.ariaSnapshot`]. + +Learn more in the [aria snapshots guide](./aria-snapshots). + +### Tracing groups + +New method [`method: Tracing.group`] allows you to visually group actions in the trace viewer. + +```csharp +// All actions between GroupAsync and GroupEndAsync +// will be shown in the trace viewer as a group. +await Page.Context.Tracing.GroupAsync("Open Playwright.dev > API"); +await Page.GotoAsync("https://playwright.dev/"); +await Page.GetByRole(AriaRole.Link, new() { Name = "API" }).ClickAsync(); +await Page.Context.Tracing.GroupEndAsync(); +``` + +### Breaking: `chrome` and `msedge` channels switch to new headless mode + +This change affects you if you're using one of the following channels in your `playwright.config.ts`: +- `chrome`, `chrome-dev`, `chrome-beta`, or `chrome-canary` +- `msedge`, `msedge-dev`, `msedge-beta`, or `msedge-canary` + +After updating to Playwright v1.49, run your test suite. If it still passes, you're good to go. If not, you will probably need to update your snapshots, and adapt some of your test code around PDF viewers and extensions. See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for more details. + +### Try new Chromium headless + +You can opt into the new headless mode by using `'chromium'` channel. As [official Chrome documentation puts it](https://developer.chrome.com/blog/chrome-headless-shell): + +> New Headless on the other hand is the real Chrome browser, and is thus more authentic, reliable, and offers more features. This makes it more suitable for high-accuracy end-to-end web app testing or browser extension testing. + +See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for the list of possible breakages you could encounter and more details on Chromium headless. Please file an issue if you see any problems after opting in. + +```xml csharp title="runsettings.xml" + + + + chromium + + chromium + + + +``` + +```bash csharp +dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=chromium +``` + +### Miscellaneous + +- There will be no more updates for WebKit on Ubuntu 20.04 and Debian 11. We recommend updating your OS to a later version. +- `` elements inside a snapshot now draw a preview. + +### Browser Versions + +- Chromium 131.0.6778.33 +- Mozilla Firefox 132.0 +- WebKit 18.2 + +This version was also tested against the following stable channels: + +- Google Chrome 130 +- Microsoft Edge 130 + + ## Version 1.48 ### WebSocket routing diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index a5d01668def38..8130c77f07321 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -4,6 +4,79 @@ title: "Release notes" toc_max_heading_level: 2 --- +## Version 1.49 + +### Aria snapshots + +New assertion [`method: LocatorAssertions.toMatchAriaSnapshot`] verifies page structure by comparing to an expected accessibility tree, represented as YAML. + +```java +page.navigate("https://playwright.dev"); +assertThat(page.locator("body")).matchesAriaSnapshot(""" + - banner: + - heading /Playwright enables reliable/ [level=1] + - link "Get started" + - link "Star microsoft/playwright on GitHub" + - main: + - img "Browsers (Chromium, Firefox, WebKit)" + - heading "Any browser • Any platform • One API" +"""); +``` + +You can generate this assertion with [Test Generator](./codegen) or by calling [`method: Locator.ariaSnapshot`]. + +Learn more in the [aria snapshots guide](./aria-snapshots). + +### Tracing groups + +New method [`method: Tracing.group`] allows you to visually group actions in the trace viewer. + +```java +// All actions between group and groupEnd +// will be shown in the trace viewer as a group. +page.context().tracing().group("Open Playwright.dev > API"); +page.navigate("https://playwright.dev/"); +page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click(); +page.context().tracing().groupEnd(); +``` + +### Breaking: `chrome` and `msedge` channels switch to new headless mode + +This change affects you if you're using one of the following channels in your `playwright.config.ts`: +- `chrome`, `chrome-dev`, `chrome-beta`, or `chrome-canary` +- `msedge`, `msedge-dev`, `msedge-beta`, or `msedge-canary` + +After updating to Playwright v1.49, run your test suite. If it still passes, you're good to go. If not, you will probably need to update your snapshots, and adapt some of your test code around PDF viewers and extensions. See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for more details. + +### Try new Chromium headless + +You can opt into the new headless mode by using `'chromium'` channel. As [official Chrome documentation puts it](https://developer.chrome.com/blog/chrome-headless-shell): + +> New Headless on the other hand is the real Chrome browser, and is thus more authentic, reliable, and offers more features. This makes it more suitable for high-accuracy end-to-end web app testing or browser extension testing. + +See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for the list of possible breakages you could encounter and more details on Chromium headless. Please file an issue if you see any problems after opting in. + +```java +Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setChannel("chromium")); +``` + +### Miscellaneous + +- There will be no more updates for WebKit on Ubuntu 20.04 and Debian 11. We recommend updating your OS to a later version. +- `` elements inside a snapshot now draw a preview. + +### Browser Versions + +- Chromium 131.0.6778.33 +- Mozilla Firefox 132.0 +- WebKit 18.2 + +This version was also tested against the following stable channels: + +- Google Chrome 130 +- Microsoft Edge 130 + + ## Version 1.48 ### WebSocket routing diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md index af806fc31afd6..a27291c27db68 100644 --- a/docs/src/release-notes-js.md +++ b/docs/src/release-notes-js.md @@ -8,6 +8,11 @@ import LiteYouTube from '@site/src/components/LiteYouTube'; ## Version 1.49 + + ### Aria snapshots New assertion [`method: LocatorAssertions.toMatchAriaSnapshot`] verifies page structure by comparing to an expected accessibility tree, represented as YAML. diff --git a/docs/src/release-notes-python.md b/docs/src/release-notes-python.md index 211e0ad5c2af8..fc7dd1ccd138c 100644 --- a/docs/src/release-notes-python.md +++ b/docs/src/release-notes-python.md @@ -4,6 +4,80 @@ title: "Release notes" toc_max_heading_level: 2 --- +## Version 1.49 + +### Aria snapshots + +New assertion [`method: LocatorAssertions.toMatchAriaSnapshot`] verifies page structure by comparing to an expected accessibility tree, represented as YAML. + +```python +page.goto("https://playwright.dev") +expect(page.locator('body')).to_match_aria_snapshot(''' + - banner: + - heading /Playwright enables reliable/ [level=1] + - link "Get started" + - link "Star microsoft/playwright on GitHub" + - main: + - img "Browsers (Chromium, Firefox, WebKit)" + - heading "Any browser • Any platform • One API" +''') +``` + +You can generate this assertion with [Test Generator](./codegen) or by calling [`method: Locator.ariaSnapshot`]. + +Learn more in the [aria snapshots guide](./aria-snapshots). + +### Tracing groups + +New method [`method: Tracing.group`] allows you to visually group actions in the trace viewer. + +```python +# All actions between group and group_end +# will be shown in the trace viewer as a group. +page.context.tracing.group("Open Playwright.dev > API") +page.goto("https://playwright.dev/") +page.get_by_role("link", name="API").click() +page.context.tracing.group_end() +``` + +### Breaking: `chrome` and `msedge` channels switch to new headless mode + +This change affects you if you're using one of the following channels in your `playwright.config.ts`: +- `chrome`, `chrome-dev`, `chrome-beta`, or `chrome-canary` +- `msedge`, `msedge-dev`, `msedge-beta`, or `msedge-canary` + +After updating to Playwright v1.49, run your test suite. If it still passes, you're good to go. If not, you will probably need to update your snapshots, and adapt some of your test code around PDF viewers and extensions. See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for more details. + +### Try new Chromium headless + +You can opt into the new headless mode by using `'chromium'` channel. As [official Chrome documentation puts it](https://developer.chrome.com/blog/chrome-headless-shell): + +> New Headless on the other hand is the real Chrome browser, and is thus more authentic, reliable, and offers more features. This makes it more suitable for high-accuracy end-to-end web app testing or browser extension testing. + +See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for the list of possible breakages you could encounter and more details on Chromium headless. Please file an issue if you see any problems after opting in. + +```bash python +pytest test_login.py --browser-channel chromium +``` + +### Miscellaneous + +- There will be no more updates for WebKit on Ubuntu 20.04 and Debian 11. We recommend updating your OS to a later version. +- `` elements inside a snapshot now draw a preview. +- Python 3.8 is not supported anymore. + +### Browser Versions + +- Chromium 131.0.6778.33 +- Mozilla Firefox 132.0 +- WebKit 18.2 + +This version was also tested against the following stable channels: + +- Google Chrome 130 +- Microsoft Edge 130 + + ## Version 1.48 ### WebSocket routing diff --git a/package-lock.json b/package-lock.json index 5471d4e43bcac..20b0be31a7f02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "playwright-internal", - "version": "1.49.0", + "version": "1.49.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "playwright-internal", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "workspaces": [ "packages/*" @@ -7733,10 +7733,10 @@ "version": "0.0.0" }, "packages/playwright": { - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -7750,11 +7750,11 @@ }, "packages/playwright-browser-chromium": { "name": "@playwright/browser-chromium", - "version": "1.49.0", + "version": "1.49.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "engines": { "node": ">=18" @@ -7762,11 +7762,11 @@ }, "packages/playwright-browser-firefox": { "name": "@playwright/browser-firefox", - "version": "1.49.0", + "version": "1.49.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "engines": { "node": ">=18" @@ -7774,22 +7774,22 @@ }, "packages/playwright-browser-webkit": { "name": "@playwright/browser-webkit", - "version": "1.49.0", + "version": "1.49.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "engines": { "node": ">=18" } }, "packages/playwright-chromium": { - "version": "1.49.0", + "version": "1.49.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -7799,7 +7799,7 @@ } }, "packages/playwright-core": { - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -7810,11 +7810,11 @@ }, "packages/playwright-ct-core": { "name": "@playwright/experimental-ct-core", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.0", - "playwright-core": "1.49.0", + "playwright": "1.49.1", + "playwright-core": "1.49.1", "vite": "^5.2.8" }, "engines": { @@ -7823,10 +7823,10 @@ }, "packages/playwright-ct-react": { "name": "@playwright/experimental-ct-react", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -7838,10 +7838,10 @@ }, "packages/playwright-ct-react17": { "name": "@playwright/experimental-ct-react17", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -7853,10 +7853,10 @@ }, "packages/playwright-ct-svelte": { "name": "@playwright/experimental-ct-svelte", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@sveltejs/vite-plugin-svelte": "^3.0.1" }, "bin": { @@ -7871,10 +7871,10 @@ }, "packages/playwright-ct-vue": { "name": "@playwright/experimental-ct-vue", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@vitejs/plugin-vue": "^4.2.1" }, "bin": { @@ -7885,11 +7885,11 @@ } }, "packages/playwright-firefox": { - "version": "1.49.0", + "version": "1.49.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -7900,10 +7900,10 @@ }, "packages/playwright-test": { "name": "@playwright/test", - "version": "1.49.0", + "version": "1.49.1", "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.0" + "playwright": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -7913,11 +7913,11 @@ } }, "packages/playwright-webkit": { - "version": "1.49.0", + "version": "1.49.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" diff --git a/package.json b/package.json index 3c1489d9c454e..0d857d91a5ae2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "playwright-internal", "private": true, - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate web browsers", "repository": { "type": "git", diff --git a/packages/playwright-browser-chromium/package.json b/packages/playwright-browser-chromium/package.json index 118b9646c04b2..dca8ba83aceba 100644 --- a/packages/playwright-browser-chromium/package.json +++ b/packages/playwright-browser-chromium/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-chromium", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright package that automatically installs Chromium", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" } } diff --git a/packages/playwright-browser-firefox/package.json b/packages/playwright-browser-firefox/package.json index 5c35f5c32d118..c8a436bff77c2 100644 --- a/packages/playwright-browser-firefox/package.json +++ b/packages/playwright-browser-firefox/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-firefox", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright package that automatically installs Firefox", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" } } diff --git a/packages/playwright-browser-webkit/package.json b/packages/playwright-browser-webkit/package.json index e9226865ab374..b62f6c696f5a4 100644 --- a/packages/playwright-browser-webkit/package.json +++ b/packages/playwright-browser-webkit/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-webkit", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright package that automatically installs WebKit", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" } } diff --git a/packages/playwright-chromium/package.json b/packages/playwright-chromium/package.json index 650a5ca60ea54..172087fb97755 100644 --- a/packages/playwright-chromium/package.json +++ b/packages/playwright-chromium/package.json @@ -1,6 +1,6 @@ { "name": "playwright-chromium", - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate Chromium", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" } } diff --git a/packages/playwright-core/package.json b/packages/playwright-core/package.json index 7aff01eb6ebaf..c9843b1267f34 100644 --- a/packages/playwright-core/package.json +++ b/packages/playwright-core/package.json @@ -1,6 +1,6 @@ { "name": "playwright-core", - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate web browsers", "repository": { "type": "git", diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index 57ebc5fa69b8b..6d9dac039ad46 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -842,6 +842,9 @@ class FrameSession { event.type, event.message, async (accept: boolean, promptText?: string) => { + // TODO: this should actually be a CDP event that notifies about a cancelled navigation attempt. + if (this._isMainFrame() && event.type === 'beforeunload' && !accept) + this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog'); await this._client.send('Page.handleJavaScriptDialog', { accept, promptText }); }, event.defaultPrompt)); diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index ddfb0386d98e0..73740357061ee 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -1157,7 +1157,6 @@ export class Recorder { } clearHighlight() { - this._currentTool.cleanup?.(); this.updateHighlight(null, false); } diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index 50564fa31f163..25035b699830e 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -383,7 +383,11 @@ export function getAriaLabelledByElements(element: Element): Element[] | null { const ref = element.getAttribute('aria-labelledby'); if (ref === null) return null; - return getIdRefs(element, ref); + const refs = getIdRefs(element, ref); + // step 2b: + // "if the current node has an aria-labelledby attribute that contains at least one valid IDREF" + // Therefore, if none of the refs match an element, we consider aria-labelledby to be missing. + return refs.length ? refs : null; } function allowsNameFromContent(role: string, targetDescendant: boolean) { diff --git a/packages/playwright-core/src/server/injected/yaml.ts b/packages/playwright-core/src/server/injected/yaml.ts index 977591c1cc26b..7daebc574a5cf 100644 --- a/packages/playwright-core/src/server/injected/yaml.ts +++ b/packages/playwright-core/src/server/injected/yaml.ts @@ -62,12 +62,8 @@ function yamlStringNeedsQuotes(str: string): boolean { if (/^-\s/.test(str)) return true; - // Strings that start with a special indicator character need quotes - if (/^[&*].*/.test(str)) - return true; - - // Strings containing ':' followed by a space or at the end need quotes - if (/:(\s|$)/.test(str)) + // Strings containing ':' or '\n' followed by a space or at the end need quotes + if (/[\n:](\s|$)/.test(str)) return true; // Strings containing '#' preceded by a space need quotes (comment indicator) @@ -78,21 +74,17 @@ function yamlStringNeedsQuotes(str: string): boolean { if (/[\n\r]/.test(str)) return true; - // Strings starting with '?' or '!' (directives) need quotes - if (/^[?!]/.test(str)) - return true; - - // Strings starting with '>' or '|' (block scalar indicators) need quotes - if (/^[>|]/.test(str)) - return true; - - // Strings starting with quotes need quotes - if (/^["']/.test(str)) + // Strings starting with indicator characters or quotes need quotes + if (/^[&*\],?!>|@"'#%]/.test(str)) return true; // Strings containing special characters that could cause ambiguity if (/[{}`]/.test(str)) return true; + // Non-string types recognized by YAML + if (!isNaN(Number(str)) || ['y', 'n', 'yes', 'no', 'true', 'false', 'on', 'off', 'null'].includes(str.toLowerCase())) + return true; + return false; } diff --git a/packages/playwright-core/src/server/launchApp.ts b/packages/playwright-core/src/server/launchApp.ts index 3d119f9d46459..d8c81a3169127 100644 --- a/packages/playwright-core/src/server/launchApp.ts +++ b/packages/playwright-core/src/server/launchApp.ts @@ -43,12 +43,12 @@ export async function launchApp(browserType: BrowserType, options: { } const context = await browserType.launchPersistentContext(serverSideCallMetadata(), '', { - channel: !options.persistentContextOptions?.executablePath ? findChromiumChannel(options.sdkLanguage) : undefined, - noDefaultViewport: true, ignoreDefaultArgs: ['--enable-automation'], - colorScheme: 'no-override', - acceptDownloads: isUnderTest() ? 'accept' : 'internal-browser-default', ...options?.persistentContextOptions, + channel: options.persistentContextOptions?.channel ?? (!options.persistentContextOptions?.executablePath ? findChromiumChannel(options.sdkLanguage) : undefined), + noDefaultViewport: options.persistentContextOptions?.noDefaultViewport ?? true, + acceptDownloads: options?.persistentContextOptions?.acceptDownloads ?? (isUnderTest() ? 'accept' : 'internal-browser-default'), + colorScheme: options?.persistentContextOptions?.colorScheme ?? 'no-override', args, }); const [page] = context.pages(); diff --git a/packages/playwright-core/src/server/recorder/recorderCollection.ts b/packages/playwright-core/src/server/recorder/recorderCollection.ts index b5216d7382e08..2643dece9131b 100644 --- a/packages/playwright-core/src/server/recorder/recorderCollection.ts +++ b/packages/playwright-core/src/server/recorder/recorderCollection.ts @@ -38,7 +38,7 @@ export class RecorderCollection extends EventEmitter { restart() { this._actions = []; - this._fireChange(); + this.emit('change', []); } setEnabled(enabled: boolean) { @@ -128,6 +128,7 @@ export class RecorderCollection extends EventEmitter { private _fireChange() { if (!this._enabled) return; + this.emit('change', collapseActions(this._actions)); } } diff --git a/packages/playwright-core/src/server/webkit/wkPage.ts b/packages/playwright-core/src/server/webkit/wkPage.ts index 0bd82ed338342..b5e2281d5f539 100644 --- a/packages/playwright-core/src/server/webkit/wkPage.ts +++ b/packages/playwright-core/src/server/webkit/wkPage.ts @@ -612,6 +612,9 @@ export class WKPage implements PageDelegate { event.type as dialog.DialogType, event.message, async (accept: boolean, promptText?: string) => { + // TODO: this should actually be a RDP event that notifies about a cancelled navigation attempt. + if (event.type === 'beforeunload' && !accept) + this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog'); await this._pageProxySession.send('Dialog.handleJavaScriptDialog', { accept, promptText }); }, event.defaultPrompt)); diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 85dd2d50a6424..865fd0cb7cb26 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -14709,9 +14709,12 @@ export interface BrowserType { bypassCSP?: boolean; /** - * Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", - * "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using - * [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). + * Browser distribution channel. + * + * Use "chromium" to [opt in to new headless mode](https://playwright.dev/docs/browsers#opt-in-to-new-headless-mode). + * + * Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or + * "msedge-canary" to use branded [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). */ channel?: string; @@ -15205,9 +15208,12 @@ export interface BrowserType { args?: Array; /** - * Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", - * "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using - * [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). + * Browser distribution channel. + * + * Use "chromium" to [opt in to new headless mode](https://playwright.dev/docs/browsers#opt-in-to-new-headless-mode). + * + * Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or + * "msedge-canary" to use branded [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). */ channel?: string; @@ -21540,9 +21546,12 @@ export interface LaunchOptions { args?: Array; /** - * Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", - * "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using - * [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). + * Browser distribution channel. + * + * Use "chromium" to [opt in to new headless mode](https://playwright.dev/docs/browsers#opt-in-to-new-headless-mode). + * + * Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or + * "msedge-canary" to use branded [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). */ channel?: string; diff --git a/packages/playwright-ct-core/package.json b/packages/playwright-ct-core/package.json index fd31fbe4872fd..954797e6ecbdf 100644 --- a/packages/playwright-ct-core/package.json +++ b/packages/playwright-ct-core/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-core", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright Component Testing Helpers", "repository": { "type": "git", @@ -26,8 +26,8 @@ } }, "dependencies": { - "playwright-core": "1.49.0", + "playwright-core": "1.49.1", "vite": "^5.2.8", - "playwright": "1.49.0" + "playwright": "1.49.1" } } diff --git a/packages/playwright-ct-react/package.json b/packages/playwright-ct-react/package.json index d69245f593701..e4594085b5d80 100644 --- a/packages/playwright-ct-react/package.json +++ b/packages/playwright-ct-react/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-react", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright Component Testing for React", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@vitejs/plugin-react": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-react17/package.json b/packages/playwright-ct-react17/package.json index e7a18ec6392be..cfa82e12521bf 100644 --- a/packages/playwright-ct-react17/package.json +++ b/packages/playwright-ct-react17/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-react17", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright Component Testing for React", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@vitejs/plugin-react": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-svelte/package.json b/packages/playwright-ct-svelte/package.json index e8c4c341de413..2cc7266254115 100644 --- a/packages/playwright-ct-svelte/package.json +++ b/packages/playwright-ct-svelte/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-svelte", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright Component Testing for Svelte", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@sveltejs/vite-plugin-svelte": "^3.0.1" }, "devDependencies": { diff --git a/packages/playwright-ct-vue/package.json b/packages/playwright-ct-vue/package.json index 8b27102339618..67c6c6a8c2663 100644 --- a/packages/playwright-ct-vue/package.json +++ b/packages/playwright-ct-vue/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-vue", - "version": "1.49.0", + "version": "1.49.1", "description": "Playwright Component Testing for Vue", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0", + "@playwright/experimental-ct-core": "1.49.1", "@vitejs/plugin-vue": "^4.2.1" }, "bin": { diff --git a/packages/playwright-firefox/package.json b/packages/playwright-firefox/package.json index 4833f047c34db..c7c1e2ef1f30f 100644 --- a/packages/playwright-firefox/package.json +++ b/packages/playwright-firefox/package.json @@ -1,6 +1,6 @@ { "name": "playwright-firefox", - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate Firefox", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" } } diff --git a/packages/playwright-test/package.json b/packages/playwright-test/package.json index 5950a948716b7..4677428e31229 100644 --- a/packages/playwright-test/package.json +++ b/packages/playwright-test/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/test", - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -30,6 +30,6 @@ }, "scripts": {}, "dependencies": { - "playwright": "1.49.0" + "playwright": "1.49.1" } } diff --git a/packages/playwright-webkit/package.json b/packages/playwright-webkit/package.json index bb9ca55a9bd46..1ebe2f9996614 100644 --- a/packages/playwright-webkit/package.json +++ b/packages/playwright-webkit/package.json @@ -1,6 +1,6 @@ { "name": "playwright-webkit", - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate WebKit", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" } } diff --git a/packages/playwright/package.json b/packages/playwright/package.json index 47037f4570709..42a2c3d593d16 100644 --- a/packages/playwright/package.json +++ b/packages/playwright/package.json @@ -1,6 +1,6 @@ { "name": "playwright", - "version": "1.49.0", + "version": "1.49.1", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -56,7 +56,7 @@ }, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "optionalDependencies": { "fsevents": "2.3.2" diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 305ae67caff4c..d8a1d3a8fba7d 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5776,9 +5776,12 @@ export interface PlaywrightWorkerOptions { */ headless: boolean; /** - * Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", - * "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using - * [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). + * Browser distribution channel. + * + * Use "chromium" to [opt in to new headless mode](https://playwright.dev/docs/browsers#opt-in-to-new-headless-mode). + * + * Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or + * "msedge-canary" to use branded [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge). * * **Usage** * diff --git a/packages/web/src/components/treeView.tsx b/packages/web/src/components/treeView.tsx index e6cf557e99c7d..242e834edeae3 100644 --- a/packages/web/src/components/treeView.tsx +++ b/packages/web/src/components/treeView.tsx @@ -319,7 +319,9 @@ function indexTree( selectedItem: T | undefined, expandedItems: Map, autoExpandDepth: number, - isVisible?: (item: T) => boolean): Map { + isVisible: (item: T) => boolean = () => true): Map { + if (!isVisible(rootItem)) + return new Map(); const result = new Map(); const temporaryExpanded = new Set(); @@ -328,9 +330,9 @@ function indexTree( let lastItem: T | null = null; const appendChildren = (parent: T, depth: number) => { - if (isVisible && !isVisible(parent)) - return; for (const item of parent.children as T[]) { + if (!isVisible(item)) + continue; const expandState = temporaryExpanded.has(item.id) || expandedItems.get(item.id); const autoExpandMatches = autoExpandDepth > depth && result.size < 25 && expandState !== false; const expanded = item.children.length ? expandState ?? autoExpandMatches : undefined; diff --git a/tests/components/ct-vue-vite/package.json b/tests/components/ct-vue-vite/package.json index 608a128763af7..6fac022cb51d6 100644 --- a/tests/components/ct-vue-vite/package.json +++ b/tests/components/ct-vue-vite/package.json @@ -14,6 +14,7 @@ "devDependencies": { "@vitejs/plugin-vue": "^4.1.0", "@vue/tsconfig": "^0.5.1", + "typescript": "5.6.2", "vite": "^5.2.8", "vue-tsc": "^2.0.21" } diff --git a/tests/library/beforeunload.spec.ts b/tests/library/beforeunload.spec.ts index 9f0982eea7654..05134bd429332 100644 --- a/tests/library/beforeunload.spec.ts +++ b/tests/library/beforeunload.spec.ts @@ -104,3 +104,25 @@ it('should not stall on evaluate when dismissing beforeunload', async ({ page, s ]); }); +it('should not stall on click when dismissing beforeunload', async ({ page, server }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33806' }); + + await page.goto(server.EMPTY_PAGE); + await page.setContent(`click me`); + + await page.evaluate(() => { + window.onbeforeunload = () => false; + }); + page.on('dialog', async dialog => { + await dialog.dismiss(); + }); + + await page.getByRole('link').click({ noWaitAfter: true }); + await page.evaluate(() => { + window.onbeforeunload = null; + }); + + // This line should not timeout. + await page.getByRole('link').click({ timeout: 5000 }); + await expect(page).toHaveURL(server.PREFIX + '/frames/one-frame.html'); +}); diff --git a/tests/library/inspector/cli-codegen-1.spec.ts b/tests/library/inspector/cli-codegen-1.spec.ts index a876a25e47c2a..0fd5f69d0bbb9 100644 --- a/tests/library/inspector/cli-codegen-1.spec.ts +++ b/tests/library/inspector/cli-codegen-1.spec.ts @@ -926,4 +926,34 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`) const predicate = (msg: ConsoleMessage) => msg.type() === 'error' && /Content[\- ]Security[\- ]Policy/i.test(msg.text()); await expect(page.waitForEvent('console', { predicate, timeout: 1000 })).rejects.toThrow(); }); + + test('should clear when recording is disabled', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33802' } }, async ({ openRecorder }) => { + const { recorder } = await openRecorder(); + + await recorder.setContentAndWait(` + + + `); + + await recorder.hoverOverElement('#foo'); + let [sources] = await Promise.all([ + recorder.waitForOutput('JavaScript', 'click'), + recorder.trustedClick(), + ]); + + expect(sources.get('JavaScript').text).toContain(`getByRole('button', { name: 'Foo' }).click()`); + + await recorder.recorderPage.getByRole('button', { name: 'Record' }).click(); + await recorder.recorderPage.getByRole('button', { name: 'Clear' }).click(); + await recorder.recorderPage.getByRole('button', { name: 'Record' }).click(); + + await recorder.hoverOverElement('#bar'); + [sources] = await Promise.all([ + recorder.waitForOutput('JavaScript', 'click'), + recorder.trustedClick(), + ]); + + expect(sources.get('JavaScript').text).toContain(`getByRole('button', { name: 'Bar' }).click()`); + expect(sources.get('JavaScript').text).not.toContain(`getByRole('button', { name: 'Foo' })`); + }); }); diff --git a/tests/library/role-utils.spec.ts b/tests/library/role-utils.spec.ts index a02680ce86ac3..2b5792d0f1fc3 100644 --- a/tests/library/role-utils.spec.ts +++ b/tests/library/role-utils.spec.ts @@ -495,6 +495,16 @@ test('should not include hidden pseudo into accessible name', async ({ page }) = expect.soft(await getNameAndRole(page, 'a')).toEqual({ role: 'link', name: 'hello hello' }); }); +test('should ignore invalid aria-labelledby', async ({ page }) => { + await page.setContent(` + + `); + expect.soft(await getNameAndRole(page, 'input')).toEqual({ role: 'textbox', name: 'Text here' }); +}); + function toArray(x: any): any[] { return Array.isArray(x) ? x : [x]; } diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index a7937e9be5d46..2289e59d74113 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -465,6 +465,12 @@ it('should escape yaml text in text nodes', async ({ page }) => {
one: link1 "two link2 'three link3 \`four
+ `); await checkAndMatchSnapshot(page.locator('body'), ` @@ -476,6 +482,17 @@ it('should escape yaml text in text nodes', async ({ page }) => { - text: "'three" - link "link3" - text: "\`four" + - list: + - link "one" + - text: "," + - link "two" + - text: ( + - link "three" + - text: ") {" + - link "four" + - text: "} [" + - link "five" + - text: "]" `); }); @@ -492,3 +509,57 @@ it('should handle long strings', async ({ page }) => { - region: ${s} `); }); + +it('should escape special yaml characters', async ({ page }) => { + await page.setContent(` + @hello@hello + ]hello]hello + hello\n + hello\n\n hello\n hello + #hello#hello + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "@hello" + - text: "@hello" + - link "]hello" + - text: "]hello" + - link "hello" + - text: hello + - link "hello" + - text: hello + - link "#hello" + - text: "#hello" + `); +}); + +it('should escape special yaml values', async ({ page }) => { + await page.setContent(` + trueFalse + NOyes + yN + onOff + nullNULL + 123123 + -1.2-1.2 + + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "true" + - text: "False" + - link "NO" + - text: "yes" + - link "y" + - text: "N" + - link "on" + - text: "Off" + - link "null" + - text: "NULL" + - link "123" + - text: "123" + - link "-1.2" + - text: "-1.2" + - textbox: "555" + `); +}); diff --git a/tests/playwright-test/ui-mode-trace.spec.ts b/tests/playwright-test/ui-mode-trace.spec.ts index def44e9aeb451..b52b7d59f99e2 100644 --- a/tests/playwright-test/ui-mode-trace.spec.ts +++ b/tests/playwright-test/ui-mode-trace.spec.ts @@ -307,3 +307,27 @@ test('should show request source context id', async ({ runUITest, server }) => { await expect(page.getByText('page#2')).toBeVisible(); await expect(page.getByText('api#1')).toBeVisible(); }); + +test('should filter actions tab on double-click', async ({ runUITest, server }) => { + const { page } = await runUITest({ + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('pass', async ({ page }) => { + await page.goto('${server.EMPTY_PAGE}'); + }); + `, + }); + + await page.getByText('pass').dblclick(); + + const actionsTree = page.getByTestId('actions-tree'); + await expect(actionsTree.getByRole('treeitem')).toHaveText([ + /Before Hooks/, + /page.goto/, + /After Hooks/, + ]); + await actionsTree.getByRole('treeitem', { name: 'page.goto' }).dblclick(); + await expect(actionsTree.getByRole('treeitem')).toHaveText([ + /page.goto/, + ]); +});