Compare commits

...

16 commits

Author SHA1 Message Date
Dmitry Gozman a051ceb8e1
chore: mark 1.43.1 (#30354) 2024-04-12 10:19:02 -07:00
Max Schmitt 3ab466e1d3
cherry-pick(#30312): fix(ui-mode): do not loose run information after writing into testDir (#30328)
Partially reverts https://github.com/microsoft/playwright/pull/30008
that started to reset all test results upon listing tests, including the
test that did just run and triggered re-listing.

https://github.com/microsoft/playwright/issues/30300.
2024-04-11 23:40:07 +02:00
Playwright Service 35468cfaaa
cherry-pick(#30342): Revert "fix(reuse): reset Origin Private File System API (#29921)" (#30344)
This PR cherry-picks the following commits:

- 96053ed0b5

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-11 20:28:25 +02:00
Max Schmitt 5332639114 cherry-pick(#30263): docs: add v1.43 release notes for language ports 2024-04-09 09:09:56 +02:00
Max Schmitt c729a7b86d cherry-pick(#30232): docs: fix C# and python snippets 2024-04-09 09:09:32 +02:00
Max Schmitt 7748e219a1 cherry-pick(#30210): docs: update context.backgroundPage event examples 2024-04-09 09:09:14 +02:00
Max Schmitt acb6ff1d84 cherry-pick(#30200): docs(java,csharp): add BrowserContext.backgroundPage(s) 2024-04-09 09:08:56 +02:00
Dmitry Gozman 7c7f8ac9fa
cherry-pick(#30227): chore(deps): bump vite from 5.0.12 to 5.0.13 (#30254) 2024-04-04 12:25:32 -07:00
Max Schmitt 62d4dc9ebb cherry-pick(#30235): feat(chromium): roll to r1112 2024-04-04 09:59:36 +02:00
Pavel Feldman 79d477666f cherry-pick(#30226): chore: migrate to the testserver.initialize 2024-04-03 12:52:29 -07:00
Pavel Feldman 6b94231dcf cherry-pick(#30202): do not run setup tasks on test run via server 2024-04-01 15:32:58 -07:00
Pavel Feldman 0889736332 cherry-pick(#30185): chore: opt into stdio forwarding 2024-03-30 18:48:34 -07:00
Dmitry Gozman a01db3ffd7
chore: mark version 1.43.0 (#30183) 2024-03-29 12:54:53 -07:00
Pavel Feldman 1cd1239d62 cherry-pick(#30170): chore: hide internal commands 2024-03-28 12:19:58 -07:00
Max Schmitt 122ab67e34 cherry-pick(#30138): fix: UI Mode tags without theme applied
Trace Viewer theming is override based. By default you should have
something applied - an optional `dark-mode` class might be there too.
2024-03-27 16:47:16 +01:00
Pavel Feldman 75776dbc3e cherry-pick(#30135): chore: do not exit UI mode upon page reload 2024-03-26 15:51:25 -07:00
41 changed files with 434 additions and 273 deletions

View file

@ -1,6 +1,6 @@
# 🎭 Playwright # 🎭 Playwright
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-124.0.6367.8-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-124.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop --> [![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-124.0.6367.29-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-124.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
| | Linux | macOS | Windows | | | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: | | :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->124.0.6367.8<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Chromium <!-- GEN:chromium-version -->124.0.6367.29<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->124.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox <!-- GEN:firefox-version -->124.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |

View file

@ -64,7 +64,6 @@ await context.CloseAsync();
## event: BrowserContext.backgroundPage ## event: BrowserContext.backgroundPage
* since: v1.11 * since: v1.11
* langs: js, python
- argument: <[Page]> - argument: <[Page]>
:::note :::note
@ -73,6 +72,12 @@ Only works with Chromium browser's persistent context.
Emitted when new background page is created in the context. Emitted when new background page is created in the context.
```java
context.onBackgroundPage(backgroundPage -> {
System.out.println(backgroundPage.url());
});
```
```js ```js
const backgroundPage = await context.waitForEvent('backgroundpage'); const backgroundPage = await context.waitForEvent('backgroundpage');
``` ```
@ -85,6 +90,14 @@ background_page = await context.wait_for_event("backgroundpage")
background_page = context.wait_for_event("backgroundpage") background_page = context.wait_for_event("backgroundpage")
``` ```
```csharp
context.BackgroundPage += (_, backgroundPage) =>
{
Console.WriteLine(backgroundPage.Url);
};
```
## event: BrowserContext.close ## event: BrowserContext.close
* since: v1.8 * since: v1.8
- argument: <[BrowserContext]> - argument: <[BrowserContext]>
@ -441,7 +454,6 @@ Script to be evaluated in all pages in the browser context. Optional.
## method: BrowserContext.backgroundPages ## method: BrowserContext.backgroundPages
* since: v1.11 * since: v1.11
* langs: js, python
- returns: <[Array]<[Page]>> - returns: <[Array]<[Page]>>
:::note :::note

View file

@ -4,6 +4,50 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.43
### New APIs
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
```csharp
// Clear all cookies.
await Context.ClearCookiesAsync();
// New: clear cookies with a particular name.
await Context.ClearCookiesAsync(new() { Name = "session-id" });
// New: clear cookies for a particular domain.
await Context.ClearCookiesAsync(new() { Domain = "my-origin.com" });
```
- New property [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
```csharp
var locator = Page.Locator("iframe[name='embedded']");
// ...
var frameLocator = locator.ContentFrame;
await frameLocator.GetByRole(AriaRole.Button).ClickAsync();
```
- New property [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
```csharp
var frameLocator = page.FrameLocator("iframe[name='embedded']");
// ...
var locator = frameLocator.Owner;
await Expect(locator).ToBeVisibleAsync();
```
### Browser Versions
* Chromium 124.0.6367.8
* Mozilla Firefox 124.0
* WebKit 17.4
This version was also tested against the following stable channels:
* Google Chrome 123
* Microsoft Edge 123
## Version 1.42 ## Version 1.42
### New Locator Handler ### New Locator Handler

View file

@ -4,6 +4,50 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.43
### New APIs
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
```java
// Clear all cookies.
context.clearCookies();
// New: clear cookies with a particular name.
context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("session-id"));
// New: clear cookies for a particular domain.
context.clearCookies(new BrowserContext.ClearCookiesOptions().setDomain("my-origin.com"));
```
- New method [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
```java
Locator locator = page.locator("iframe[name='embedded']");
// ...
FrameLocator frameLocator = locator.contentFrame();
frameLocator.getByRole(AriaRole.BUTTON).click();
```
- New method [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
```java
FrameLocator frameLocator = page.frameLocator("iframe[name='embedded']");
// ...
Locator locator = frameLocator.owner();
assertThat(locator).isVisible();
```
### Browser Versions
* Chromium 124.0.6367.8
* Mozilla Firefox 124.0
* WebKit 17.4
This version was also tested against the following stable channels:
* Google Chrome 123
* Microsoft Edge 123
## Version 1.42 ## Version 1.42
### Experimental JUnit integration ### Experimental JUnit integration

View file

@ -4,6 +4,52 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.43
### New APIs
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
```python
# Clear all cookies.
context.clear_cookies()
# New: clear cookies with a particular name.
context.clear_cookies(name="session-id")
# New: clear cookies for a particular domain.
context.clear_cookies(domain="my-origin.com")
```
- New method [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
```python
locator = page.locator("iframe[name='embedded']")
# ...
frame_locator = locator.content_frame
frame_locator.getByRole("button").click()
```
- New method [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
```python
frame_locator = page.frame_locator("iframe[name='embedded']")
# ...
locator = frame_locator.owner
expect(locator).to_be_visible()
```
- Conda builds are now published for macOS-arm64 and Linux-arm64.
### Browser Versions
* Chromium 124.0.6367.8
* Mozilla Firefox 124.0
* WebKit 17.4
This version was also tested against the following stable channels:
* Google Chrome 123
* Microsoft Edge 123
## Version 1.42 ## Version 1.42
### New Locator Handler ### New Locator Handler

78
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "playwright-internal", "name": "playwright-internal",
"version": "1.43.0-next", "version": "1.43.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "playwright-internal", "name": "playwright-internal",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
@ -61,7 +61,7 @@
"socksv5": "0.0.6", "socksv5": "0.0.6",
"ssim.js": "^3.5.0", "ssim.js": "^3.5.0",
"typescript": "^5.3.2", "typescript": "^5.3.2",
"vite": "^5.0.12", "vite": "^5.0.13",
"ws": "^8.5.0", "ws": "^8.5.0",
"xml2js": "^0.5.0", "xml2js": "^0.5.0",
"yaml": "^2.2.2" "yaml": "^2.2.2"
@ -7345,9 +7345,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "5.0.12", "version": "5.0.13",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.13.tgz",
"integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", "integrity": "sha512-/9ovhv2M2dGTuA+dY93B9trfyWMDRQw2jdVBhHNP6wr0oF34wG2i/N55801iZIpgUpnHDm4F/FabGQLyc+eOgg==",
"dependencies": { "dependencies": {
"esbuild": "^0.19.3", "esbuild": "^0.19.3",
"postcss": "^8.4.32", "postcss": "^8.4.32",
@ -8136,10 +8136,10 @@
} }
}, },
"packages/playwright": { "packages/playwright": {
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -8153,11 +8153,11 @@
}, },
"packages/playwright-browser-chromium": { "packages/playwright-browser-chromium": {
"name": "@playwright/browser-chromium", "name": "@playwright/browser-chromium",
"version": "1.43.0-next", "version": "1.43.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=16"
@ -8165,11 +8165,11 @@
}, },
"packages/playwright-browser-firefox": { "packages/playwright-browser-firefox": {
"name": "@playwright/browser-firefox", "name": "@playwright/browser-firefox",
"version": "1.43.0-next", "version": "1.43.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=16"
@ -8177,22 +8177,22 @@
}, },
"packages/playwright-browser-webkit": { "packages/playwright-browser-webkit": {
"name": "@playwright/browser-webkit", "name": "@playwright/browser-webkit",
"version": "1.43.0-next", "version": "1.43.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"engines": { "engines": {
"node": ">=16" "node": ">=16"
} }
}, },
"packages/playwright-chromium": { "packages/playwright-chromium": {
"version": "1.43.0-next", "version": "1.43.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -8202,7 +8202,7 @@
} }
}, },
"packages/playwright-core": { "packages/playwright-core": {
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"playwright-core": "cli.js" "playwright-core": "cli.js"
@ -8213,12 +8213,12 @@
}, },
"packages/playwright-ct-core": { "packages/playwright-ct-core": {
"name": "@playwright/experimental-ct-core", "name": "@playwright/experimental-ct-core",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright": "1.43.0-next", "playwright": "1.43.1",
"playwright-core": "1.43.0-next", "playwright-core": "1.43.1",
"vite": "^5.0.12" "vite": "^5.0.13"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -8229,10 +8229,10 @@
}, },
"packages/playwright-ct-react": { "packages/playwright-ct-react": {
"name": "@playwright/experimental-ct-react", "name": "@playwright/experimental-ct-react",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-react": "^4.2.1" "@vitejs/plugin-react": "^4.2.1"
}, },
"bin": { "bin": {
@ -8244,10 +8244,10 @@
}, },
"packages/playwright-ct-react17": { "packages/playwright-ct-react17": {
"name": "@playwright/experimental-ct-react17", "name": "@playwright/experimental-ct-react17",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-react": "^4.2.1" "@vitejs/plugin-react": "^4.2.1"
}, },
"bin": { "bin": {
@ -8259,10 +8259,10 @@
}, },
"packages/playwright-ct-solid": { "packages/playwright-ct-solid": {
"name": "@playwright/experimental-ct-solid", "name": "@playwright/experimental-ct-solid",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"vite-plugin-solid": "^2.7.0" "vite-plugin-solid": "^2.7.0"
}, },
"bin": { "bin": {
@ -8277,10 +8277,10 @@
}, },
"packages/playwright-ct-svelte": { "packages/playwright-ct-svelte": {
"name": "@playwright/experimental-ct-svelte", "name": "@playwright/experimental-ct-svelte",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@sveltejs/vite-plugin-svelte": "^3.0.1" "@sveltejs/vite-plugin-svelte": "^3.0.1"
}, },
"bin": { "bin": {
@ -8295,10 +8295,10 @@
}, },
"packages/playwright-ct-vue": { "packages/playwright-ct-vue": {
"name": "@playwright/experimental-ct-vue", "name": "@playwright/experimental-ct-vue",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-vue": "^4.2.1" "@vitejs/plugin-vue": "^4.2.1"
}, },
"bin": { "bin": {
@ -8310,10 +8310,10 @@
}, },
"packages/playwright-ct-vue2": { "packages/playwright-ct-vue2": {
"name": "@playwright/experimental-ct-vue2", "name": "@playwright/experimental-ct-vue2",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-vue2": "^2.2.0" "@vitejs/plugin-vue2": "^2.2.0"
}, },
"bin": { "bin": {
@ -8362,11 +8362,11 @@
} }
}, },
"packages/playwright-firefox": { "packages/playwright-firefox": {
"version": "1.43.0-next", "version": "1.43.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -8377,10 +8377,10 @@
}, },
"packages/playwright-test": { "packages/playwright-test": {
"name": "@playwright/test", "name": "@playwright/test",
"version": "1.43.0-next", "version": "1.43.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright": "1.43.0-next" "playwright": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -8390,11 +8390,11 @@
} }
}, },
"packages/playwright-webkit": { "packages/playwright-webkit": {
"version": "1.43.0-next", "version": "1.43.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"

View file

@ -1,7 +1,7 @@
{ {
"name": "playwright-internal", "name": "playwright-internal",
"private": true, "private": true,
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -99,7 +99,7 @@
"socksv5": "0.0.6", "socksv5": "0.0.6",
"ssim.js": "^3.5.0", "ssim.js": "^3.5.0",
"typescript": "^5.3.2", "typescript": "^5.3.2",
"vite": "^5.0.12", "vite": "^5.0.13",
"ws": "^8.5.0", "ws": "^8.5.0",
"xml2js": "^0.5.0", "xml2js": "^0.5.0",
"yaml": "^2.2.2" "yaml": "^2.2.2"

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/browser-chromium", "name": "@playwright/browser-chromium",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright package that automatically installs Chromium", "description": "Playwright package that automatically installs Chromium",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,6 +27,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/browser-firefox", "name": "@playwright/browser-firefox",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright package that automatically installs Firefox", "description": "Playwright package that automatically installs Firefox",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,6 +27,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/browser-webkit", "name": "@playwright/browser-webkit",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright package that automatically installs WebKit", "description": "Playwright package that automatically installs WebKit",
"repository": { "repository": {
"type": "git", "type": "git",
@ -27,6 +27,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-chromium", "name": "playwright-chromium",
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate Chromium", "description": "A high-level API to automate Chromium",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
} }
} }

View file

@ -3,9 +3,9 @@
"browsers": [ "browsers": [
{ {
"name": "chromium", "name": "chromium",
"revision": "1110", "revision": "1112",
"installByDefault": true, "installByDefault": true,
"browserVersion": "124.0.6367.8" "browserVersion": "124.0.6367.29"
}, },
{ {
"name": "chromium-tip-of-tree", "name": "chromium-tip-of-tree",

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-core", "name": "playwright-core",
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -110,7 +110,7 @@
"defaultBrowserType": "webkit" "defaultBrowserType": "webkit"
}, },
"Galaxy S5": { "Galaxy S5": {
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 360, "width": 360,
"height": 640 "height": 640
@ -121,7 +121,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy S5 landscape": { "Galaxy S5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 360 "height": 360
@ -132,7 +132,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy S8": { "Galaxy S8": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 360, "width": 360,
"height": 740 "height": 740
@ -143,7 +143,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy S8 landscape": { "Galaxy S8 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 740, "width": 740,
"height": 360 "height": 360
@ -154,7 +154,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy S9+": { "Galaxy S9+": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 320, "width": 320,
"height": 658 "height": 658
@ -165,7 +165,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy S9+ landscape": { "Galaxy S9+ landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 658, "width": 658,
"height": 320 "height": 320
@ -176,7 +176,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy Tab S4": { "Galaxy Tab S4": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"viewport": { "viewport": {
"width": 712, "width": 712,
"height": 1138 "height": 1138
@ -187,7 +187,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Galaxy Tab S4 landscape": { "Galaxy Tab S4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"viewport": { "viewport": {
"width": 1138, "width": 1138,
"height": 712 "height": 712
@ -978,7 +978,7 @@
"defaultBrowserType": "webkit" "defaultBrowserType": "webkit"
}, },
"LG Optimus L70": { "LG Optimus L70": {
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 384, "width": 384,
"height": 640 "height": 640
@ -989,7 +989,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"LG Optimus L70 landscape": { "LG Optimus L70 landscape": {
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 384 "height": 384
@ -1000,7 +1000,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Microsoft Lumia 550": { "Microsoft Lumia 550": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36 Edge/14.14263", "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36 Edge/14.14263",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 360 "height": 360
@ -1011,7 +1011,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Microsoft Lumia 550 landscape": { "Microsoft Lumia 550 landscape": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36 Edge/14.14263", "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36 Edge/14.14263",
"viewport": { "viewport": {
"width": 360, "width": 360,
"height": 640 "height": 640
@ -1022,7 +1022,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Microsoft Lumia 950": { "Microsoft Lumia 950": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36 Edge/14.14263", "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36 Edge/14.14263",
"viewport": { "viewport": {
"width": 360, "width": 360,
"height": 640 "height": 640
@ -1033,7 +1033,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Microsoft Lumia 950 landscape": { "Microsoft Lumia 950 landscape": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36 Edge/14.14263", "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36 Edge/14.14263",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 360 "height": 360
@ -1044,7 +1044,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 10": { "Nexus 10": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"viewport": { "viewport": {
"width": 800, "width": 800,
"height": 1280 "height": 1280
@ -1055,7 +1055,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 10 landscape": { "Nexus 10 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"viewport": { "viewport": {
"width": 1280, "width": 1280,
"height": 800 "height": 800
@ -1066,7 +1066,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 4": { "Nexus 4": {
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 384, "width": 384,
"height": 640 "height": 640
@ -1077,7 +1077,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 4 landscape": { "Nexus 4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 384 "height": 384
@ -1088,7 +1088,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 5": { "Nexus 5": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 360, "width": 360,
"height": 640 "height": 640
@ -1099,7 +1099,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 5 landscape": { "Nexus 5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 360 "height": 360
@ -1110,7 +1110,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 5X": { "Nexus 5X": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 412, "width": 412,
"height": 732 "height": 732
@ -1121,7 +1121,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 5X landscape": { "Nexus 5X landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 732, "width": 732,
"height": 412 "height": 412
@ -1132,7 +1132,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 6": { "Nexus 6": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 412, "width": 412,
"height": 732 "height": 732
@ -1143,7 +1143,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 6 landscape": { "Nexus 6 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 732, "width": 732,
"height": 412 "height": 412
@ -1154,7 +1154,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 6P": { "Nexus 6P": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 412, "width": 412,
"height": 732 "height": 732
@ -1165,7 +1165,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 6P landscape": { "Nexus 6P landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 732, "width": 732,
"height": 412 "height": 412
@ -1176,7 +1176,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 7": { "Nexus 7": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"viewport": { "viewport": {
"width": 600, "width": 600,
"height": 960 "height": 960
@ -1187,7 +1187,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Nexus 7 landscape": { "Nexus 7 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"viewport": { "viewport": {
"width": 960, "width": 960,
"height": 600 "height": 600
@ -1242,7 +1242,7 @@
"defaultBrowserType": "webkit" "defaultBrowserType": "webkit"
}, },
"Pixel 2": { "Pixel 2": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 411, "width": 411,
"height": 731 "height": 731
@ -1253,7 +1253,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 2 landscape": { "Pixel 2 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 731, "width": 731,
"height": 411 "height": 411
@ -1264,7 +1264,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 2 XL": { "Pixel 2 XL": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 411, "width": 411,
"height": 823 "height": 823
@ -1275,7 +1275,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 2 XL landscape": { "Pixel 2 XL landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 823, "width": 823,
"height": 411 "height": 411
@ -1286,7 +1286,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 3": { "Pixel 3": {
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 393, "width": 393,
"height": 786 "height": 786
@ -1297,7 +1297,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 3 landscape": { "Pixel 3 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 786, "width": 786,
"height": 393 "height": 393
@ -1308,7 +1308,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 4": { "Pixel 4": {
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 353, "width": 353,
"height": 745 "height": 745
@ -1319,7 +1319,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 4 landscape": { "Pixel 4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 745, "width": 745,
"height": 353 "height": 353
@ -1330,7 +1330,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 4a (5G)": { "Pixel 4a (5G)": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"screen": { "screen": {
"width": 412, "width": 412,
"height": 892 "height": 892
@ -1345,7 +1345,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 4a (5G) landscape": { "Pixel 4a (5G) landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"screen": { "screen": {
"height": 892, "height": 892,
"width": 412 "width": 412
@ -1360,7 +1360,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 5": { "Pixel 5": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"screen": { "screen": {
"width": 393, "width": 393,
"height": 851 "height": 851
@ -1375,7 +1375,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 5 landscape": { "Pixel 5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"screen": { "screen": {
"width": 851, "width": 851,
"height": 393 "height": 393
@ -1390,7 +1390,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 7": { "Pixel 7": {
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"screen": { "screen": {
"width": 412, "width": 412,
"height": 915 "height": 915
@ -1405,7 +1405,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Pixel 7 landscape": { "Pixel 7 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"screen": { "screen": {
"width": 915, "width": 915,
"height": 412 "height": 412
@ -1420,7 +1420,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Moto G4": { "Moto G4": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 360, "width": 360,
"height": 640 "height": 640
@ -1431,7 +1431,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Moto G4 landscape": { "Moto G4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Mobile Safari/537.36", "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Mobile Safari/537.36",
"viewport": { "viewport": {
"width": 640, "width": 640,
"height": 360 "height": 360
@ -1442,7 +1442,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Desktop Chrome HiDPI": { "Desktop Chrome HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"screen": { "screen": {
"width": 1792, "width": 1792,
"height": 1120 "height": 1120
@ -1457,7 +1457,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Desktop Edge HiDPI": { "Desktop Edge HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36 Edg/124.0.6367.8", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36 Edg/124.0.6367.29",
"screen": { "screen": {
"width": 1792, "width": 1792,
"height": 1120 "height": 1120
@ -1502,7 +1502,7 @@
"defaultBrowserType": "webkit" "defaultBrowserType": "webkit"
}, },
"Desktop Chrome": { "Desktop Chrome": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36",
"screen": { "screen": {
"width": 1920, "width": 1920,
"height": 1080 "height": 1080
@ -1517,7 +1517,7 @@
"defaultBrowserType": "chromium" "defaultBrowserType": "chromium"
}, },
"Desktop Edge": { "Desktop Edge": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.8 Safari/537.36 Edg/124.0.6367.8", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.29 Safari/537.36 Edg/124.0.6367.29",
"screen": { "screen": {
"width": 1920, "width": 1920,
"height": 1080 "height": 1080

View file

@ -1692,17 +1692,6 @@ export class Frame extends SdkObject {
if (db.name) if (db.name)
indexedDB.deleteDatabase(db.name!); indexedDB.deleteDatabase(db.name!);
} }
// Clean StorageManager
const root = await navigator.storage.getDirectory();
const entries = await (root as any).entries();
// Manual loop instead of for await because in Firefox's utility context instanceof AsyncIterable is not working.
let entry = await entries.next();
while (!entry.done) {
const [name] = entry.value;
await root.removeEntry(name, { recursive: true });
entry = await entries.next();
}
}, { ls: newStorage?.localStorage }).catch(() => {}); }, { ls: newStorage?.localStorage }).catch(() => {});
} }

View file

@ -222,14 +222,13 @@ class StdinServer implements Transport {
} }
async dispatch(method: string, params: any) { async dispatch(method: string, params: any) {
if (method === 'ready') { if (method === 'initialize') {
if (this._traceUrl) if (this._traceUrl)
this._loadTrace(this._traceUrl); this._loadTrace(this._traceUrl);
} }
} }
onclose() { onclose() {
gracefullyProcessExitDoNotHang(0);
} }
sendEvent?: (method: string, params: any) => void; sendEvent?: (method: string, params: any) => void;

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-core", "name": "@playwright/experimental-ct-core",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing Helpers", "description": "Playwright Component Testing Helpers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -26,9 +26,9 @@
} }
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next", "playwright-core": "1.43.1",
"vite": "^5.0.12", "vite": "^5.0.13",
"playwright": "1.43.0-next" "playwright": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"

View file

@ -21,7 +21,7 @@ import { runDevServer } from './devServer';
export { program } from 'playwright/lib/program'; export { program } from 'playwright/lib/program';
function addDevServerCommand(program: Command) { function addDevServerCommand(program: Command) {
const command = program.command('dev-server'); const command = program.command('dev-server', { hidden: true });
command.description('start dev server'); command.description('start dev server');
command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`); command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
command.action(options => { command.action(options => {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-react", "name": "@playwright/experimental-ct-react",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing for React", "description": "Playwright Component Testing for React",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-react": "^4.2.1" "@vitejs/plugin-react": "^4.2.1"
}, },
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-react17", "name": "@playwright/experimental-ct-react17",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing for React", "description": "Playwright Component Testing for React",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-react": "^4.2.1" "@vitejs/plugin-react": "^4.2.1"
}, },
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-solid", "name": "@playwright/experimental-ct-solid",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing for Solid", "description": "Playwright Component Testing for Solid",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"vite-plugin-solid": "^2.7.0" "vite-plugin-solid": "^2.7.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-svelte", "name": "@playwright/experimental-ct-svelte",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing for Svelte", "description": "Playwright Component Testing for Svelte",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@sveltejs/vite-plugin-svelte": "^3.0.1" "@sveltejs/vite-plugin-svelte": "^3.0.1"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-vue", "name": "@playwright/experimental-ct-vue",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing for Vue", "description": "Playwright Component Testing for Vue",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-vue": "^4.2.1" "@vitejs/plugin-vue": "^4.2.1"
}, },
"bin": { "bin": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-vue2", "name": "@playwright/experimental-ct-vue2",
"version": "1.43.0-next", "version": "1.43.1",
"description": "Playwright Component Testing for Vue2", "description": "Playwright Component Testing for Vue2",
"repository": { "repository": {
"type": "git", "type": "git",
@ -29,7 +29,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/experimental-ct-core": "1.43.0-next", "@playwright/experimental-ct-core": "1.43.1",
"@vitejs/plugin-vue2": "^2.2.0" "@vitejs/plugin-vue2": "^2.2.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-firefox", "name": "playwright-firefox",
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate Firefox", "description": "A high-level API to automate Firefox",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/test", "name": "@playwright/test",
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
}, },
"scripts": {}, "scripts": {},
"dependencies": { "dependencies": {
"playwright": "1.43.0-next" "playwright": "1.43.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-webkit", "name": "playwright-webkit",
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate WebKit", "description": "A high-level API to automate WebKit",
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,6 +30,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright", "name": "playwright",
"version": "1.43.0-next", "version": "1.43.1",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": { "repository": {
"type": "git", "type": "git",
@ -58,7 +58,7 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.43.0-next" "playwright-core": "1.43.1"
}, },
"optionalDependencies": { "optionalDependencies": {
"fsevents": "2.3.2" "fsevents": "2.3.2"

View file

@ -130,6 +130,7 @@ type TeleReporterReceiverOptions = {
}; };
export class TeleReporterReceiver { export class TeleReporterReceiver {
public isListing = false;
private _rootSuite: TeleSuite; private _rootSuite: TeleSuite;
private _options: TeleReporterReceiverOptions; private _options: TeleReporterReceiverOptions;
private _reporter: Partial<ReporterV2>; private _reporter: Partial<ReporterV2>;
@ -143,12 +144,6 @@ export class TeleReporterReceiver {
this._reporter = reporter; this._reporter = reporter;
} }
reset() {
this._rootSuite.suites = [];
this._rootSuite.tests = [];
this._tests.clear();
}
dispatch(message: JsonEvent): Promise<void> | void { dispatch(message: JsonEvent): Promise<void> | void {
const { method, params } = message; const { method, params } = message;
if (method === 'onConfigure') { if (method === 'onConfigure') {
@ -209,6 +204,28 @@ export class TeleReporterReceiver {
// Always update project in watch mode. // Always update project in watch mode.
projectSuite._project = this._parseProject(project); projectSuite._project = this._parseProject(project);
this._mergeSuitesInto(project.suites, projectSuite); this._mergeSuitesInto(project.suites, projectSuite);
// Remove deleted tests when listing. Empty suites will be auto-filtered
// in the UI layer.
if (this.isListing) {
const testIds = new Set<string>();
const collectIds = (suite: JsonSuite) => {
suite.tests.map(t => t.testId).forEach(testId => testIds.add(testId));
suite.suites.forEach(collectIds);
};
project.suites.forEach(collectIds);
const filterTests = (suite: TeleSuite) => {
suite.tests = suite.tests.filter(t => {
if (testIds.has(t.id))
return true;
this._tests.delete(t.id);
return false;
});
suite.suites.forEach(filterTests);
};
filterTests(projectSuite);
}
} }
private _onBegin() { private _onBegin() {

View file

@ -64,10 +64,7 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
}); });
const pingInterval = setInterval(() => this._sendMessage('ping').catch(() => {}), 30000); const pingInterval = setInterval(() => this._sendMessage('ping').catch(() => {}), 30000);
this._connectedPromise = new Promise<void>((f, r) => { this._connectedPromise = new Promise<void>((f, r) => {
this._ws.addEventListener('open', () => { this._ws.addEventListener('open', () => f());
f();
this._ws.send(JSON.stringify({ id: -1, method: 'ready' }));
});
this._ws.addEventListener('error', r); this._ws.addEventListener('error', r);
}); });
this._ws.addEventListener('close', () => { this._ws.addEventListener('close', () => {
@ -76,10 +73,6 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
}); });
} }
connect() {
return this._connectedPromise;
}
private async _sendMessage(method: string, params?: any): Promise<any> { private async _sendMessage(method: string, params?: any): Promise<any> {
const logForTest = (globalThis as any).__logForTest; const logForTest = (globalThis as any).__logForTest;
logForTest?.({ method, params }); logForTest?.({ method, params });
@ -110,16 +103,16 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
this._onLoadTraceRequestedEmitter.fire(params); this._onLoadTraceRequestedEmitter.fire(params);
} }
async setSerializer(params: { serializer: string; }): Promise<void> { async initialize(params: Parameters<TestServerInterface['initialize']>[0]): ReturnType<TestServerInterface['initialize']> {
await this._sendMessage('setSerializer', params); await this._sendMessage('initialize', params);
} }
async ping(params: Parameters<TestServerInterface['ping']>[0]): ReturnType<TestServerInterface['ping']> { async ping(params: Parameters<TestServerInterface['ping']>[0]): ReturnType<TestServerInterface['ping']> {
await this._sendMessage('ping'); await this._sendMessage('ping', params);
} }
async pingNoReply(params: Parameters<TestServerInterface['ping']>[0]) { async pingNoReply(params: Parameters<TestServerInterface['ping']>[0]) {
this._sendMessageNoReply('ping'); this._sendMessageNoReply('ping', params);
} }
async watch(params: Parameters<TestServerInterface['watch']>[0]): ReturnType<TestServerInterface['watch']> { async watch(params: Parameters<TestServerInterface['watch']>[0]): ReturnType<TestServerInterface['watch']> {
@ -130,10 +123,6 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
this._sendMessageNoReply('watch', params); this._sendMessageNoReply('watch', params);
} }
async watchTestDir(params: Parameters<TestServerInterface['watchTestDir']>[0]): ReturnType<TestServerInterface['watchTestDir']> {
await this._sendMessage('watchTestDir', params);
}
async open(params: Parameters<TestServerInterface['open']>[0]): ReturnType<TestServerInterface['open']> { async open(params: Parameters<TestServerInterface['open']>[0]): ReturnType<TestServerInterface['open']> {
await this._sendMessage('open', params); await this._sendMessage('open', params);
} }
@ -151,19 +140,19 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
} }
async checkBrowsers(params: Parameters<TestServerInterface['checkBrowsers']>[0]): ReturnType<TestServerInterface['checkBrowsers']> { async checkBrowsers(params: Parameters<TestServerInterface['checkBrowsers']>[0]): ReturnType<TestServerInterface['checkBrowsers']> {
return await this._sendMessage('checkBrowsers'); return await this._sendMessage('checkBrowsers', params);
} }
async installBrowsers(params: Parameters<TestServerInterface['installBrowsers']>[0]): ReturnType<TestServerInterface['installBrowsers']> { async installBrowsers(params: Parameters<TestServerInterface['installBrowsers']>[0]): ReturnType<TestServerInterface['installBrowsers']> {
await this._sendMessage('installBrowsers'); await this._sendMessage('installBrowsers', params);
} }
async runGlobalSetup(params: Parameters<TestServerInterface['runGlobalSetup']>[0]): ReturnType<TestServerInterface['runGlobalSetup']> { async runGlobalSetup(params: Parameters<TestServerInterface['runGlobalSetup']>[0]): ReturnType<TestServerInterface['runGlobalSetup']> {
return await this._sendMessage('runGlobalSetup'); return await this._sendMessage('runGlobalSetup', params);
} }
async runGlobalTeardown(params: Parameters<TestServerInterface['runGlobalTeardown']>[0]): ReturnType<TestServerInterface['runGlobalTeardown']> { async runGlobalTeardown(params: Parameters<TestServerInterface['runGlobalTeardown']>[0]): ReturnType<TestServerInterface['runGlobalTeardown']> {
return await this._sendMessage('runGlobalTeardown'); return await this._sendMessage('runGlobalTeardown', params);
} }
async listFiles(params: Parameters<TestServerInterface['listFiles']>[0]): ReturnType<TestServerInterface['listFiles']> { async listFiles(params: Parameters<TestServerInterface['listFiles']>[0]): ReturnType<TestServerInterface['listFiles']> {
@ -183,14 +172,21 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
} }
async stopTests(params: Parameters<TestServerInterface['stopTests']>[0]): ReturnType<TestServerInterface['stopTests']> { async stopTests(params: Parameters<TestServerInterface['stopTests']>[0]): ReturnType<TestServerInterface['stopTests']> {
await this._sendMessage('stopTests'); await this._sendMessage('stopTests', params);
} }
stopTestsNoReply(params: Parameters<TestServerInterface['stopTests']>[0]) { stopTestsNoReply(params: Parameters<TestServerInterface['stopTests']>[0]) {
this._sendMessageNoReply('stopTests'); this._sendMessageNoReply('stopTests', params);
} }
async closeGracefully(params: Parameters<TestServerInterface['closeGracefully']>[0]): ReturnType<TestServerInterface['closeGracefully']> { async closeGracefully(params: Parameters<TestServerInterface['closeGracefully']>[0]): ReturnType<TestServerInterface['closeGracefully']> {
await this._sendMessage('closeGracefully'); await this._sendMessage('closeGracefully', params);
}
close() {
try {
this._ws.close();
} catch {
}
} }
} }

View file

@ -21,7 +21,12 @@ import type { JsonEvent } from './teleReceiver';
export type ReportEntry = JsonEvent; export type ReportEntry = JsonEvent;
export interface TestServerInterface { export interface TestServerInterface {
setSerializer(params: { serializer: string }): Promise<void>; initialize(params: {
serializer?: string,
closeOnDisconnect?: boolean,
interceptStdio?: boolean,
watchTestDirs?: boolean,
}): Promise<void>;
ping(params: {}): Promise<void>; ping(params: {}): Promise<void>;
@ -29,8 +34,6 @@ export interface TestServerInterface {
fileNames: string[]; fileNames: string[];
}): Promise<void>; }): Promise<void>;
watchTestDir(params: {}): Promise<void>;
open(params: { location: reporterTypes.Location }): Promise<void>; open(params: { location: reporterTypes.Location }): Promise<void>;
resizeTerminal(params: { cols: number, rows: number }): Promise<void>; resizeTerminal(params: { cols: number, rows: number }): Promise<void>;

View file

@ -295,20 +295,7 @@ export class TestTree {
} }
collectTestIds(treeItem?: TreeItem): Set<string> { collectTestIds(treeItem?: TreeItem): Set<string> {
const testIds = new Set<string>(); return treeItem ? collectTestIds(treeItem) : new Set();
if (!treeItem)
return testIds;
const visit = (treeItem: TreeItem) => {
if (treeItem.kind === 'case')
treeItem.tests.map(t => t.id).forEach(id => testIds.add(id));
else if (treeItem.kind === 'test')
testIds.add(treeItem.id);
else
treeItem.children?.forEach(visit);
};
visit(treeItem);
return testIds;
} }
} }
@ -349,4 +336,18 @@ export function sortAndPropagateStatus(treeItem: TreeItem) {
treeItem.status = 'passed'; treeItem.status = 'passed';
} }
export function collectTestIds(treeItem: TreeItem): Set<string> {
const testIds = new Set<string>();
const visit = (treeItem: TreeItem) => {
if (treeItem.kind === 'case')
treeItem.tests.map(t => t.id).forEach(id => testIds.add(id));
else if (treeItem.kind === 'test')
testIds.add(treeItem.id);
else
treeItem.children?.forEach(visit);
};
visit(treeItem);
return testIds;
}
export const statusEx = Symbol('statusEx'); export const statusEx = Symbol('statusEx');

View file

@ -169,6 +169,8 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
timeout: cliOverrides.timeout, timeout: cliOverrides.timeout,
}); });
await stopProfiling('runner'); await stopProfiling('runner');
if (status === 'restarted')
return;
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1); const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
gracefullyProcessExitDoNotHang(exitCode); gracefullyProcessExitDoNotHang(exitCode);
return; return;
@ -200,6 +202,8 @@ async function runTestServer(opts: { [key: string]: any }) {
const host = opts.host || 'localhost'; const host = opts.host || 'localhost';
const port = opts.port ? +opts.port : 0; const port = opts.port ? +opts.port : 0;
const status = await testServer.runTestServer(opts.config, { host, port }); const status = await testServer.runTestServer(opts.config, { host, port });
if (status === 'restarted')
return;
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1); const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
gracefullyProcessExitDoNotHang(exitCode); gracefullyProcessExitDoNotHang(exitCode);
} }

View file

@ -85,7 +85,6 @@ export function createTaskRunnerForWatch(config: FullConfigInternal, reporter: R
export function createTaskRunnerForTestServer(config: FullConfigInternal, reporter: ReporterV2): TaskRunner<TestRun> { export function createTaskRunnerForTestServer(config: FullConfigInternal, reporter: ReporterV2): TaskRunner<TestRun> {
const taskRunner = new TaskRunner<TestRun>(reporter, 0); const taskRunner = new TaskRunner<TestRun>(reporter, 0);
addGlobalSetupTasks(taskRunner, config);
taskRunner.addTask('load tests', createLoadTask('out-of-process', { filterOnly: true, failOnLoadErrors: false, doNotRunDepsOutsideProjectFilter: true })); taskRunner.addTask('load tests', createLoadTask('out-of-process', { filterOnly: true, failOnLoadErrors: false, doNotRunDepsOutsideProjectFilter: true }));
addRunTasks(taskRunner, config); addRunTasks(taskRunner, config);
return taskRunner; return taskRunner;

View file

@ -39,16 +39,15 @@ import type { TraceViewerRedirectOptions, TraceViewerServerOptions } from 'playw
import type { TestRunnerPluginRegistration } from '../plugins'; import type { TestRunnerPluginRegistration } from '../plugins';
import { serializeError } from '../util'; import { serializeError } from '../util';
const originalStdoutWrite = process.stdout.write;
const originalStderrWrite = process.stderr.write;
class TestServer { class TestServer {
private _configFile: string | undefined; private _configFile: string | undefined;
private _dispatcher: TestServerDispatcher | undefined; private _dispatcher: TestServerDispatcher | undefined;
private _originalStdoutWrite: NodeJS.WriteStream['write'];
private _originalStderrWrite: NodeJS.WriteStream['write'];
constructor(configFile: string | undefined) { constructor(configFile: string | undefined) {
this._configFile = configFile; this._configFile = configFile;
this._originalStdoutWrite = process.stdout.write;
this._originalStderrWrite = process.stderr.write;
} }
async start(options: { host?: string, port?: number }): Promise<HttpServer> { async start(options: { host?: string, port?: number }): Promise<HttpServer> {
@ -57,28 +56,9 @@ class TestServer {
} }
async stop() { async stop() {
await this._dispatcher?._setInterceptStdio(false);
await this._dispatcher?.runGlobalTeardown(); await this._dispatcher?.runGlobalTeardown();
} }
wireStdIO() {
if (!process.env.PWTEST_DEBUG) {
process.stdout.write = (chunk: string | Buffer) => {
this._dispatcher?._dispatchEvent('stdio', chunkToPayload('stdout', chunk));
return true;
};
process.stderr.write = (chunk: string | Buffer) => {
this._dispatcher?._dispatchEvent('stdio', chunkToPayload('stderr', chunk));
return true;
};
}
}
unwireStdIO() {
if (!process.env.PWTEST_DEBUG) {
process.stdout.write = this._originalStdoutWrite;
process.stderr.write = this._originalStderrWrite;
}
}
} }
class TestServerDispatcher implements TestServerInterface { class TestServerDispatcher implements TestServerInterface {
@ -92,13 +72,17 @@ class TestServerDispatcher implements TestServerInterface {
readonly _dispatchEvent: TestServerInterfaceEventEmitters['dispatchEvent']; readonly _dispatchEvent: TestServerInterfaceEventEmitters['dispatchEvent'];
private _plugins: TestRunnerPluginRegistration[] | undefined; private _plugins: TestRunnerPluginRegistration[] | undefined;
private _serializer = require.resolve('./uiModeReporter'); private _serializer = require.resolve('./uiModeReporter');
private _watchTestDir = false; private _watchTestDirs = false;
private _closeOnDisconnect = false;
constructor(configFile: string | undefined) { constructor(configFile: string | undefined) {
this._configFile = configFile; this._configFile = configFile;
this.transport = { this.transport = {
dispatch: (method, params) => (this as any)[method](params), dispatch: (method, params) => (this as any)[method](params),
onclose: () => gracefullyProcessExitDoNotHang(0), onclose: () => {
if (this._closeOnDisconnect)
gracefullyProcessExitDoNotHang(0);
},
}; };
this._globalWatcher = new Watcher('deep', () => this._dispatchEvent('listChanged', {})); this._globalWatcher = new Watcher('deep', () => this._dispatchEvent('listChanged', {}));
this._testWatcher = new Watcher('flat', events => { this._testWatcher = new Watcher('flat', events => {
@ -109,10 +93,6 @@ class TestServerDispatcher implements TestServerInterface {
this._dispatchEvent = (method, params) => this.transport.sendEvent?.(method, params); this._dispatchEvent = (method, params) => this.transport.sendEvent?.(method, params);
} }
async setSerializer(params: { serializer: string; }): Promise<void> {
this._serializer = params.serializer;
}
private async _wireReporter(messageSink: (message: any) => void) { private async _wireReporter(messageSink: (message: any) => void) {
return await createReporterForTestServer(this._serializer, messageSink); return await createReporterForTestServer(this._serializer, messageSink);
} }
@ -124,7 +104,16 @@ class TestServerDispatcher implements TestServerInterface {
return { reporter, report }; return { reporter, report };
} }
async ready() {} async initialize(params: Parameters<TestServerInterface['initialize']>[0]): ReturnType<TestServerInterface['initialize']> {
if (params.serializer)
this._serializer = params.serializer;
if (params.closeOnDisconnect)
this._closeOnDisconnect = true;
if (params.interceptStdio)
await this._setInterceptStdio(true);
if (params.watchTestDirs)
this._watchTestDirs = true;
}
async ping() {} async ping() {}
@ -246,7 +235,7 @@ class TestServerDispatcher implements TestServerInterface {
projectOutputs.add(result.outDir); projectOutputs.add(result.outDir);
} }
if (this._watchTestDir) if (this._watchTestDirs)
this._globalWatcher.update([...projectDirs], [...projectOutputs], false); this._globalWatcher.update([...projectDirs], [...projectOutputs], false);
return { report, status }; return { report, status };
} }
@ -315,10 +304,6 @@ class TestServerDispatcher implements TestServerInterface {
return { status: await run }; return { status: await run };
} }
async watchTestDir() {
this._watchTestDir = true;
}
async watch(params: { fileNames: string[]; }) { async watch(params: { fileNames: string[]; }) {
const files = new Set<string>(); const files = new Set<string>();
for (const fileName of params.fileNames) { for (const fileName of params.fileNames) {
@ -341,6 +326,24 @@ class TestServerDispatcher implements TestServerInterface {
await this._testRun?.run; await this._testRun?.run;
} }
async _setInterceptStdio(intercept: boolean) {
if (process.env.PWTEST_DEBUG)
return;
if (intercept) {
process.stdout.write = (chunk: string | Buffer) => {
this._dispatchEvent('stdio', chunkToPayload('stdout', chunk));
return true;
};
process.stderr.write = (chunk: string | Buffer) => {
this._dispatchEvent('stdio', chunkToPayload('stderr', chunk));
return true;
};
} else {
process.stdout.write = originalStdoutWrite;
process.stderr.write = originalStderrWrite;
}
}
async closeGracefully() { async closeGracefully() {
gracefullyProcessExitDoNotHang(0); gracefullyProcessExitDoNotHang(0);
} }
@ -362,7 +365,7 @@ class TestServerDispatcher implements TestServerInterface {
} }
} }
export async function runUIMode(configFile: string | undefined, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise<reporterTypes.FullResult['status']> { export async function runUIMode(configFile: string | undefined, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
return await innerRunTestServer(configFile, options, async (server: HttpServer, cancelPromise: ManualPromise<void>) => { return await innerRunTestServer(configFile, options, async (server: HttpServer, cancelPromise: ManualPromise<void>) => {
await installRootRedirect(server, [], { ...options, webApp: 'uiMode.html' }); await installRootRedirect(server, [], { ...options, webApp: 'uiMode.html' });
if (options.host !== undefined || options.port !== undefined) { if (options.host !== undefined || options.port !== undefined) {
@ -379,27 +382,26 @@ export async function runUIMode(configFile: string | undefined, options: TraceVi
}); });
} }
export async function runTestServer(configFile: string | undefined, options: { host?: string, port?: number }): Promise<reporterTypes.FullResult['status']> { export async function runTestServer(configFile: string | undefined, options: { host?: string, port?: number }): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
return await innerRunTestServer(configFile, options, async server => { return await innerRunTestServer(configFile, options, async server => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log('Listening on ' + server.urlPrefix().replace('http:', 'ws:') + '/' + server.wsGuid()); console.log('Listening on ' + server.urlPrefix().replace('http:', 'ws:') + '/' + server.wsGuid());
}); });
} }
async function innerRunTestServer(configFile: string | undefined, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise<void>) => Promise<void>): Promise<reporterTypes.FullResult['status']> { async function innerRunTestServer(configFile: string | undefined, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise<void>) => Promise<void>): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
if (restartWithExperimentalTsEsm(undefined, true)) if (restartWithExperimentalTsEsm(undefined, true))
return 'passed'; return 'restarted';
const testServer = new TestServer(configFile); const testServer = new TestServer(configFile);
const cancelPromise = new ManualPromise<void>(); const cancelPromise = new ManualPromise<void>();
const sigintWatcher = new SigIntWatcher(); const sigintWatcher = new SigIntWatcher();
process.stdin.on('close', () => gracefullyProcessExitDoNotHang(0));
void sigintWatcher.promise().then(() => cancelPromise.resolve()); void sigintWatcher.promise().then(() => cancelPromise.resolve());
try { try {
const server = await testServer.start(options); const server = await testServer.start(options);
await openUI(server, cancelPromise); await openUI(server, cancelPromise);
testServer.wireStdIO();
await cancelPromise; await cancelPromise;
} finally { } finally {
testServer.unwireStdIO();
await testServer.stop(); await testServer.stop();
sigintWatcher.disarm(); sigintWatcher.disarm();
} }

View file

@ -29,32 +29,32 @@
font-weight: 600; font-weight: 600;
} }
.light-mode .tag-color-0 { .tag-color-0 {
background-color: #ddf4ff; background-color: #ddf4ff;
color: #0550ae; color: #0550ae;
border: 1px solid #218bff; border: 1px solid #218bff;
} }
.light-mode .tag-color-1 { .tag-color-1 {
background-color: #fff8c5; background-color: #fff8c5;
color: #7d4e00; color: #7d4e00;
border: 1px solid #bf8700; border: 1px solid #bf8700;
} }
.light-mode .tag-color-2 { .tag-color-2 {
background-color: #fbefff; background-color: #fbefff;
color: #6e40c9; color: #6e40c9;
border: 1px solid #a475f9; border: 1px solid #a475f9;
} }
.light-mode .tag-color-3 { .tag-color-3 {
background-color: #ffeff7; background-color: #ffeff7;
color: #99286e; color: #99286e;
border: 1px solid #e85aad; border: 1px solid #e85aad;
} }
.light-mode .tag-color-4 { .tag-color-4 {
background-color: #FFF0EB; background-color: #FFF0EB;
color: #9E2F1C; color: #9E2F1C;
border: 1px solid #EA6045; border: 1px solid #EA6045;
} }
.light-mode .tag-color-5 { .tag-color-5 {
background-color: #fff1e5; background-color: #fff1e5;
color: #9b4215; color: #9b4215;
border: 1px solid #e16f24; border: 1px solid #e16f24;

View file

@ -123,9 +123,10 @@ export class TeleSuiteUpdater {
} }
processListReport(report: any[]) { processListReport(report: any[]) {
this._receiver.reset(); this._receiver.isListing = true;
for (const message of report) for (const message of report)
this._receiver.dispatch(message); this._receiver.dispatch(message);
this._receiver.isListing = false;
} }
processTestReportEvent(message: any) { processTestReportEvent(message: any) {

View file

@ -172,7 +172,10 @@ export const UIModeView: React.FC<{}> = ({
setIsLoading(true); setIsLoading(true);
setWatchedTreeIds({ value: new Set() }); setWatchedTreeIds({ value: new Set() });
(async () => { (async () => {
await testServerConnection.watchTestDir({}); await testServerConnection.initialize({
interceptStdio: true,
watchTestDirs: true
});
const { status } = await testServerConnection.runGlobalSetup({}); const { status } = await testServerConnection.runGlobalSetup({});
if (status !== 'passed') if (status !== 'passed')
return; return;

View file

@ -93,6 +93,7 @@ export const WorkbenchLoader: React.FunctionComponent<{
setDragOver(false); setDragOver(false);
setProcessingErrorMessage(null); setProcessingErrorMessage(null);
}); });
testServerConnection.initialize({}).catch(() => {});
} else if (!newTraceURLs.some(url => url.startsWith('blob:'))) { } else if (!newTraceURLs.some(url => url.startsWith('blob:'))) {
// Don't re-use blob file URLs on page load (results in Fetch error) // Don't re-use blob file URLs on page load (results in Fetch error)
setTraceURLs(newTraceURLs); setTraceURLs(newTraceURLs);

View file

@ -15,16 +15,13 @@
*/ */
import { browserTest, expect } from '../config/browserTest'; import { browserTest, expect } from '../config/browserTest';
import type { BrowserContext, BrowserContextOptions } from '@playwright/test'; import type { BrowserContext } from '@playwright/test';
const test = browserTest.extend<{ reusedContext: (options?: BrowserContextOptions) => Promise<BrowserContext> }>({ const test = browserTest.extend<{ reusedContext: () => Promise<BrowserContext> }>({
reusedContext: async ({ browserType, browser }, use) => { reusedContext: async ({ browserType, browser }, use) => {
await use(async (options: BrowserContextOptions = {}) => { await use(async () => {
const defaultContextOptions = (browserType as any)._defaultContextOptions; const defaultContextOptions = (browserType as any)._defaultContextOptions;
const context = await (browser as any)._newContextForReuse({ const context = await (browser as any)._newContextForReuse(defaultContextOptions);
...defaultContextOptions,
...options,
});
return context; return context;
}); });
}, },
@ -238,33 +235,6 @@ test('should reset mouse position', async ({ reusedContext, browserName, platfor
await expect(page.locator('#two')).toHaveCSS('background-color', 'rgb(0, 0, 255)'); await expect(page.locator('#two')).toHaveCSS('background-color', 'rgb(0, 0, 255)');
}); });
test('should reset Origin Private File System', async ({ reusedContext, httpsServer, browserName }) => {
test.skip(browserName === 'webkit', 'getDirectory is not supported in ephemeral context in WebKit https://github.com/microsoft/playwright/issues/18235#issuecomment-1289792576');
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29901' });
let context = await reusedContext({ ignoreHTTPSErrors: true });
let page = await context.newPage();
await page.goto(httpsServer.EMPTY_PAGE);
await page.evaluate(async () => {
const root = await navigator.storage.getDirectory();
await root.getDirectoryHandle('someDirectoryName', { create: true });
await root.getFileHandle('foo.txt', { create: true });
});
context = await reusedContext({ ignoreHTTPSErrors: true });
page = await context.newPage();
await page.goto(httpsServer.EMPTY_PAGE);
const { directoryExits, fileExits } = await page.evaluate(async () => {
const root = await navigator.storage.getDirectory();
let directoryExits = true, fileExits = true;
await root.getDirectoryHandle('someDirectoryName').catch(() => { directoryExits = false; });
await root.getFileHandle('foo.txt').catch(() => { fileExits = false; });
return { directoryExits, fileExits };
});
expect(directoryExits).toBe(false);
expect(fileExits).toBe(false);
});
test('should reset tracing', async ({ reusedContext, trace }, testInfo) => { test('should reset tracing', async ({ reusedContext, trace }, testInfo) => {
test.skip(trace === 'on'); test.skip(trace === 'on');

View file

@ -129,6 +129,36 @@ test('should pick new / deleted tests', async ({ runUITest, writeFiles, deleteFi
`); `);
}); });
test('should not loose run information after execution if test wrote into testDir', async ({ runUITest, writeFiles, deleteFile }) => {
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30300' });
const { page } = await runUITest({
'a.test.ts': `
import fs from 'fs';
import path from 'path';
import { test, expect } from '@playwright/test';
test('passes', () => {
fs.writeFileSync(path.join(test.info().project.testDir, 'something.txt'), 'hi');
});
`,
});
await expect.poll(dumpTestTree(page)).toBe(`
a.test.ts
passes
`);
await page.getByTitle('passes').click();
await page.getByTitle('Run all').click();
await page.waitForTimeout(5_000);
await expect(page.getByText('Did not run')).toBeHidden();
const listItem = page.getByTestId('actions-tree').getByRole('listitem');
await expect(
listItem,
'action list'
).toHaveText([
/Before Hooks[\d.]+m?s/,
/After Hooks[\d.]+m?s/,
]);
});
test('should pick new / deleted nested tests', async ({ runUITest, writeFiles, deleteFile }) => { test('should pick new / deleted nested tests', async ({ runUITest, writeFiles, deleteFile }) => {
const { page } = await runUITest(basicTestTree); const { page } = await runUITest(basicTestTree);
await expect.poll(dumpTestTree(page)).toContain(` await expect.poll(dumpTestTree(page)).toContain(`