Compare commits
21 commits
main
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a51d4a39b8 | ||
|
|
f11873a895 | ||
|
|
b5ff463779 | ||
|
|
4417a97482 | ||
|
|
2f3d88f3d5 | ||
|
|
ba85623f40 | ||
|
|
fe024dd5e3 | ||
|
|
ac4127d6cf | ||
|
|
b8761ef8de | ||
|
|
55eebadfa2 | ||
|
|
bc9f9b79c8 | ||
|
|
4aee014caf | ||
|
|
bf25a93617 | ||
|
|
7effaf4f22 | ||
|
|
ef18287266 | ||
|
|
552cba8c05 | ||
|
|
cd94a3f01d | ||
|
|
3543a741fd | ||
|
|
7196f82e52 | ||
|
|
32c247b815 | ||
|
|
c551cce74e |
|
|
@ -1,6 +1,6 @@
|
|||
# 🎭 Playwright
|
||||
|
||||
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop -->
|
||||
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop -->
|
||||
|
||||
## [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 |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->114.0.5735.26<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->114.0.5735.35<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->16.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Firefox <!-- GEN:firefox-version -->113.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ Emitted when Browser context gets closed. This might happen because of one of th
|
|||
* The [`method: Browser.close`] method was called.
|
||||
|
||||
## event: BrowserContext.console
|
||||
* since: v1.33
|
||||
* since: v1.34
|
||||
* langs:
|
||||
- alias-java: consoleMessage
|
||||
- argument: <[ConsoleMessage]>
|
||||
|
|
@ -156,7 +156,7 @@ await page.EvaluateAsync("console.log('hello', 5, { foo: 'bar' })");
|
|||
|
||||
|
||||
## event: BrowserContext.dialog
|
||||
* since: v1.33
|
||||
* since: v1.34
|
||||
- argument: <[Dialog]>
|
||||
|
||||
Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must** either [`method: Dialog.accept`] or [`method: Dialog.dismiss`] the dialog - otherwise the page will [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the dialog, and actions like click will never finish.
|
||||
|
|
@ -180,10 +180,7 @@ context.on("dialog", lambda dialog: dialog.accept())
|
|||
```
|
||||
|
||||
```csharp
|
||||
context.RequestFailed += (_, request) =>
|
||||
{
|
||||
Console.WriteLine(request.Url + " " + request.Failure);
|
||||
};
|
||||
context.Dialog += (_, dialog) => dialog.AcceptAsync();
|
||||
```
|
||||
|
||||
:::note
|
||||
|
|
@ -1456,6 +1453,37 @@ Condition to wait for.
|
|||
### option: BrowserContext.waitForCondition.timeout = %%-wait-for-function-timeout-%%
|
||||
* since: v1.32
|
||||
|
||||
## async method: BrowserContext.waitForConsoleMessage
|
||||
* since: v1.34
|
||||
* langs: java, python, csharp
|
||||
- alias-python: expect_console_message
|
||||
- alias-csharp: RunAndWaitForConsoleMessage
|
||||
- returns: <[ConsoleMessage]>
|
||||
|
||||
Performs action and waits for a [ConsoleMessage] to be logged by in the pages in the context. If predicate is provided, it passes
|
||||
[ConsoleMessage] value into the `predicate` function and waits for `predicate(message)` to return a truthy value.
|
||||
Will throw an error if the page is closed before the [`event: BrowserContext.console`] event is fired.
|
||||
|
||||
## async method: BrowserContext.waitForConsoleMessage
|
||||
* since: v1.34
|
||||
* langs: python
|
||||
- returns: <[EventContextManager]<[ConsoleMessage]>>
|
||||
|
||||
### param: BrowserContext.waitForConsoleMessage.action = %%-csharp-wait-for-event-action-%%
|
||||
* since: v1.34
|
||||
|
||||
### option: BrowserContext.waitForConsoleMessage.predicate
|
||||
* since: v1.34
|
||||
- `predicate` <[function]\([ConsoleMessage]\):[boolean]>
|
||||
|
||||
Receives the [ConsoleMessage] object and resolves to truthy value when the waiting should resolve.
|
||||
|
||||
### option: BrowserContext.waitForConsoleMessage.timeout = %%-wait-for-event-timeout-%%
|
||||
* since: v1.34
|
||||
|
||||
### param: BrowserContext.waitForConsoleMessage.callback = %%-java-wait-for-event-callback-%%
|
||||
* since: v1.34
|
||||
|
||||
## async method: BrowserContext.waitForEvent
|
||||
* since: v1.8
|
||||
* langs: js, python
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ List of arguments passed to a `console` function call. See also [`event: Page.co
|
|||
URL of the resource followed by 0-based line and column numbers in the resource formatted as `URL:line:column`.
|
||||
|
||||
## method: ConsoleMessage.page
|
||||
* since: v1.33
|
||||
- returns: <[Page]|[null]>
|
||||
* since: v1.34
|
||||
- returns: <[null]|[Page]>
|
||||
|
||||
The page that produced this console message, if any.
|
||||
|
||||
|
|
|
|||
|
|
@ -138,8 +138,8 @@ Returns when the dialog has been dismissed.
|
|||
A message displayed in the dialog.
|
||||
|
||||
## method: Dialog.page
|
||||
* since: v1.33
|
||||
- returns: <[Page]|[null]>
|
||||
* since: v1.34
|
||||
- returns: <[null]|[Page]>
|
||||
|
||||
The page that initiated this dialog, if available.
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ jobs:
|
|||
name: 'Playwright Tests'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
|
|
@ -256,7 +256,7 @@ jobs:
|
|||
name: 'Playwright Tests'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright/python:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright/python:v1.34.3-jammy
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
|
|
@ -284,7 +284,7 @@ jobs:
|
|||
name: 'Playwright Tests'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright/java:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright/java:v1.34.3-jammy
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
|
|
@ -309,7 +309,7 @@ jobs:
|
|||
name: 'Playwright Tests'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright/dotnet:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright/dotnet:v1.34.3-jammy
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup dotnet
|
||||
|
|
@ -338,7 +338,7 @@ jobs:
|
|||
name: 'Playwright Tests - ${{ matrix.project }} - Shard ${{ matrix.shardIndex }} of ${{ matrix.shardTotal }}'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -413,7 +413,7 @@ jobs:
|
|||
- deployment: Run_E2E_Tests
|
||||
pool:
|
||||
vmImage: ubuntu-22.04
|
||||
container: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
container: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
environment: testing
|
||||
strategy:
|
||||
runOnce:
|
||||
|
|
@ -439,7 +439,7 @@ jobs:
|
|||
- deployment: Run_E2E_Tests
|
||||
pool:
|
||||
vmImage: ubuntu-22.04
|
||||
container: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
container: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
environment: testing
|
||||
strategy:
|
||||
runOnce:
|
||||
|
|
@ -483,7 +483,7 @@ Running Playwright on CircleCI is very similar to running on GitHub Actions. In
|
|||
executors:
|
||||
pw-jammy-development:
|
||||
docker:
|
||||
- image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
- image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
```
|
||||
|
||||
Note: When using the docker agent definition, you are specifying the resource class of where playwright runs to the 'medium' tier [here](https://circleci.com/docs/configuration-reference?#docker-execution-environment). The default behavior of Playwright is to set the number of workers to the detected core count (2 in the case of the medium tier). Overriding the number of workers to greater than this number will cause unnecessary timeouts and failures.
|
||||
|
|
@ -507,7 +507,7 @@ to run tests on Jenkins.
|
|||
|
||||
```groovy
|
||||
pipeline {
|
||||
agent { docker { image 'mcr.microsoft.com/playwright:v1.34.0-jammy' } }
|
||||
agent { docker { image 'mcr.microsoft.com/playwright:v1.34.3-jammy' } }
|
||||
stages {
|
||||
stage('e2e-tests') {
|
||||
steps {
|
||||
|
|
@ -525,7 +525,7 @@ pipeline {
|
|||
Bitbucket Pipelines can use public [Docker images as build environments](https://confluence.atlassian.com/bitbucket/use-docker-images-as-build-environments-792298897.html). To run Playwright tests on Bitbucket, use our public Docker image ([see Dockerfile](./docker.md)).
|
||||
|
||||
```yml
|
||||
image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
```
|
||||
|
||||
### GitLab CI
|
||||
|
|
@ -538,7 +538,7 @@ stages:
|
|||
|
||||
tests:
|
||||
stage: test
|
||||
image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
script:
|
||||
...
|
||||
```
|
||||
|
|
@ -554,7 +554,7 @@ stages:
|
|||
|
||||
tests:
|
||||
stage: test
|
||||
image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
parallel: 7
|
||||
script:
|
||||
- npm ci
|
||||
|
|
@ -569,7 +569,7 @@ stages:
|
|||
|
||||
tests:
|
||||
stage: test
|
||||
image: mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
image: mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
parallel:
|
||||
matrix:
|
||||
- PROJECT: ['chromium', 'webkit']
|
||||
|
|
|
|||
|
|
@ -18,19 +18,19 @@ This Docker image is intended to be used for testing and development purposes on
|
|||
### Pull the image
|
||||
|
||||
```bash js
|
||||
docker pull mcr.microsoft.com/playwright:v1.34.0-jammy
|
||||
docker pull mcr.microsoft.com/playwright:v1.34.3-jammy
|
||||
```
|
||||
|
||||
```bash python
|
||||
docker pull mcr.microsoft.com/playwright/python:v1.34.0-jammy
|
||||
docker pull mcr.microsoft.com/playwright/python:v1.34.3-jammy
|
||||
```
|
||||
|
||||
```bash csharp
|
||||
docker pull mcr.microsoft.com/playwright/dotnet:v1.34.0-jammy
|
||||
docker pull mcr.microsoft.com/playwright/dotnet:v1.34.3-jammy
|
||||
```
|
||||
|
||||
```bash java
|
||||
docker pull mcr.microsoft.com/playwright/java:v1.34.0-jammy
|
||||
docker pull mcr.microsoft.com/playwright/java:v1.34.3-jammy
|
||||
```
|
||||
|
||||
### Run the image
|
||||
|
|
@ -42,19 +42,19 @@ By default, the Docker image will use the `root` user to run the browsers. This
|
|||
On trusted websites, you can avoid creating a separate user and use root for it since you trust the code which will run on the browsers.
|
||||
|
||||
```bash js
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
```bash python
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/python:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/python:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
```bash csharp
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/dotnet:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/dotnet:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
```bash java
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
#### Crawling and scraping
|
||||
|
|
@ -62,19 +62,19 @@ docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v1.34.0-jammy /
|
|||
On untrusted websites, it's recommended to use a separate user for launching the browsers in combination with the seccomp profile. Inside the container or if you are using the Docker image as a base image you have to use `adduser` for it.
|
||||
|
||||
```bash js
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
```bash python
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/python:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/python:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
```bash csharp
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/dotnet:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/dotnet:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
```bash java
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/java:v1.34.0-jammy /bin/bash
|
||||
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/java:v1.34.3-jammy /bin/bash
|
||||
```
|
||||
|
||||
[`seccomp_profile.json`](https://github.com/microsoft/playwright/blob/main/utils/docker/seccomp_profile.json) is needed to run Chromium with sandbox. This is a [default Docker seccomp profile](https://github.com/docker/engine/blob/d0d99b04cf6e00ed3fc27e81fc3d94e7eda70af3/profiles/seccomp/default.json) with extra user namespace cloning permissions:
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
|
|||
|
||||
## Version 1.34
|
||||
|
||||
### New APIs
|
||||
### Highlights
|
||||
|
||||
* UI Mode now shows steps, fixtures and attachments:
|
||||

|
||||
* New property [`property: TestProject.teardown`] to specify a project that needs to run after this
|
||||
and all dependent projects have finished. Teardown is useful to cleanup any resources acquired by this project.
|
||||
|
||||
|
|
@ -46,6 +48,18 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
|
|||
],
|
||||
});
|
||||
```
|
||||
* New method [`expect.configure`](./test-assertions.md#expectconfigure) to
|
||||
create pre-configured expect instance with its own defaults such as `timeout`
|
||||
and `soft`.
|
||||
|
||||
```js
|
||||
const slowExpect = expect.configure({ timeout: 10000 });
|
||||
await slowExpect(locator).toHaveText('Submit');
|
||||
|
||||
// Always do soft assertions.
|
||||
const softExpect = expect.configure({ soft: true });
|
||||
```
|
||||
|
||||
* New options `stderr` and `stdout` in [`property: TestConfig.webServer`] to configure output handling:
|
||||
|
||||
```js title="playwright.config.ts"
|
||||
|
|
|
|||
|
|
@ -526,6 +526,7 @@ export default defineConfig({
|
|||
* since: v1.10
|
||||
- type: <[Object]|[TraceMode]<"off"|"on"|"retain-on-failure"|"on-first-retry">>
|
||||
- `mode` <[TraceMode]<"off"|"on"|"retain-on-failure"|"on-first-retry"|"on-all-retries">> Trace recording mode.
|
||||
- `attachments` ?<[boolean]> Whether to include test attachments. Defaults to true. Optional.
|
||||
- `screenshots` ?<[boolean]> Whether to capture screenshots during tracing. Screenshots are used to build a timeline preview. Defaults to true. Optional.
|
||||
- `snapshots` ?<[boolean]> Whether to capture DOM snapshot on every action. Defaults to true. Optional.
|
||||
- `sources` ?<[boolean]> Whether to include source files for trace actions. Defaults to true. Optional.
|
||||
|
|
|
|||
|
|
@ -128,7 +128,10 @@ defaults such as `timeout` and `soft`.
|
|||
|
||||
```js
|
||||
const slowExpect = expect.configure({ timeout: 10000 });
|
||||
await slowExpect(locator).toHaveText('Submit);
|
||||
await slowExpect(locator).toHaveText('Submit');
|
||||
|
||||
// Always do soft assertions.
|
||||
const softExpect = expect.configure({ soft: true });
|
||||
```
|
||||
|
||||
## expect.poll
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ The snapshot name `example-test-1-chromium-darwin.png` consists of a few parts:
|
|||
If you are not on the same operating system as your CI system, you can use Docker to generate/update the screenshots:
|
||||
|
||||
```bash
|
||||
docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.34.0-jammy /bin/bash
|
||||
docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.34.3-jammy /bin/bash
|
||||
npm install
|
||||
npx playwright test --update-snapshots
|
||||
```
|
||||
|
|
|
|||
78
package-lock.json
generated
78
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "playwright-internal",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "playwright-internal",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
|
|
@ -6197,11 +6197,11 @@
|
|||
}
|
||||
},
|
||||
"packages/playwright": {
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -6211,11 +6211,11 @@
|
|||
}
|
||||
},
|
||||
"packages/playwright-chromium": {
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -6225,7 +6225,7 @@
|
|||
}
|
||||
},
|
||||
"packages/playwright-core": {
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
|
@ -6233,10 +6233,10 @@
|
|||
},
|
||||
"packages/playwright-ct-core": {
|
||||
"name": "@playwright/experimental-ct-core",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/test": "1.34.0-next",
|
||||
"@playwright/test": "1.34.3",
|
||||
"vite": "^4.3.3"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6248,10 +6248,10 @@
|
|||
},
|
||||
"packages/playwright-ct-react": {
|
||||
"name": "@playwright/experimental-ct-react",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-react": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6280,10 +6280,10 @@
|
|||
},
|
||||
"packages/playwright-ct-react17": {
|
||||
"name": "@playwright/experimental-ct-react17",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-react": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6312,10 +6312,10 @@
|
|||
},
|
||||
"packages/playwright-ct-solid": {
|
||||
"name": "@playwright/experimental-ct-solid",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"vite-plugin-solid": "^2.7.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6330,10 +6330,10 @@
|
|||
},
|
||||
"packages/playwright-ct-svelte": {
|
||||
"name": "@playwright/experimental-ct-svelte",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^2.1.1"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6348,10 +6348,10 @@
|
|||
},
|
||||
"packages/playwright-ct-vue": {
|
||||
"name": "@playwright/experimental-ct-vue",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-vue": "^4.2.1"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6399,10 +6399,10 @@
|
|||
},
|
||||
"packages/playwright-ct-vue2": {
|
||||
"name": "@playwright/experimental-ct-vue2",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-vue2": "^2.2.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
@ -6416,11 +6416,11 @@
|
|||
}
|
||||
},
|
||||
"packages/playwright-firefox": {
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -6431,11 +6431,11 @@
|
|||
},
|
||||
"packages/playwright-test": {
|
||||
"name": "@playwright/test",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -6448,11 +6448,11 @@
|
|||
}
|
||||
},
|
||||
"packages/playwright-webkit": {
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -7262,14 +7262,14 @@
|
|||
"@playwright/experimental-ct-core": {
|
||||
"version": "file:packages/playwright-ct-core",
|
||||
"requires": {
|
||||
"@playwright/test": "1.34.0-next",
|
||||
"@playwright/test": "1.34.3",
|
||||
"vite": "^4.3.3"
|
||||
}
|
||||
},
|
||||
"@playwright/experimental-ct-react": {
|
||||
"version": "file:packages/playwright-ct-react",
|
||||
"requires": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-react": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -7289,7 +7289,7 @@
|
|||
"@playwright/experimental-ct-react17": {
|
||||
"version": "file:packages/playwright-ct-react17",
|
||||
"requires": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-react": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -7309,7 +7309,7 @@
|
|||
"@playwright/experimental-ct-solid": {
|
||||
"version": "file:packages/playwright-ct-solid",
|
||||
"requires": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"solid-js": "^1.7.0",
|
||||
"vite-plugin-solid": "^2.7.0"
|
||||
}
|
||||
|
|
@ -7317,7 +7317,7 @@
|
|||
"@playwright/experimental-ct-svelte": {
|
||||
"version": "file:packages/playwright-ct-svelte",
|
||||
"requires": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^2.1.1",
|
||||
"svelte": "^3.55.1"
|
||||
}
|
||||
|
|
@ -7325,7 +7325,7 @@
|
|||
"@playwright/experimental-ct-vue": {
|
||||
"version": "file:packages/playwright-ct-vue",
|
||||
"requires": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-vue": "^4.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -7359,7 +7359,7 @@
|
|||
"@playwright/experimental-ct-vue2": {
|
||||
"version": "file:packages/playwright-ct-vue2",
|
||||
"requires": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-vue2": "^2.2.0",
|
||||
"vue": "^2.7.14"
|
||||
}
|
||||
|
|
@ -7369,7 +7369,7 @@
|
|||
"requires": {
|
||||
"@types/node": "*",
|
||||
"fsevents": "2.3.2",
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
|
|
@ -9663,13 +9663,13 @@
|
|||
"playwright": {
|
||||
"version": "file:packages/playwright",
|
||||
"requires": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
},
|
||||
"playwright-chromium": {
|
||||
"version": "file:packages/playwright-chromium",
|
||||
"requires": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
},
|
||||
"playwright-core": {
|
||||
|
|
@ -9678,13 +9678,13 @@
|
|||
"playwright-firefox": {
|
||||
"version": "file:packages/playwright-firefox",
|
||||
"requires": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
},
|
||||
"playwright-webkit": {
|
||||
"version": "file:packages/playwright-webkit",
|
||||
"requires": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "playwright-internal",
|
||||
"private": true,
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate web browsers",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
background-color: var(--color-canvas-subtle);
|
||||
padding: 0 8px;
|
||||
border-bottom: none;
|
||||
margin-top: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 38px;
|
||||
white-space: nowrap;
|
||||
|
|
|
|||
|
|
@ -108,9 +108,11 @@ export class Filter {
|
|||
if (test.outcome === 'skipped')
|
||||
status = 'skipped';
|
||||
const searchValues: SearchValues = {
|
||||
text: (status + ' ' + test.projectName + ' ' + test.path.join(' ') + ' ' + test.title).toLowerCase(),
|
||||
text: (status + ' ' + test.projectName + ' ' + test.location.file + ' ' + test.path.join(' ') + ' ' + test.title).toLowerCase(),
|
||||
project: test.projectName.toLowerCase(),
|
||||
status: status as any,
|
||||
file: test.location.file,
|
||||
line: String(test.location.line),
|
||||
};
|
||||
(test as any).searchValues = searchValues;
|
||||
}
|
||||
|
|
@ -127,9 +129,14 @@ export class Filter {
|
|||
return false;
|
||||
}
|
||||
if (this.text.length) {
|
||||
const matches = this.text.filter(t => searchValues.text.includes(t)).length === this.text.length;
|
||||
if (!matches)
|
||||
for (const text of this.text) {
|
||||
if (searchValues.text.includes(text))
|
||||
continue;
|
||||
const location = text.split(':');
|
||||
if (location.length === 2 && searchValues.file.includes(location[0]) && searchValues.line.includes(location[1]))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.labels.length) {
|
||||
const matches = this.labels.every(l => searchValues.text?.match(new RegExp(`(\\s|^)${escapeRegExp(l)}(\\s|$)`, 'g')));
|
||||
|
|
@ -145,5 +152,7 @@ type SearchValues = {
|
|||
text: string;
|
||||
project: string;
|
||||
status: 'passed' | 'failed' | 'flaky' | 'skipped';
|
||||
file: string;
|
||||
line: string;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ test('should switch to actual', async ({ mount }) => {
|
|||
for (let i = 0; i < imageCount; ++i) {
|
||||
const image = images.nth(i);
|
||||
const box = await image.boundingBox();
|
||||
expect(box).toEqual({ x: 400, y: 124, width: 200, height: 200 });
|
||||
expect(box).toEqual({ x: 400, y: 108, width: 200, height: 200 });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ test('should switch to expected', async ({ mount }) => {
|
|||
for (let i = 0; i < imageCount; ++i) {
|
||||
const image = images.nth(i);
|
||||
const box = await image.boundingBox();
|
||||
expect(box).toEqual({ x: 400, y: 124, width: 200, height: 200 });
|
||||
expect(box).toEqual({ x: 400, y: 108, width: 200, height: 200 });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -79,5 +79,5 @@ test('should show diff by default', async ({ mount }) => {
|
|||
|
||||
const image = component.locator('img');
|
||||
const box = await image.boundingBox();
|
||||
expect(box).toEqual({ x: 400, y: 124, width: 200, height: 200 });
|
||||
expect(box).toEqual({ x: 400, y: 108, width: 200, height: 200 });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
height: 48px;
|
||||
min-width: 70px;
|
||||
box-shadow: inset 0 -1px 0 var(--color-border-muted) !important;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.tabbed-pane-tab-strip:focus {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
.test-case-duration {
|
||||
flex: none;
|
||||
align-items: center;
|
||||
padding: 0 8px 24px;
|
||||
padding: 0 8px 8px;
|
||||
}
|
||||
|
||||
.test-case-path {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "playwright-chromium",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate Chromium",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -27,6 +27,6 @@
|
|||
"install": "node install.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
"browsers": [
|
||||
{
|
||||
"name": "chromium",
|
||||
"revision": "1063",
|
||||
"revision": "1064",
|
||||
"installByDefault": true,
|
||||
"browserVersion": "114.0.5735.26"
|
||||
"browserVersion": "114.0.5735.35"
|
||||
},
|
||||
{
|
||||
"name": "chromium-with-symbols",
|
||||
"revision": "1063",
|
||||
"revision": "1064",
|
||||
"installByDefault": false,
|
||||
"browserVersion": "114.0.5735.26"
|
||||
"browserVersion": "114.0.5735.35"
|
||||
},
|
||||
{
|
||||
"name": "chromium-tip-of-tree",
|
||||
|
|
|
|||
17
packages/playwright-core/cli.js
Executable file
17
packages/playwright-core/cli.js
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
module.exports = require('playwright-core/lib/cli/cli');
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "playwright-core",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate web browsers",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -35,5 +35,8 @@
|
|||
"./types/protocol": "./types/protocol.d.ts",
|
||||
"./types/structs": "./types/structs.d.ts"
|
||||
},
|
||||
"bin": {
|
||||
"playwright-core": "./cli.js"
|
||||
},
|
||||
"types": "types/types.d.ts"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ const debugLoggerColorMap = {
|
|||
'install': 34, // green
|
||||
'download': 34, // green
|
||||
'browser': 0, // reset
|
||||
'proxy': 92, // purple
|
||||
'socks': 92, // purple
|
||||
'error': 160, // red,
|
||||
'channel:command': 33, // blue
|
||||
'channel:response': 202, // orange
|
||||
'channel:event': 207, // magenta
|
||||
'server': 45, // cyan
|
||||
'server:channel': 34, // green
|
||||
};
|
||||
export type LogName = keyof typeof debugLoggerColorMap;
|
||||
|
||||
|
|
|
|||
|
|
@ -436,7 +436,6 @@ export class SocksProxy extends EventEmitter implements SocksConnectionClient {
|
|||
this._server.listen(port, () => {
|
||||
const port = (this._server.address() as AddressInfo).port;
|
||||
this._port = port;
|
||||
debugLogger.log('proxy', `Starting socks proxy server on port ${port}`);
|
||||
f(port);
|
||||
});
|
||||
});
|
||||
|
|
@ -525,8 +524,10 @@ export class SocksProxyHandler extends EventEmitter {
|
|||
}
|
||||
|
||||
async socketRequested({ uid, host, port }: SocksSocketRequestedPayload): Promise<void> {
|
||||
debugLogger.log('socks', `[${uid}] => request ${host}:${port}`);
|
||||
if (!this._patternMatcher(host, port)) {
|
||||
const payload: SocksSocketFailedPayload = { uid, errorCode: 'ERULESET' };
|
||||
debugLogger.log('socks', `[${uid}] <= pattern error ${payload.errorCode}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksFailed, payload);
|
||||
return;
|
||||
}
|
||||
|
|
@ -543,11 +544,13 @@ export class SocksProxyHandler extends EventEmitter {
|
|||
});
|
||||
socket.on('error', error => {
|
||||
const payload: SocksSocketErrorPayload = { uid, error: error.message };
|
||||
debugLogger.log('socks', `[${uid}] <= network socket error ${payload.error}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksError, payload);
|
||||
this._sockets.delete(uid);
|
||||
});
|
||||
socket.on('end', () => {
|
||||
const payload: SocksSocketEndPayload = { uid };
|
||||
debugLogger.log('socks', `[${uid}] <= network socket closed`);
|
||||
this.emit(SocksProxyHandler.Events.SocksEnd, payload);
|
||||
this._sockets.delete(uid);
|
||||
});
|
||||
|
|
@ -555,9 +558,11 @@ export class SocksProxyHandler extends EventEmitter {
|
|||
const localPort = socket.localPort;
|
||||
this._sockets.set(uid, socket);
|
||||
const payload: SocksSocketConnectedPayload = { uid, host: localAddress, port: localPort };
|
||||
debugLogger.log('socks', `[${uid}] <= connected to network ${payload.host}:${payload.port}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksConnected, payload);
|
||||
} catch (error) {
|
||||
const payload: SocksSocketFailedPayload = { uid, errorCode: error.code };
|
||||
debugLogger.log('socks', `[${uid}] <= connect error ${payload.errorCode}`);
|
||||
this.emit(SocksProxyHandler.Events.SocksFailed, payload);
|
||||
}
|
||||
}
|
||||
|
|
@ -567,6 +572,7 @@ export class SocksProxyHandler extends EventEmitter {
|
|||
}
|
||||
|
||||
socketClosed({ uid }: SocksSocketClosedPayload): void {
|
||||
debugLogger.log('socks', `[${uid}] <= browser socket closed`);
|
||||
this._sockets.get(uid)?.destroy();
|
||||
this._sockets.delete(uid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import type { LaunchOptions } from '../server/types';
|
|||
import { AndroidDevice } from '../server/android/android';
|
||||
import { DebugControllerDispatcher } from '../server/dispatchers/debugControllerDispatcher';
|
||||
import { startProfiling, stopProfiling } from '../utils';
|
||||
import { monotonicTime } from '../utils';
|
||||
import { debugLogger } from '../common/debugLogger';
|
||||
|
||||
export type ClientType = 'controller' | 'playwright' | 'launch-browser' | 'reuse-browser' | 'pre-launched-browser-or-android';
|
||||
|
||||
|
|
@ -46,14 +48,14 @@ export class PlaywrightConnection {
|
|||
private _onClose: () => void;
|
||||
private _dispatcherConnection: DispatcherConnection;
|
||||
private _cleanups: (() => Promise<void>)[] = [];
|
||||
private _debugLog: (m: string) => void;
|
||||
private _id: string;
|
||||
private _disconnected = false;
|
||||
private _preLaunched: PreLaunched;
|
||||
private _options: Options;
|
||||
private _root: DispatcherScope;
|
||||
private _profileName: string;
|
||||
|
||||
constructor(lock: Promise<void>, clientType: ClientType, ws: WebSocket, options: Options, preLaunched: PreLaunched, log: (m: string) => void, onClose: () => void) {
|
||||
constructor(lock: Promise<void>, clientType: ClientType, ws: WebSocket, options: Options, preLaunched: PreLaunched, id: string, onClose: () => void) {
|
||||
this._ws = ws;
|
||||
this._preLaunched = preLaunched;
|
||||
this._options = options;
|
||||
|
|
@ -63,18 +65,25 @@ export class PlaywrightConnection {
|
|||
if (clientType === 'pre-launched-browser-or-android')
|
||||
assert(preLaunched.browser || preLaunched.androidDevice);
|
||||
this._onClose = onClose;
|
||||
this._debugLog = log;
|
||||
this._id = id;
|
||||
this._profileName = `${new Date().toISOString()}-${clientType}`;
|
||||
|
||||
this._dispatcherConnection = new DispatcherConnection();
|
||||
this._dispatcherConnection.onmessage = async message => {
|
||||
await lock;
|
||||
if (ws.readyState !== ws.CLOSING)
|
||||
ws.send(JSON.stringify(message));
|
||||
if (ws.readyState !== ws.CLOSING) {
|
||||
const messageString = JSON.stringify(message);
|
||||
if (debugLogger.isEnabled('server:channel'))
|
||||
debugLogger.log('server:channel', `[${this._id}] ${monotonicTime() * 1000} SEND ► ${messageString}`);
|
||||
ws.send(messageString);
|
||||
}
|
||||
};
|
||||
ws.on('message', async (message: string) => {
|
||||
await lock;
|
||||
this._dispatcherConnection.dispatch(JSON.parse(Buffer.from(message).toString()));
|
||||
const messageString = Buffer.from(message).toString();
|
||||
if (debugLogger.isEnabled('server:channel'))
|
||||
debugLogger.log('server:channel', `[${this._id}] ${monotonicTime() * 1000} ◀ RECV ${messageString}`);
|
||||
this._dispatcherConnection.dispatch(JSON.parse(messageString));
|
||||
});
|
||||
|
||||
ws.on('close', () => this._onDisconnect());
|
||||
|
|
@ -100,7 +109,7 @@ export class PlaywrightConnection {
|
|||
}
|
||||
|
||||
private async _initPlaywrightConnectMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged playwright.connect mode`);
|
||||
debugLogger.log('server', `[${this._id}] engaged playwright.connect mode`);
|
||||
const playwright = createPlaywright('javascript');
|
||||
// Close all launched browsers on disconnect.
|
||||
this._cleanups.push(async () => {
|
||||
|
|
@ -112,7 +121,7 @@ export class PlaywrightConnection {
|
|||
}
|
||||
|
||||
private async _initLaunchBrowserMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged launch mode for "${this._options.browserName}"`);
|
||||
debugLogger.log('server', `[${this._id}] engaged launch mode for "${this._options.browserName}"`);
|
||||
const playwright = createPlaywright('javascript');
|
||||
|
||||
const ownedSocksProxy = await this._createOwnedSocksProxy(playwright);
|
||||
|
|
@ -131,7 +140,7 @@ export class PlaywrightConnection {
|
|||
}
|
||||
|
||||
private async _initPreLaunchedBrowserMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged pre-launched (browser) mode`);
|
||||
debugLogger.log('server', `[${this._id}] engaged pre-launched (browser) mode`);
|
||||
const playwright = this._preLaunched.playwright!;
|
||||
|
||||
// Note: connected client owns the socks proxy and configures the pattern.
|
||||
|
|
@ -154,7 +163,7 @@ export class PlaywrightConnection {
|
|||
}
|
||||
|
||||
private async _initPreLaunchedAndroidMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged pre-launched (Android) mode`);
|
||||
debugLogger.log('server', `[${this._id}] engaged pre-launched (Android) mode`);
|
||||
const playwright = this._preLaunched.playwright!;
|
||||
const androidDevice = this._preLaunched.androidDevice!;
|
||||
androidDevice.on(AndroidDevice.Events.Close, () => {
|
||||
|
|
@ -167,7 +176,7 @@ export class PlaywrightConnection {
|
|||
}
|
||||
|
||||
private _initDebugControllerMode(): DebugControllerDispatcher {
|
||||
this._debugLog(`engaged reuse controller mode`);
|
||||
debugLogger.log('server', `[${this._id}] engaged reuse controller mode`);
|
||||
const playwright = this._preLaunched.playwright!;
|
||||
// Always create new instance based on the reused Playwright instance.
|
||||
return new DebugControllerDispatcher(this._dispatcherConnection, playwright.debugController);
|
||||
|
|
@ -177,7 +186,7 @@ export class PlaywrightConnection {
|
|||
// Note: reuse browser mode does not support socks proxy, because
|
||||
// clients come and go, while the browser stays the same.
|
||||
|
||||
this._debugLog(`engaged reuse browsers mode for ${this._options.browserName}`);
|
||||
debugLogger.log('server', `[${this._id}] engaged reuse browsers mode for ${this._options.browserName}`);
|
||||
const playwright = this._preLaunched.playwright!;
|
||||
|
||||
const requestedOptions = launchOptionsHash(this._options.launchOptions);
|
||||
|
|
@ -232,27 +241,27 @@ export class PlaywrightConnection {
|
|||
const socksProxy = new SocksProxy();
|
||||
socksProxy.setPattern(this._options.socksProxyPattern);
|
||||
playwright.options.socksProxyPort = await socksProxy.listen(0);
|
||||
this._debugLog(`started socks proxy on port ${playwright.options.socksProxyPort}`);
|
||||
debugLogger.log('server', `[${this._id}] started socks proxy on port ${playwright.options.socksProxyPort}`);
|
||||
this._cleanups.push(() => socksProxy.close());
|
||||
return socksProxy;
|
||||
}
|
||||
|
||||
private async _onDisconnect(error?: Error) {
|
||||
this._disconnected = true;
|
||||
this._debugLog(`disconnected. error: ${error}`);
|
||||
debugLogger.log('server', `[${this._id}] disconnected. error: ${error}`);
|
||||
this._root._dispose();
|
||||
this._debugLog(`starting cleanup`);
|
||||
debugLogger.log('server', `[${this._id}] starting cleanup`);
|
||||
for (const cleanup of this._cleanups)
|
||||
await cleanup().catch(() => {});
|
||||
await stopProfiling(this._profileName);
|
||||
this._onClose();
|
||||
this._debugLog(`finished cleanup`);
|
||||
debugLogger.log('server', `[${this._id}] finished cleanup`);
|
||||
}
|
||||
|
||||
async close(reason?: { code: number, reason: string }) {
|
||||
if (this._disconnected)
|
||||
return;
|
||||
this._debugLog(`force closing connection: ${reason?.reason || ''} (${reason?.code || 0})`);
|
||||
debugLogger.log('server', `[${this._id}] force closing connection: ${reason?.reason || ''} (${reason?.code || 0})`);
|
||||
try {
|
||||
this._ws.close(reason?.code, reason?.reason);
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { debug, wsServer } from '../utilsBundle';
|
||||
import { wsServer } from '../utilsBundle';
|
||||
import type { WebSocketServer } from '../utilsBundle';
|
||||
import http from 'http';
|
||||
import type { Browser } from '../server/browser';
|
||||
|
|
@ -26,17 +26,11 @@ import type { LaunchOptions } from '../server/types';
|
|||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import type { AndroidDevice } from '../server/android/android';
|
||||
import { type SocksProxy } from '../common/socksProxy';
|
||||
|
||||
const debugLog = debug('pw:server');
|
||||
import { debugLogger } from '../common/debugLogger';
|
||||
|
||||
let lastConnectionId = 0;
|
||||
const kConnectionSymbol = Symbol('kConnection');
|
||||
|
||||
function newLogger() {
|
||||
const id = ++lastConnectionId;
|
||||
return (message: string) => debugLog(`[id=${id}] ${message}`);
|
||||
}
|
||||
|
||||
type ServerOptions = {
|
||||
path: string;
|
||||
maxConnections: number;
|
||||
|
|
@ -59,6 +53,8 @@ export class PlaywrightServer {
|
|||
}
|
||||
|
||||
async listen(port: number = 0): Promise<string> {
|
||||
debugLogger.log('server', `Server started at ${new Date()}`);
|
||||
|
||||
const server = http.createServer((request: http.IncomingMessage, response: http.ServerResponse) => {
|
||||
if (request.method === 'GET' && request.url === '/json') {
|
||||
response.setHeader('Content-Type', 'application/json');
|
||||
|
|
@ -69,7 +65,7 @@ export class PlaywrightServer {
|
|||
}
|
||||
response.end('Running');
|
||||
});
|
||||
server.on('error', error => debugLog(error));
|
||||
server.on('error', error => debugLogger.log('server', String(error)));
|
||||
|
||||
const wsEndpoint = await new Promise<string>((resolve, reject) => {
|
||||
server.listen(port, () => {
|
||||
|
|
@ -83,7 +79,7 @@ export class PlaywrightServer {
|
|||
}).on('error', reject);
|
||||
});
|
||||
|
||||
debugLog('Listening at ' + wsEndpoint);
|
||||
debugLogger.log('server', 'Listening at ' + wsEndpoint);
|
||||
this._wsServer = new wsServer({ server, path: this._options.path });
|
||||
const browserSemaphore = new Semaphore(this._options.maxConnections);
|
||||
const controllerSemaphore = new Semaphore(1);
|
||||
|
|
@ -107,8 +103,8 @@ export class PlaywrightServer {
|
|||
} catch (e) {
|
||||
}
|
||||
|
||||
const log = newLogger();
|
||||
log(`serving connection: ${request.url}`);
|
||||
const id = String(++lastConnectionId);
|
||||
debugLogger.log('server', `[${id}] serving connection: ${request.url}`);
|
||||
const isDebugControllerClient = !!request.headers['x-playwright-debug-controller'];
|
||||
const shouldReuseBrowser = !!request.headers['x-playwright-reuse-context'];
|
||||
|
||||
|
|
@ -145,7 +141,7 @@ export class PlaywrightServer {
|
|||
androidDevice: this._options.preLaunchedAndroidDevice,
|
||||
socksProxy: this._options.preLaunchedSocksProxy,
|
||||
},
|
||||
log, () => semaphore.release());
|
||||
id, () => semaphore.release());
|
||||
(ws as any)[kConnectionSymbol] = connection;
|
||||
});
|
||||
|
||||
|
|
@ -156,7 +152,7 @@ export class PlaywrightServer {
|
|||
const server = this._wsServer;
|
||||
if (!server)
|
||||
return;
|
||||
debugLog('closing websocket server');
|
||||
debugLogger.log('server', 'closing websocket server');
|
||||
const waitForClose = new Promise(f => server.close(f));
|
||||
// First disconnect all remaining clients.
|
||||
await Promise.all(Array.from(server.clients).map(async ws => {
|
||||
|
|
@ -169,15 +165,15 @@ export class PlaywrightServer {
|
|||
}
|
||||
}));
|
||||
await waitForClose;
|
||||
debugLog('closing http server');
|
||||
debugLogger.log('server', 'closing http server');
|
||||
await new Promise(f => server.options.server!.close(f));
|
||||
this._wsServer = undefined;
|
||||
debugLog('closed server');
|
||||
debugLogger.log('server', 'closed server');
|
||||
|
||||
debugLog('closing browsers');
|
||||
debugLogger.log('server', 'closing browsers');
|
||||
if (this._preLaunchedPlaywright)
|
||||
await Promise.all(this._preLaunchedPlaywright.allBrowsers().map(browser => browser.close()));
|
||||
debugLog('closed browsers');
|
||||
debugLogger.log('server', 'closed browsers');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@
|
|||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"Galaxy S5": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S5 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S8": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 740
|
||||
|
|
@ -143,7 +143,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S8 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 740,
|
||||
"height": 360
|
||||
|
|
@ -154,7 +154,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S9+": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 320,
|
||||
"height": 658
|
||||
|
|
@ -165,7 +165,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy S9+ landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 658,
|
||||
"height": 320
|
||||
|
|
@ -176,7 +176,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy Tab S4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 712,
|
||||
"height": 1138
|
||||
|
|
@ -187,7 +187,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Galaxy Tab S4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 1138,
|
||||
"height": 712
|
||||
|
|
@ -836,7 +836,7 @@
|
|||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 384,
|
||||
"height": 640
|
||||
|
|
@ -847,7 +847,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 384
|
||||
|
|
@ -858,7 +858,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
|
|
@ -869,7 +869,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
|
|
@ -880,7 +880,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
|
|
@ -891,7 +891,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36 Edge/14.14263",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
|
|
@ -902,7 +902,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 10": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 800,
|
||||
"height": 1280
|
||||
|
|
@ -913,7 +913,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 10 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 1280,
|
||||
"height": 800
|
||||
|
|
@ -924,7 +924,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 384,
|
||||
"height": 640
|
||||
|
|
@ -935,7 +935,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 384
|
||||
|
|
@ -946,7 +946,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
|
|
@ -957,7 +957,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
|
|
@ -968,7 +968,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 5X": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 412,
|
||||
"height": 732
|
||||
|
|
@ -979,7 +979,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 732,
|
||||
"height": 412
|
||||
|
|
@ -990,7 +990,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 412,
|
||||
"height": 732
|
||||
|
|
@ -1001,7 +1001,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 732,
|
||||
"height": 412
|
||||
|
|
@ -1012,7 +1012,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 6P": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 412,
|
||||
"height": 732
|
||||
|
|
@ -1023,7 +1023,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 732,
|
||||
"height": 412
|
||||
|
|
@ -1034,7 +1034,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 7": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 600,
|
||||
"height": 960
|
||||
|
|
@ -1045,7 +1045,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Nexus 7 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 960,
|
||||
"height": 600
|
||||
|
|
@ -1100,7 +1100,7 @@
|
|||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"Pixel 2": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 411,
|
||||
"height": 731
|
||||
|
|
@ -1111,7 +1111,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 2 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 731,
|
||||
"height": 411
|
||||
|
|
@ -1122,7 +1122,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 411,
|
||||
"height": 823
|
||||
|
|
@ -1133,7 +1133,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"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/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 823,
|
||||
"height": 411
|
||||
|
|
@ -1144,7 +1144,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 3": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 393,
|
||||
"height": 786
|
||||
|
|
@ -1155,7 +1155,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 3 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 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/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 786,
|
||||
"height": 393
|
||||
|
|
@ -1166,7 +1166,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 353,
|
||||
"height": 745
|
||||
|
|
@ -1177,7 +1177,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 745,
|
||||
"height": 353
|
||||
|
|
@ -1188,7 +1188,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4a (5G)": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 412,
|
||||
"height": 892
|
||||
|
|
@ -1203,7 +1203,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 4a (5G) landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"height": 892,
|
||||
"width": 412
|
||||
|
|
@ -1218,7 +1218,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 5": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 393,
|
||||
"height": 851
|
||||
|
|
@ -1233,7 +1233,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Pixel 5 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"screen": {
|
||||
"width": 851,
|
||||
"height": 393
|
||||
|
|
@ -1248,7 +1248,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Moto G4": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 360,
|
||||
"height": 640
|
||||
|
|
@ -1259,7 +1259,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Moto G4 landscape": {
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Mobile Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Mobile Safari/537.36",
|
||||
"viewport": {
|
||||
"width": 640,
|
||||
"height": 360
|
||||
|
|
@ -1270,7 +1270,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Chrome HiDPI": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"screen": {
|
||||
"width": 1792,
|
||||
"height": 1120
|
||||
|
|
@ -1285,7 +1285,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Edge HiDPI": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36 Edg/114.0.5735.26",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36 Edg/114.0.5735.35",
|
||||
"screen": {
|
||||
"width": 1792,
|
||||
"height": 1120
|
||||
|
|
@ -1330,7 +1330,7 @@
|
|||
"defaultBrowserType": "webkit"
|
||||
},
|
||||
"Desktop Chrome": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36",
|
||||
"screen": {
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
|
|
@ -1345,7 +1345,7 @@
|
|||
"defaultBrowserType": "chromium"
|
||||
},
|
||||
"Desktop Edge": {
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.26 Safari/537.36 Edg/114.0.5735.26",
|
||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.35 Safari/537.36 Edg/114.0.5735.35",
|
||||
"screen": {
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ export const deps: any = {
|
|||
'libgles2',
|
||||
'libglib2.0-0',
|
||||
'libgtk-3-0',
|
||||
'libgudev-1.0-0',
|
||||
'libharfbuzz-icu0',
|
||||
'libharfbuzz0b',
|
||||
'libhyphen0',
|
||||
|
|
@ -343,6 +344,7 @@ export const deps: any = {
|
|||
'libgthread-2.0.so.0': 'libglib2.0-0',
|
||||
'libgtk-3.so.0': 'libgtk-3-0',
|
||||
'libgtk-x11-2.0.so.0': 'libgtk2.0-0',
|
||||
'libgudev-1.0.so.0': 'libgudev-1.0-0',
|
||||
'libharfbuzz-icu.so.0': 'libharfbuzz-icu0',
|
||||
'libharfbuzz.so.0': 'libharfbuzz0b',
|
||||
'libhyphen.so.0': 'libhyphen0',
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps
|
|||
for (const entry of entries)
|
||||
zipFile.addFile(entry.value, entry.name);
|
||||
zipFile.end();
|
||||
const zipFileName = state.traceFile + '.zip';
|
||||
const zipFileName = state.traceFile.file + '.zip';
|
||||
zipFile.outputStream.pipe(fs.createWriteStream(zipFileName)).on('close', () => {
|
||||
const artifact = new Artifact(this._context, zipFileName);
|
||||
artifact.reportFinished();
|
||||
|
|
|
|||
4
packages/playwright-core/types/types.d.ts
vendored
4
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -16435,7 +16435,7 @@ export interface ConsoleMessage {
|
|||
/**
|
||||
* The page that produced this console message, if any.
|
||||
*/
|
||||
page(): Page|null;
|
||||
page(): null|Page;
|
||||
|
||||
/**
|
||||
* The text of the console message.
|
||||
|
|
@ -16637,7 +16637,7 @@ export interface Dialog {
|
|||
/**
|
||||
* The page that initiated this dialog, if available.
|
||||
*/
|
||||
page(): Page|null;
|
||||
page(): null|Page;
|
||||
|
||||
/**
|
||||
* Returns dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
module.exports = require('@playwright/test/cli');
|
||||
module.exports = require('@playwright/test/lib/cli');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-core",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing Helpers",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"vite": "^4.3.3",
|
||||
"@playwright/test": "1.34.0-next"
|
||||
"@playwright/test": "1.34.3"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "./cli.js"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-react",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing for React",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-react": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-react17",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing for React",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-react": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-solid",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing for Solid",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"vite-plugin-solid": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-svelte",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing for Svelte",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-vue",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing for Vue",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-vue": "^4.2.1"
|
||||
},
|
||||
"bin": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/experimental-ct-vue2",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "Playwright Component Testing for Vue2",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.34.0-next",
|
||||
"@playwright/experimental-ct-core": "1.34.3",
|
||||
"@vitejs/plugin-vue2": "^2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "playwright-firefox",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate Firefox",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -27,6 +27,6 @@
|
|||
"install": "node install.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
module.exports = require('./lib/cli');
|
||||
module.exports = require('@playwright/test/lib/cli');
|
||||
|
|
|
|||
|
|
@ -28,7 +28,10 @@ function jsxs(type, props) {
|
|||
};
|
||||
}
|
||||
|
||||
const Fragment = {};
|
||||
|
||||
module.exports = {
|
||||
Fragment,
|
||||
jsx,
|
||||
jsxs,
|
||||
};
|
||||
|
|
|
|||
21
packages/playwright-test/jsx-runtime.mjs
Normal file
21
packages/playwright-test/jsx-runtime.mjs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import jsxRuntime from './jsx-runtime.js';
|
||||
|
||||
export const jsx = jsxRuntime.jsx;
|
||||
export const jsxs = jsxRuntime.jsxs;
|
||||
export const Fragment = jsxRuntime.Fragment;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@playwright/test",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate web browsers",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -23,7 +23,11 @@
|
|||
"./lib/internalsForTest": "./lib/internalsForTest.js",
|
||||
"./lib/experimentalLoader": "./lib/experimentalLoader.js",
|
||||
"./lib/plugins": "./lib/plugins/index.js",
|
||||
"./jsx-runtime": "./jsx-runtime.js",
|
||||
"./jsx-runtime": {
|
||||
"import": "./jsx-runtime.mjs",
|
||||
"require": "./jsx-runtime.js",
|
||||
"default": "./jsx-runtime.js"
|
||||
},
|
||||
"./lib/util": "./lib/util.js",
|
||||
"./lib/utilsBundle": "./lib/utilsBundle.js",
|
||||
"./reporter": "./reporter.js"
|
||||
|
|
@ -37,7 +41,7 @@
|
|||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ class ArtifactsRecorder {
|
|||
private _traceMode: TraceMode;
|
||||
private _captureTrace = false;
|
||||
private _screenshotOptions: { mode: ScreenshotMode } & Pick<playwrightLibrary.PageScreenshotOptions, 'fullPage' | 'omitBackground'> | undefined;
|
||||
private _traceOptions: { screenshots: boolean, snapshots: boolean, sources: boolean, mode?: TraceMode };
|
||||
private _traceOptions: { screenshots: boolean, snapshots: boolean, sources: boolean, attachments: boolean, mode?: TraceMode };
|
||||
private _temporaryTraceFiles: string[] = [];
|
||||
private _temporaryScreenshots: string[] = [];
|
||||
private _reusedContexts = new Set<BrowserContext>();
|
||||
|
|
@ -572,7 +572,7 @@ class ArtifactsRecorder {
|
|||
this._screenshotMode = normalizeScreenshotMode(screenshot);
|
||||
this._screenshotOptions = typeof screenshot === 'string' ? undefined : screenshot;
|
||||
this._traceMode = normalizeTraceMode(trace);
|
||||
const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true };
|
||||
const defaultTraceOptions = { screenshots: true, snapshots: true, sources: true, attachments: true };
|
||||
this._traceOptions = typeof trace === 'string' ? defaultTraceOptions : { ...defaultTraceOptions, ...trace, mode: undefined };
|
||||
this._screenshottedSymbol = Symbol('screenshotted');
|
||||
this._startedCollectingArtifacts = Symbol('startedCollectingArtifacts');
|
||||
|
|
@ -661,6 +661,12 @@ class ArtifactsRecorder {
|
|||
if (this._preserveTrace()) {
|
||||
const events = this._testInfo._traceEvents;
|
||||
if (events.length) {
|
||||
if (!this._traceOptions.attachments) {
|
||||
for (const event of events) {
|
||||
if (event.type === 'after')
|
||||
delete event.attachments;
|
||||
}
|
||||
}
|
||||
const tracePath = path.join(this._artifactsDir, createGuid() + '.zip');
|
||||
this._temporaryTraceFiles.push(tracePath);
|
||||
await saveTraceFile(tracePath, events, this._traceOptions.sources);
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ export class TestInfoImpl implements TestInfo {
|
|||
|
||||
async attach(name: string, options: { path?: string, body?: string | Buffer, contentType?: string } = {}) {
|
||||
const step = this._addStep({
|
||||
title: `attach "${name}"`,
|
||||
title: `attach "${name}"`,
|
||||
category: 'attach',
|
||||
wallTime: Date.now(),
|
||||
});
|
||||
|
|
|
|||
2
packages/playwright-test/types/test.d.ts
vendored
2
packages/playwright-test/types/test.d.ts
vendored
|
|
@ -3554,7 +3554,7 @@ export interface PlaywrightWorkerOptions {
|
|||
*
|
||||
* Learn more about [recording trace](https://playwright.dev/docs/test-configuration#record-test-trace).
|
||||
*/
|
||||
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean };
|
||||
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean, attachments?: boolean };
|
||||
/**
|
||||
* Whether to record video for each test. Defaults to `'off'`.
|
||||
* - `'off'`: Do not record video.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "playwright-webkit",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate WebKit",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -27,6 +27,6 @@
|
|||
"install": "node install.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "playwright",
|
||||
"version": "1.34.0-next",
|
||||
"version": "1.34.3",
|
||||
"description": "A high-level API to automate web browsers",
|
||||
"repository": "github:Microsoft/playwright",
|
||||
"homepage": "https://playwright.dev",
|
||||
|
|
@ -28,6 +28,6 @@
|
|||
"install": "node install.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"playwright-core": "1.34.0-next"
|
||||
"playwright-core": "1.34.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,13 +76,6 @@ export class TraceModel {
|
|||
unzipProgress(++done, total);
|
||||
|
||||
contextEntry.actions = [...actionMap.values()].sort((a1, a2) => a1.startTime - a2.startTime);
|
||||
if (!backend.isLive()) {
|
||||
for (const action of contextEntry.actions) {
|
||||
if (!action.endTime && !action.error)
|
||||
action.error = { name: 'Error', message: 'Timed out' };
|
||||
}
|
||||
}
|
||||
|
||||
const stacks = await this._backend.readText(ordinal + '.stacks');
|
||||
if (stacks) {
|
||||
const callMetadata = parseClientSideCallMetadata(JSON.parse(stacks));
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export interface ActionListProps {
|
|||
onSelected: (action: ActionTraceEvent) => void,
|
||||
onHighlighted: (action: ActionTraceEvent | undefined) => void,
|
||||
revealConsole: () => void,
|
||||
isLive?: boolean,
|
||||
}
|
||||
|
||||
type ActionTreeItem = {
|
||||
|
|
@ -49,6 +50,7 @@ export const ActionList: React.FC<ActionListProps> = ({
|
|||
onSelected,
|
||||
onHighlighted,
|
||||
revealConsole,
|
||||
isLive,
|
||||
}) => {
|
||||
const [treeState, setTreeState] = React.useState<TreeState>({ expandedItems: new Map() });
|
||||
const { rootItem, itemMap } = React.useMemo(() => {
|
||||
|
|
@ -86,14 +88,15 @@ export const ActionList: React.FC<ActionListProps> = ({
|
|||
onSelected={item => onSelected(item.action!)}
|
||||
onHighlighted={item => onHighlighted(item?.action)}
|
||||
isError={item => !!item.action?.error?.message}
|
||||
render={item => renderAction(item.action!, sdkLanguage, revealConsole)}
|
||||
render={item => renderAction(item.action!, sdkLanguage, revealConsole, isLive || false)}
|
||||
/>;
|
||||
};
|
||||
|
||||
const renderAction = (
|
||||
action: ActionTraceEvent,
|
||||
sdkLanguage: Language | undefined,
|
||||
revealConsole: () => void
|
||||
revealConsole: () => void,
|
||||
isLive: boolean,
|
||||
) => {
|
||||
const { errors, warnings } = modelUtil.stats(action);
|
||||
const locator = action.params.selector ? asLocator(sdkLanguage || 'javascript', action.params.selector, false /* isFrameLocator */, true /* playSafe */) : undefined;
|
||||
|
|
@ -103,6 +106,8 @@ const renderAction = (
|
|||
time = msToString(action.endTime - action.startTime);
|
||||
else if (action.error)
|
||||
time = 'Timed out';
|
||||
else if (!isLive)
|
||||
time = '-';
|
||||
return <>
|
||||
<div className='action-title'>
|
||||
<span>{action.apiName}</span>
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ const TraceView: React.FC<{
|
|||
item: { testFile?: SourceLocation, testCase?: TestCase },
|
||||
rootDir?: string,
|
||||
}> = ({ item, rootDir }) => {
|
||||
const [model, setModel] = React.useState<MultiTraceModel | undefined>();
|
||||
const [model, setModel] = React.useState<{ model: MultiTraceModel, isLive: boolean } | undefined>();
|
||||
const [counter, setCounter] = React.useState(0);
|
||||
const pollTimer = React.useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
|
|
@ -505,7 +505,7 @@ const TraceView: React.FC<{
|
|||
// This avoids auto-selection of the last action every time we reload the model.
|
||||
const [selectedActionId, setSelectedActionId] = React.useState<string | undefined>();
|
||||
const onSelectionChanged = React.useCallback((action: ActionTraceEvent) => setSelectedActionId(idForAction(action)), [setSelectedActionId]);
|
||||
const initialSelection = selectedActionId ? model?.actions.find(a => idForAction(a) === selectedActionId) : undefined;
|
||||
const initialSelection = selectedActionId ? model?.model.actions.find(a => idForAction(a) === selectedActionId) : undefined;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (pollTimer.current)
|
||||
|
|
@ -520,7 +520,7 @@ const TraceView: React.FC<{
|
|||
// Test finished.
|
||||
const attachment = result && result.duration >= 0 && result.attachments.find(a => a.name === 'trace');
|
||||
if (attachment && attachment.path) {
|
||||
loadSingleTraceFile(attachment.path).then(model => setModel(model));
|
||||
loadSingleTraceFile(attachment.path).then(model => setModel({ model, isLive: false }));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +534,7 @@ const TraceView: React.FC<{
|
|||
pollTimer.current = setTimeout(async () => {
|
||||
try {
|
||||
const model = await loadSingleTraceFile(traceLocation);
|
||||
setModel(model);
|
||||
setModel({ model, isLive: true });
|
||||
} catch {
|
||||
setModel(undefined);
|
||||
} finally {
|
||||
|
|
@ -549,14 +549,15 @@ const TraceView: React.FC<{
|
|||
|
||||
return <Workbench
|
||||
key='workbench'
|
||||
model={model}
|
||||
model={model?.model}
|
||||
hideTimelineBars={true}
|
||||
hideStackFrames={true}
|
||||
showSourcesFirst={true}
|
||||
rootDir={rootDir}
|
||||
initialSelection={initialSelection}
|
||||
onSelectionChanged={onSelectionChanged}
|
||||
fallbackLocation={item.testFile} />;
|
||||
fallbackLocation={item.testFile}
|
||||
isLive={model?.isLive} />;
|
||||
};
|
||||
|
||||
declare global {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ export const Workbench: React.FunctionComponent<{
|
|||
fallbackLocation?: modelUtil.SourceLocation,
|
||||
initialSelection?: ActionTraceEvent,
|
||||
onSelectionChanged?: (action: ActionTraceEvent) => void,
|
||||
}> = ({ model, hideTimelineBars, hideStackFrames, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged }) => {
|
||||
isLive?: boolean,
|
||||
}> = ({ model, hideTimelineBars, hideStackFrames, showSourcesFirst, rootDir, fallbackLocation, initialSelection, onSelectionChanged, isLive }) => {
|
||||
const [selectedAction, setSelectedAction] = React.useState<ActionTraceEvent | undefined>(undefined);
|
||||
const [highlightedAction, setHighlightedAction] = React.useState<ActionTraceEvent | undefined>();
|
||||
const [selectedNavigatorTab, setSelectedNavigatorTab] = React.useState<string>('actions');
|
||||
|
|
@ -142,6 +143,7 @@ export const Workbench: React.FunctionComponent<{
|
|||
onSelected={onActionSelected}
|
||||
onHighlighted={setHighlightedAction}
|
||||
revealConsole={() => setSelectedPropertiesTab('console')}
|
||||
isLive={isLive}
|
||||
/>
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -578,7 +578,6 @@ test('should record global request trace', async ({ request, context, server },
|
|||
});
|
||||
|
||||
test('should store global request traces separately', async ({ request, server, playwright, browserName, mode }, testInfo) => {
|
||||
test.fixme(browserName === 'chromium' && mode === 'driver', 'https://github.com/microsoft/playwright/issues/23108');
|
||||
const request2 = await playwright.request.newContext();
|
||||
await Promise.all([
|
||||
(request as any)._tracing.start({ snapshots: true }),
|
||||
|
|
|
|||
|
|
@ -488,6 +488,34 @@ test('should load a jsx/tsx files', async ({ runInlineTest }) => {
|
|||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should load a jsx/tsx files in ESM mode', async ({ runInlineTest }) => {
|
||||
const { exitCode, passed } = await runInlineTest({
|
||||
'package.json': JSON.stringify({
|
||||
type: 'module'
|
||||
}),
|
||||
'playwright.config.ts': `
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({ projects: [{name: 'foo'}] });
|
||||
`,
|
||||
'a.spec.tsx': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
const component = () => <div></div>;
|
||||
test('succeeds', () => {
|
||||
expect(1 + 1).toBe(2);
|
||||
});
|
||||
`,
|
||||
'b.spec.jsx': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
const component = () => <div></div>;
|
||||
test('succeeds', () => {
|
||||
expect(1 + 1).toBe(2);
|
||||
});
|
||||
`
|
||||
});
|
||||
expect(passed).toBe(2);
|
||||
expect(exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should load jsx with top-level component', async ({ runInlineTest }) => {
|
||||
const { exitCode, passed } = await runInlineTest({
|
||||
'a.spec.tsx': `
|
||||
|
|
|
|||
|
|
@ -526,3 +526,59 @@ test(`trace:retain-on-failure should create trace if request context is disposed
|
|||
expect(trace.apiNames).toContain('apiRequestContext.get');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
test('should include attachments by default', async ({ runInlineTest, server }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: 'on' } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('pass', async ({}, testInfo) => {
|
||||
testInfo.attach('foo', { body: 'bar' });
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(1);
|
||||
const trace = await parseTrace(testInfo.outputPath('test-results', 'a-pass', 'trace.zip'));
|
||||
expect(trace.apiNames).toEqual([
|
||||
'Before Hooks',
|
||||
`attach "foo"`,
|
||||
'After Hooks',
|
||||
]);
|
||||
expect(trace.actions[1].attachments).toEqual([{
|
||||
name: 'foo',
|
||||
contentType: 'text/plain',
|
||||
sha1: expect.any(String),
|
||||
}]);
|
||||
expect([...trace.resources.keys()].filter(f => f.startsWith('resources/'))).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('should opt out of attachments', async ({ runInlineTest, server }, testInfo) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = { use: { trace: { mode: 'on', attachments: false } } };
|
||||
`,
|
||||
'a.spec.ts': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('pass', async ({}, testInfo) => {
|
||||
testInfo.attach('foo', { body: 'bar' });
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(1);
|
||||
const trace = await parseTrace(testInfo.outputPath('test-results', 'a-pass', 'trace.zip'));
|
||||
expect(trace.apiNames).toEqual([
|
||||
'Before Hooks',
|
||||
`attach "foo"`,
|
||||
'After Hooks',
|
||||
]);
|
||||
expect(trace.actions[1].attachments).toEqual(undefined);
|
||||
expect([...trace.resources.keys()].filter(f => f.startsWith('resources/'))).toHaveLength(0);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1348,7 +1348,7 @@ test.describe('labels', () => {
|
|||
const result = await runInlineTest({
|
||||
'a.test.js': `
|
||||
const { expect, test } = require('@playwright/test');
|
||||
const tags = ['@smoke:p1', '@issue[123]', '@issue#123', '@$$$', '@tl/dr'];
|
||||
const tags = ['@smoke-p1', '@issue[123]', '@issue#123', '@$$$', '@tl/dr'];
|
||||
|
||||
test.describe('Error Pages', () => {
|
||||
tags.forEach(tag => {
|
||||
|
|
@ -1364,7 +1364,7 @@ test.describe('labels', () => {
|
|||
expect(result.passed).toBe(5);
|
||||
|
||||
await showReport();
|
||||
const tags = ['smoke:p1', 'issue[123]', 'issue#123', '$$$', 'tl/dr'];
|
||||
const tags = ['smoke-p1', 'issue[123]', 'issue#123', '$$$', 'tl/dr'];
|
||||
const searchInput = page.locator('.subnav-search-input');
|
||||
|
||||
for (const tag of tags) {
|
||||
|
|
@ -1881,3 +1881,61 @@ test('should list tests in the right order', async ({ runInlineTest, showReport,
|
|||
/main › second › passes\d+m?ssecond.ts:5/,
|
||||
]);
|
||||
});
|
||||
|
||||
test('tests should filter by file', async ({ runInlineTest, showReport, page }) => {
|
||||
const result = await runInlineTest({
|
||||
'file-a.test.js': `
|
||||
const { test } = require('@playwright/test');
|
||||
test('a test 1', async ({}) => {});
|
||||
test('a test 2', async ({}) => {});
|
||||
`,
|
||||
'file-b.test.js': `
|
||||
const { test } = require('@playwright/test');
|
||||
test('b test 1', async ({}) => {});
|
||||
test('b test 2', async ({}) => {});
|
||||
`,
|
||||
}, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' });
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(4);
|
||||
expect(result.failed).toBe(0);
|
||||
|
||||
await showReport();
|
||||
|
||||
const searchInput = page.locator('.subnav-search-input');
|
||||
|
||||
await searchInput.fill('file-a');
|
||||
await expect(page.getByText('file-a.test.js', { exact: true })).toBeVisible();
|
||||
await expect(page.getByText('a test 1')).toBeVisible();
|
||||
await expect(page.getByText('a test 2')).toBeVisible();
|
||||
await expect(page.getByText('file-b.test.js', { exact: true })).not.toBeVisible();
|
||||
await expect(page.getByText('b test 1')).not.toBeVisible();
|
||||
await expect(page.getByText('b test 2')).not.toBeVisible();
|
||||
|
||||
await searchInput.fill('file-a:3');
|
||||
await expect(page.getByText('a test 1')).toBeVisible();
|
||||
await expect(page.getByText('a test 2')).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('tests should filter by status', async ({ runInlineTest, showReport, page }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.js': `
|
||||
const { test, expect } = require('@playwright/test');
|
||||
test('failed title', async ({}) => { expect(1).toBe(1); });
|
||||
test('passes title', async ({}) => { expect(1).toBe(2); });
|
||||
`,
|
||||
}, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' });
|
||||
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.failed).toBe(1);
|
||||
|
||||
await showReport();
|
||||
|
||||
const searchInput = page.locator('.subnav-search-input');
|
||||
|
||||
await searchInput.fill('s:failed');
|
||||
await expect(page.getByText('a.test.js', { exact: true })).toBeVisible();
|
||||
await expect(page.getByText('failed title')).not.toBeVisible();
|
||||
await expect(page.getByText('passes title')).toBeVisible();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -98,9 +98,12 @@ test('should merge screenshot assertions', async ({ runUITest }, testInfo) => {
|
|||
'action list'
|
||||
).toHaveText([
|
||||
/Before Hooks[\d.]+m?s/,
|
||||
/page\.setContent[\d.]+m?s/,
|
||||
/expect\.toHaveScreenshot[\d.]+m?s/,
|
||||
/After Hooks/,
|
||||
/page.setContent[\d.]+m?s/,
|
||||
/expect.toHaveScreenshot[\d.]+m?s/,
|
||||
/After Hooks-/,
|
||||
/fixture: page[\d.]+m?s/,
|
||||
/fixture: context[\d.]+m?s/,
|
||||
/fixture: browser[\d.]+m?s/,
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ RUN mkdir /ms-playwright && \
|
|||
mkdir /ms-playwright-agent && \
|
||||
cd /ms-playwright-agent && npm init -y && \
|
||||
npm i /tmp/playwright-core.tar.gz && \
|
||||
npx playwright mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
|
||||
npx playwright install --with-deps && rm -rf /var/lib/apt/lists/* && \
|
||||
npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
|
||||
npm exec --no -- playwright-core install --with-deps && rm -rf /var/lib/apt/lists/* && \
|
||||
rm /tmp/playwright-core.tar.gz && \
|
||||
chmod -R 777 /ms-playwright
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ RUN mkdir /ms-playwright && \
|
|||
mkdir /ms-playwright-agent && \
|
||||
cd /ms-playwright-agent && npm init -y && \
|
||||
npm i /tmp/playwright-core.tar.gz && \
|
||||
npx playwright mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
|
||||
npx playwright install --with-deps && rm -rf /var/lib/apt/lists/* && \
|
||||
npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
|
||||
npm exec --no -- playwright-core install --with-deps && rm -rf /var/lib/apt/lists/* && \
|
||||
rm /tmp/playwright-core.tar.gz && \
|
||||
rm -rf /ms-playwright-agent && \
|
||||
chmod -R 777 /ms-playwright
|
||||
|
|
|
|||
2
utils/generate_types/overrides-test.d.ts
vendored
2
utils/generate_types/overrides-test.d.ts
vendored
|
|
@ -206,7 +206,7 @@ export interface PlaywrightWorkerOptions {
|
|||
launchOptions: LaunchOptions;
|
||||
connectOptions: ConnectOptions | undefined;
|
||||
screenshot: ScreenshotMode | { mode: ScreenshotMode } & Pick<PageScreenshotOptions, 'fullPage' | 'omitBackground'>;
|
||||
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean };
|
||||
trace: TraceMode | /** deprecated */ 'retry-with-trace' | { mode: TraceMode, snapshots?: boolean, screenshots?: boolean, sources?: boolean, attachments?: boolean };
|
||||
video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ apt-get update && apt-get install -y curl && \
|
|||
apt-get update && apt-get install -y apt-file && apt-file update
|
||||
|
||||
# Install tip-of-tree playwright-core and browsers
|
||||
mkdir /root/tmp && cd /root/tmp && npm init -y && npm i /root/hostfolder/playwright-core.tar.gz && npx playwright install
|
||||
mkdir /root/tmp && cd /root/tmp && npm init -y && npm i /root/hostfolder/playwright-core.tar.gz && npx playwright-core install
|
||||
|
||||
cp /root/hostfolder/inside_docker/list_dependencies.js /root/tmp/list_dependencies.js
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue