Compare commits

...

28 commits

Author SHA1 Message Date
Andrey Lushnikov 396487fc4c
chore: mark v1.25.2 (#17138) 2022-09-06 15:06:41 -07:00
Pavel Feldman 53320f3b52 cherry-pick(#17139): fix(selectors): allow custom engines in out-of-process 2022-09-06 14:19:45 -07:00
Pavel Feldman 35d1aff7ca cherry-pick(#17137): chore: silenсe best effort cleanup errors 2022-09-06 12:49:58 -07:00
Dmitry Gozman a37f18c962
cherry-pick(#17051): fix(firefox): disable cookie partitioning (#17054) 2022-09-02 16:35:57 -07:00
Dmitry Gozman 487de33e4b
cherry-pick(#16589): chore(ct): svelte-kit is being a moving target, remove tests for now (#17002) 2022-08-31 13:56:57 -07:00
Dmitry Gozman df6fbcb8dc
cherry-pick(#16898): fix: include headlessness as a launch argument to browser (#16998) 2022-08-31 13:18:37 -07:00
Andrey Lushnikov 1c54ead163
chore: mark v1.25.1 (#16769) 2022-08-23 11:36:18 -07:00
Pavel Feldman 9bc72cca54 chery-pick(#16733): chore: do not use experimental loader for web server 2022-08-23 10:26:19 -07:00
Playwright Service 403b723a2c
chery-pick(#16663): docs(dotnet): add missing TestClass attribute (#16700)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-20 08:44:21 +02:00
Pavel Feldman ca18f2eb98 Revert "cherry-pick: sync ToT docs (#16680)"
Please don't bulk-pick, we should have a cherry-pick per commit and we
should make sure only critical changes are merged into the branch.
2022-08-19 16:44:16 -07:00
Pavel Feldman 962e41474e cherry-pick(#16691): fix(selectors): make them work in the browser reuse mode 2022-08-19 16:40:27 -07:00
Playwright Service c9e2a8b340
cherry-pick: sync ToT docs (#16680)
This PR cherry-picks the following commits:

- daee232e9e
- 2581705115
- f272ad2308
- c5f0265481
- d7ba592704
- cfe7af79e9
- 411ec4479c
- 00ba305152
- 14ac443c85
2022-08-19 14:30:34 +02:00
Pavel Feldman 817a29b346 cherry-pick(#16481): fix(ct): pass local config to preview 2022-08-15 15:45:35 -07:00
Pavel Feldman 10fcbe3f88 cherry-pick(#16477): feat(driver): report backend state 2022-08-15 15:44:57 -07:00
Playwright Service cb34325249
chery-pick(#16547): docs(release-notes): deprecate Node.js 12 (#16552)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2022-08-15 20:15:44 +02:00
Playwright Service f86aa2b188
chery-pick(#16550): docs: remove extra quoutes (#16551) 2022-08-15 11:03:01 -07:00
Playwright Service 34014638da
chery-pick(docs): sync with ToT docs (#16533)
This PR cherry-picks the following commits:

- b089d0a5aa
- 13f210a1e8
- 2bdf51d284
- 32adf50e65
- 435272248f
- 8170432fab
2022-08-15 09:43:33 +02:00
Playwright Service 3bc6b4b644
cherry-pick: sync ToT docs (#16448)
This PR cherry-picks the following commits:

- 16d9f66ff9
- fcee4d5444
- d12afa7ff3
2022-08-11 12:29:25 +02:00
Andrey Lushnikov bb54c04096
chore: mark v1.25.0 (#16405) 2022-08-10 15:41:05 -07:00
Andrey Lushnikov e440e41b50
cherry-pick(#16426): devops: use REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN everywhere (#16428) 2022-08-10 14:19:16 -07:00
Dmitry Gozman fdf31cd70d
cherry-pick(#16420): feat(driver): add reuse and navigate commands (#16423) 2022-08-10 12:37:43 -07:00
Yury Semikhatsky bbd3fd72f2
cherry-pick(#16421): docs: test.step return value (#16422) 2022-08-10 11:27:26 -07:00
Max Schmitt ecb8266a76
cherry-pick(#16400): fix(codegen): make sure input recording with japanese IME Work (#16414)
SHA: 699a52ec74
2022-08-10 18:32:20 +02:00
Max Schmitt 0227708c2f
cherry-pick(#16395): fix(test runner): do not resolve relative imports through baseUrl (#16415)
SHA: f58c376443
2022-08-10 07:36:48 -07:00
Max Schmitt 7de99f3a48
cherry-pick(#16396): fix(test runner): show interrupted as yellow (#16412)
SHA: baa2ef2700
2022-08-10 14:53:45 +02:00
Max Schmitt 150a75189e
cherry-pick: ToT docs (#16413)
* docs: Remove html reporter page (#16407)

* docs: intro doc on ci (#16346)

* docs: Trace-viewer-intro (#16254)

Co-authored-by: Debbie O'Brien <debs-obrien@users.noreply.github.com>
2022-08-10 14:52:52 +02:00
Andrey Lushnikov e93ed0ae97
cherry-pick(#16392): docs: add JS Release notes (#16410) 2022-08-10 05:25:02 -07:00
Andrey Lushnikov 259887f32f
cherry-pick(#16278): test: fix firefox-beta tests (#16409) 2022-08-10 05:23:49 -07:00
90 changed files with 1106 additions and 645 deletions

View file

@ -15,7 +15,7 @@ jobs:
- name: Create GitHub issue - name: Create GitHub issue
uses: actions/github-script@v4 uses: actions/github-script@v4
with: with:
github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: | script: |
const { data } = await github.git.getCommit({ const { data } = await github.git.getCommit({
owner: context.repo.owner, owner: context.repo.owner,

View file

@ -78,9 +78,9 @@ jobs:
run: bash utils/build/deploy-trace-viewer.sh --canary run: bash utils/build/deploy-trace-viewer.sh --canary
if: contains(github.ref, 'main') if: contains(github.ref, 'main')
env: env:
GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
- name: Deploy BETA - name: Deploy BETA
run: bash utils/build/deploy-trace-viewer.sh --beta run: bash utils/build/deploy-trace-viewer.sh --beta
if: contains(github.ref, 'release') if: contains(github.ref, 'release')
env: env:
GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}

View file

@ -18,4 +18,4 @@ jobs:
- name: Deploy Stable - name: Deploy Stable
run: bash utils/build/deploy-trace-viewer.sh --stable run: bash utils/build/deploy-trace-viewer.sh --stable
env: env:
GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}

View file

@ -36,7 +36,7 @@ jobs:
- name: Create Pull Request - name: Create Pull Request
uses: actions/github-script@v4 uses: actions/github-script@v4
with: with:
github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: | script: |
const response = await github.pulls.create({ const response = await github.pulls.create({
owner: 'microsoft', owner: 'microsoft',

View file

@ -134,27 +134,27 @@ you can still opt into stable channels on the bots that are typically free of su
To invoke Playwright CLI commands, you need to invoke a PowerShell script: To invoke Playwright CLI commands, you need to invoke a PowerShell script:
```bash ```bash
pwsh bin\Debug\netX\playwright.ps1 --help pwsh bin/Debug/netX/playwright.ps1 --help
``` ```
Playwright can install supported browsers by means of the CLI tool. Playwright can install supported browsers by means of the CLI tool.
```bash csharp ```bash csharp
# Running without arguments will install all browsers # Running without arguments will install all browsers
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
You can also install specific browsers by providing an argument: You can also install specific browsers by providing an argument:
```bash csharp ```bash csharp
# Install WebKit # Install WebKit
pwsh bin\Debug\netX\playwright.ps1 install webkit pwsh bin/Debug/netX/playwright.ps1 install webkit
``` ```
See all supported browsers: See all supported browsers:
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --help pwsh bin/Debug/netX/playwright.ps1 install --help
``` ```
## Install browsers via API ## Install browsers via API
@ -236,17 +236,17 @@ mvn test
```bash tab=bash-bash lang=csharp ```bash tab=bash-bash lang=csharp
PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```batch tab=bash-batch lang=csharp ```batch tab=bash-batch lang=csharp
set PLAYWRIGHT_BROWSERS_PATH=%USERPROFILE%\pw-browsers set PLAYWRIGHT_BROWSERS_PATH=%USERPROFILE%\pw-browsers
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```powershell tab=bash-powershell lang=csharp ```powershell tab=bash-powershell lang=csharp
$env:PLAYWRIGHT_BROWSERS_PATH="$env:USERPROFILE\pw-browsers" $env:PLAYWRIGHT_BROWSERS_PATH="$env:USERPROFILE\pw-browsers"
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
When running Playwright scripts, ask it to search for browsers in a shared location. When running Playwright scripts, ask it to search for browsers in a shared location.
@ -405,17 +405,17 @@ mvn test
``` ```
```bash tab=bash-bash lang=csharp ```bash tab=bash-bash lang=csharp
HTTPS_PROXY=https://192.0.2.1 pwsh bin\Debug\netX\playwright.ps1 install HTTPS_PROXY=https://192.0.2.1 pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```batch tab=bash-batch lang=csharp ```batch tab=bash-batch lang=csharp
set HTTPS_PROXY=https://192.0.2.1 set HTTPS_PROXY=https://192.0.2.1
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```powershell tab=bash-powershell lang=csharp ```powershell tab=bash-powershell lang=csharp
$env:HTTPS_PROXY="https://192.0.2.1" $env:HTTPS_PROXY="https://192.0.2.1"
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
If the requests of the proxy get intercepted with a custom untrusted certificate authority (CA) and it yields to `Error: self signed certificate in certificate chain` while downloading the browsers, you must set your custom root certificates via the [`NODE_EXTRA_CA_CERTS`](https://nodejs.org/api/cli.html#node_extra_ca_certsfile) environment variable before installing the browsers: If the requests of the proxy get intercepted with a custom untrusted certificate authority (CA) and it yields to `Error: self signed certificate in certificate chain` while downloading the browsers, you must set your custom root certificates via the [`NODE_EXTRA_CA_CERTS`](https://nodejs.org/api/cli.html#node_extra_ca_certsfile) environment variable before installing the browsers:
@ -500,17 +500,17 @@ mvn test
``` ```
```bash tab=bash-bash lang=csharp ```bash tab=bash-bash lang=csharp
PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1 pwsh bin\Debug\netX\playwright.ps1 install PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1 pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```batch tab=bash-batch lang=csharp ```batch tab=bash-batch lang=csharp
set PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1 set PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```powershell tab=bash-powershell lang=csharp ```powershell tab=bash-powershell lang=csharp
$env:PLAYWRIGHT_DOWNLOAD_HOST="192.0.2.1" $env:PLAYWRIGHT_DOWNLOAD_HOST="192.0.2.1"
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
It is also possible to use a per-browser download hosts using `PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST`, `PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST` and `PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST` env variables that It is also possible to use a per-browser download hosts using `PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST`, `PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST` and `PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST` env variables that
@ -584,19 +584,19 @@ mvn test
``` ```
```bash tab=bash-bash lang=csharp ```bash tab=bash-bash lang=csharp
PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST=203.0.113.3 PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1 pwsh bin\Debug\netX\playwright.ps1 install PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST=203.0.113.3 PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1 pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```batch tab=bash-batch lang=csharp ```batch tab=bash-batch lang=csharp
set PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST=203.0.113.3 set PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST=203.0.113.3
set PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1 set PLAYWRIGHT_DOWNLOAD_HOST=192.0.2.1
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```powershell tab=bash-powershell lang=csharp ```powershell tab=bash-powershell lang=csharp
$env:PLAYWRIGHT_DOWNLOAD_HOST="192.0.2.1" $env:PLAYWRIGHT_DOWNLOAD_HOST="192.0.2.1"
$env:PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST="203.0.113.3" $env:PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST="203.0.113.3"
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
## Skip browser downloads ## Skip browser downloads
@ -638,17 +638,17 @@ mvn test
``` ```
```bash tab=bash-bash lang=csharp ```bash tab=bash-bash lang=csharp
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 pwsh bin\Debug\netX\playwright.ps1 install PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```batch tab=bash-batch lang=csharp ```batch tab=bash-batch lang=csharp
set PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 set PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
```powershell tab=bash-powershell lang=csharp ```powershell tab=bash-powershell lang=csharp
$env:PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 $env:PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
## Download single browser binary ## Download single browser binary

115
docs/src/ci-intro-js.md Normal file
View file

@ -0,0 +1,115 @@
---
id: ci-intro
title: "CI Github Actions"
---
When installing Playwright you are given the option to add a [GitHub Actions](https://docs.github.com/en/actions). This creates a `playwright.yml` file inside a `.github/workflows` folder containing everything you need so that your tests run on each push and pull request into the main/master branch.
**What you will learn:**
- [How to use GitHub Actions to run your tests](#github-actions)
- [How to create a repo and push to GitHub](#create-a-repo-and-push-to-github)
- [How to open the workflows](#opening-the-workflows)
- [How to view the test logs](#viewing-test-logs)
- [How to download the report from GitHub](#downloading-the-playwright-report)
- [How to view the report](#viewing-the-playwright-report)
- [How to view the trace](#viewing-the-trace)
## GitHub Actions
Tests will run on push or pull request on branches main/master. The [workflow](https://docs.github.com/en/actions/using-workflows/about-workflows) will install all dependencies, install Playwright and then run the tests. It will also create the HTML report.
```yaml
name: Playwright Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14.x"
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v2
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
```
### Create a Repo and Push to GitHub
[Create a repo on GitHub](https://docs.github.com/en/get-started/quickstart/create-a-repo) and create a new repository or push an existing repository. Follow the instructions on GitHub and don't forget to [initialize a git repository](https://github.com/git-guides/git-init) using the `git init` command so you can [add](https://github.com/git-guides/git-add), [commit](https://github.com/git-guides/git-commit) and [push](https://github.com/git-guides/git-push) your code.
<img width="861" alt="Create a Repo and Push to GitHub" src="https://user-images.githubusercontent.com/13063165/183423254-d2735278-a2ab-4d63-bb99-48d8e5e447bc.png"/>
### Opening the Workflows
Click on the **Actions** tab to see the workflows. Here you will see if your tests have passed or failed.
<img width="847" alt="Opening the Workflows" src="https://user-images.githubusercontent.com/13063165/183423584-2ea18038-cd49-4daa-a20c-2205352f0933.png"/>
On Pull Requests you can also click on the **Details** link in the [PR status check](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks).
<img width="645" alt="pr status checked" src="https://user-images.githubusercontent.com/13063165/183722462-17a985db-0e10-4205-b16c-8aaac36117b9.png" />
### Viewing Test Logs
Clicking on the workflow run will show you the all the actions that GitHub performed and clicking on **Run Playwright tests** will show the error messages, what was expected and what was received as well as the call log.
<img width="839" alt="Viewing Test Logs" src="https://user-images.githubusercontent.com/13063165/183423783-58bf2008-514e-4f96-9c12-c9a55703960c.png"/>
## HTML Report
The HTML Report shows you a full report of your tests. You can filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests.
### Downloading the HTML Report
In the Artifacts section click on the **playwright-report** to download your report in the format of a zip file.
<img width="972" alt="Downloading the HTML Report" src="https://user-images.githubusercontent.com/13063165/183437023-524f1803-84e4-4862-9ce3-1d55af0e023e.png" />
### Viewing the HTML Report
Locally opening the report will not work as expected as you need a web server in order for everything to work correctly. First, extract the zip, preferably in a folder that already has Playwright installed. Using the command line change into the directory where the report is and use `npx playwright show-report` followed by the name of the extracted folder. This will serve up the report and enable you to view it in your browser.
```bash
npx playwright show-report name-of-my-extracted-playwright-report
```
<img width="752" alt="Viewing the HTML Report" src="https://user-images.githubusercontent.com/13063165/183437645-b47dd175-2e07-4ecc-a469-27d5b150b7ed.png" />
To learn more about reports check out our detailed guide on [HTML Reporter](/test-reporters.md#html-reporter)
### Viewing the Trace
Once you have served the report using `npx playwright show-report`, click on the trace icon next to the test's file name as seen in the image above. You can then view the trace of your tests and inspect each action to try to find out why the tests are failing.
<img width="1907" alt="Viewing the Trace" src="https://user-images.githubusercontent.com/13063165/183879653-d442e6b4-14f5-4d0e-99f3-9ba19f82c7cf.png"/>
To learn more about traces check out our detailed guide on [Trace Viewer](/trace-viewer.md).
To learn more about running tests on CI check out our detailed guide on [Continuous Integration](/ci.md).
## What's Next
- [Learn how to use Web First Assertions](/test-assertions.md)
- [Learn how to use Selectors](/selectors.md)
- [Learn how to use Locators](/locators.md)

View file

@ -32,7 +32,7 @@ configurations for common CI providers.
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install --with-deps" mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="install --with-deps"
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --with-deps pwsh bin/Debug/netX/playwright.ps1 install --with-deps
``` ```
1. **Run your tests**: 1. **Run your tests**:
@ -176,7 +176,7 @@ steps:
name: 'Playwright Tests' name: 'Playwright Tests'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v2 - uses: actions/setup-node@v2
@ -194,7 +194,7 @@ steps:
name: 'Playwright Tests' name: 'Playwright Tests'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set up Python - name: Set up Python
@ -218,7 +218,7 @@ steps:
name: 'Playwright Tests' name: 'Playwright Tests'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-java@v3 - uses: actions/setup-java@v3
@ -239,7 +239,7 @@ steps:
name: 'Playwright Tests' name: 'Playwright Tests'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup dotnet - name: Setup dotnet
@ -264,7 +264,7 @@ steps:
name: 'Playwright Tests - ${{ matrix.project }} - Shard ${{ matrix.shardIndex }} of ${{ matrix.shardTotal }}' name: 'Playwright Tests - ${{ matrix.project }} - Shard ${{ matrix.shardIndex }} of ${{ matrix.shardTotal }}'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -297,7 +297,7 @@ Alternatively, you can use [Command line tools](./cli.md#install-system-dependen
pool: pool:
vmImage: 'ubuntu-20.04' vmImage: 'ubuntu-20.04'
container: mcr.microsoft.com/playwright:v1.25.0-focal container: mcr.microsoft.com/playwright:v1.25.2-focal
steps: steps:
... ...
@ -311,7 +311,7 @@ Running Playwright on CircleCI requires the following steps:
```yml ```yml
docker: docker:
- image: mcr.microsoft.com/playwright:v1.25.0-focal - image: mcr.microsoft.com/playwright:v1.25.2-focal
environment: environment:
NODE_ENV: development # Needed if playwright is in `devDependencies` NODE_ENV: development # Needed if playwright is in `devDependencies`
``` ```
@ -333,7 +333,7 @@ to run tests on Jenkins.
```groovy ```groovy
pipeline { pipeline {
agent { docker { image 'mcr.microsoft.com/playwright:v1.25.0-focal' } } agent { docker { image 'mcr.microsoft.com/playwright:v1.25.2-focal' } }
stages { stages {
stage('e2e-tests') { stage('e2e-tests') {
steps { steps {
@ -351,7 +351,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)). 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 ```yml
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
``` ```
### GitLab CI ### GitLab CI
@ -364,7 +364,7 @@ stages:
tests: tests:
stage: test stage: test
image: mcr.microsoft.com/playwright:v1.25.0-focal image: mcr.microsoft.com/playwright:v1.25.2-focal
script: script:
... ...
``` ```

View file

@ -23,7 +23,7 @@ playwright
```bash csharp ```bash csharp
# Use the tools. # Use the tools.
pwsh bin\Debug\netX\playwright.ps1 --help pwsh bin/Debug/netX/playwright.ps1 --help
``` ```
```json js ```json js
@ -56,7 +56,7 @@ playwright install
```bash csharp ```bash csharp
# Running without arguments will install default browsers # Running without arguments will install default browsers
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
You can also install specific browsers by providing an argument: You can also install specific browsers by providing an argument:
@ -78,7 +78,7 @@ playwright install webkit
```bash csharp ```bash csharp
# Install WebKit # Install WebKit
pwsh bin\Debug\netX\playwright.ps1 install webkit pwsh bin/Debug/netX/playwright.ps1 install webkit
``` ```
See all supported browsers: See all supported browsers:
@ -96,7 +96,7 @@ playwright install --help
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --help pwsh bin/Debug/netX/playwright.ps1 install --help
``` ```
## Install system dependencies ## Install system dependencies
@ -120,7 +120,7 @@ playwright install-deps
```bash csharp ```bash csharp
# See command help # See command help
pwsh bin\Debug\netX\playwright.ps1 install-deps pwsh bin/Debug/netX/playwright.ps1 install-deps
``` ```
You can also install the dependencies for a single browser only by passing it as an argument: You can also install the dependencies for a single browser only by passing it as an argument:
@ -138,7 +138,7 @@ playwright install-deps chromium
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install-deps chromium pwsh bin/Debug/netX/playwright.ps1 install-deps chromium
``` ```
It's also possible to combine `install-deps` with `install` and install by that the browsers and OS dependencies with a single command. This would do both for Chromium, but you can also leave it out. It's also possible to combine `install-deps` with `install` and install by that the browsers and OS dependencies with a single command. This would do both for Chromium, but you can also leave it out.
@ -156,7 +156,7 @@ playwright install --with-deps chromium
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --with-deps chromium pwsh bin/Debug/netX/playwright.ps1 install --with-deps chromium
``` ```
## Generate code ## Generate code
@ -174,7 +174,7 @@ playwright codegen wikipedia.org
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen wikipedia.org pwsh bin/Debug/netX/playwright.ps1 codegen wikipedia.org
``` ```
Run `codegen` and perform actions in the browser. Playwright CLI will generate JavaScript code for the user interactions. `codegen` will attempt to generate resilient text-based selectors. Run `codegen` and perform actions in the browser. Playwright CLI will generate JavaScript code for the user interactions. `codegen` will attempt to generate resilient text-based selectors.
@ -204,7 +204,7 @@ playwright codegen --save-storage=auth.json
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --save-storage=auth.json pwsh bin/Debug/netX/playwright.ps1 codegen --save-storage=auth.json
# Perform authentication and exit. # Perform authentication and exit.
# auth.json will contain the storage state. # auth.json will contain the storage state.
``` ```
@ -231,8 +231,8 @@ playwright codegen --load-storage=auth.json my.web.app
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 open --load-storage=auth.json my.web.app pwsh bin/Debug/netX/playwright.ps1 open --load-storage=auth.json my.web.app
pwsh bin\Debug\netX\playwright.ps1 codegen --load-storage=auth.json my.web.app pwsh bin/Debug/netX/playwright.ps1 codegen --load-storage=auth.json my.web.app
# Perform actions in authenticated state. # Perform actions in authenticated state.
``` ```
@ -351,7 +351,7 @@ playwright open example.com
```bash csharp ```bash csharp
# Open page in Chromium # Open page in Chromium
pwsh bin\Debug\netX\playwright.ps1 open example.com pwsh bin/Debug/netX/playwright.ps1 open example.com
``` ```
```bash js ```bash js
@ -371,7 +371,7 @@ playwright wk example.com
```bash csharp ```bash csharp
# Open page in WebKit # Open page in WebKit
pwsh bin\Debug\netX\playwright.ps1 wk example.com pwsh bin/Debug/netX/playwright.ps1 wk example.com
``` ```
### Emulate devices ### Emulate devices
@ -394,7 +394,7 @@ playwright open --device="iPhone 11" wikipedia.org
```bash csharp ```bash csharp
# Emulate iPhone 11. # Emulate iPhone 11.
pwsh bin\Debug\netX\playwright.ps1 open --device="iPhone 11" wikipedia.org pwsh bin/Debug/netX/playwright.ps1 open --device="iPhone 11" wikipedia.org
``` ```
### Emulate color scheme and viewport size ### Emulate color scheme and viewport size
@ -416,7 +416,7 @@ playwright open --viewport-size=800,600 --color-scheme=dark twitter.com
```bash csharp ```bash csharp
# Emulate screen size and color scheme. # Emulate screen size and color scheme.
pwsh bin\Debug\netX\playwright.ps1 open --viewport-size=800,600 --color-scheme=dark twitter.com pwsh bin/Debug/netX/playwright.ps1 open --viewport-size=800,600 --color-scheme=dark twitter.com
``` ```
### Emulate geolocation, language and timezone ### Emulate geolocation, language and timezone
@ -442,7 +442,7 @@ playwright open --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --l
```bash csharp ```bash csharp
# Emulate timezone, language & location # Emulate timezone, language & location
# Once page opens, click the "my location" button to see geolocation in action # Once page opens, click the "my location" button to see geolocation in action
pwsh bin\Debug\netX\playwright.ps1 open --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --lang="it-IT" maps.google.com pwsh bin/Debug/netX/playwright.ps1 open --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --lang="it-IT" maps.google.com
``` ```
## Inspect selectors ## Inspect selectors
@ -542,7 +542,7 @@ playwright screenshot \
```bash csharp ```bash csharp
# Wait 3 seconds before capturing a screenshot after page loads ('load' event fires) # Wait 3 seconds before capturing a screenshot after page loads ('load' event fires)
pwsh bin\Debug\netX\playwright.ps1 screenshot \ pwsh bin/Debug/netX/playwright.ps1 screenshot \
--device="iPhone 11" \ --device="iPhone 11" \
--color-scheme=dark \ --color-scheme=dark \
--wait-for-timeout=3000 \ --wait-for-timeout=3000 \
@ -566,7 +566,7 @@ playwright screenshot --full-page en.wikipedia.org wiki-full.png
```bash csharp ```bash csharp
# Capture a full page screenshot # Capture a full page screenshot
pwsh bin\Debug\netX\playwright.ps1 screenshot --full-page en.wikipedia.org wiki-full.png pwsh bin/Debug/netX/playwright.ps1 screenshot --full-page en.wikipedia.org wiki-full.png
``` ```
## Generate PDF ## Generate PDF
@ -590,5 +590,5 @@ playwright pdf https://en.wikipedia.org/wiki/PDF wiki.pdf
```bash csharp ```bash csharp
# See command help # See command help
pwsh bin\Debug\netX\playwright.ps1 pdf https://en.wikipedia.org/wiki/PDF wiki.pdf pwsh bin/Debug/netX/playwright.ps1 pdf https://en.wikipedia.org/wiki/PDF wiki.pdf
``` ```

49
docs/src/codegen-intro.md Normal file
View file

@ -0,0 +1,49 @@
---
id: codegen-intro
title: "Test Generator"
---
Playwright comes with the ability to generate tests out of the box and is a great way to quickly get started with testing. It will open two windows, a browser window where you interact with the website you wish to test and the Playwright Inspector window where you can record your tests, copy the tests, clear your tests as well as change the language of your tests.
**You will learn**
- [How to generate tests with Codegen](/codegen.md#running-codegen)
## Running Codegen
```bash js
npx playwright codegen playwright.dev
```
```bash java
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="codegen playwright.dev"
```
```bash python
playwright codegen playwright.dev
```
```bash csharp
pwsh bin/Debug/netX/playwright.ps1 codegen playwright.dev
```
Run `codegen` and perform actions in the browser. Playwright will generate the code for the user interactions. `Codegen` will attempt to generate resilient text-based selectors.
<img width="1183" alt="Codegen generating code for tests for playwright.dev website" src="https://user-images.githubusercontent.com/13063165/181852815-971c10da-0b55-4e54-8a73-77e1e825193c.png" />
When you have finished interacting with the page, press the **record** button to stop the recording and use the **copy** button to copy the generated code to your editor.
<img width="1266" alt="Codegen generating code for tests for playwright.dev" src="https://user-images.githubusercontent.com/13063165/183905981-003c4173-0d5e-4960-8190-50e6ca71b2c3.png" />
Use the **clear** button to clear the code to start recording again. Once finished close the Playwright inspector window or stop the terminal command.
To learn more about generating tests check out or detailed guide on [Codegen](./codegen.md).
## What's Next
- [See a trace of your tests](./trace-viewer.md)

View file

@ -5,16 +5,6 @@ title: "Test Generator"
Playwright comes with the ability to generate tests out of the box and is a great way to quickly get started with testing. It will open two windows, a browser window where you interact with the website you wish to test and the Playwright Inspector window where you can record your tests, copy the tests, clear your tests as well as change the language of your tests. Playwright comes with the ability to generate tests out of the box and is a great way to quickly get started with testing. It will open two windows, a browser window where you interact with the website you wish to test and the Playwright Inspector window where you can record your tests, copy the tests, clear your tests as well as change the language of your tests.
**You will learn**
- [How to generate tests with Codegen](/codegen.md#running-codegen)
- [How to emulate viewport size](/codegen.md#emulate-viewport-size)
- [How to emulate devices](/codegen.md#emulate-devices)
- [How to emulate color scheme](/codegen.md#emulate-color-scheme)
- [How to emulate geolocation, language and timezone](/codegen.md#emulate-geolocation-language-and-timezone)
- [How to preserve authenticated state](/codegen.md#preserve-authenticated-state)
- [How to record using a custom setup](/codegen.md#record-using-custom-setup)
## Running Codegen ## Running Codegen
```bash js ```bash js
@ -30,7 +20,7 @@ playwright codegen playwright.dev
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen playwright.dev pwsh bin/Debug/netX/playwright.ps1 codegen playwright.dev
``` ```
Run `codegen` and perform actions in the browser. Playwright will generate the code for the user interactions. `Codegen` will attempt to generate resilient text-based selectors. Run `codegen` and perform actions in the browser. Playwright will generate the code for the user interactions. `Codegen` will attempt to generate resilient text-based selectors.
@ -55,7 +45,7 @@ playwright codegen --viewport-size=800,600 playwright.dev
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --viewport-size=800,600 playwright.dev pwsh bin/Debug/netX/playwright.ps1 codegen --viewport-size=800,600 playwright.dev
``` ```
@ -79,7 +69,7 @@ playwright codegen --device="iPhone 11" playwright.dev
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --device="iPhone 11" playwright.dev pwsh bin/Debug/netX/playwright.ps1 codegen --device="iPhone 11" playwright.dev
``` ```
<img width="1239" alt="Codegen generating code for tests for playwright.dev website emulated for iPhone 11" src="https://user-images.githubusercontent.com/13063165/182360089-9dc6d33d-480e-4bb2-86a3-fec51c1c228e.png" /> <img width="1239" alt="Codegen generating code for tests for playwright.dev website emulated for iPhone 11" src="https://user-images.githubusercontent.com/13063165/182360089-9dc6d33d-480e-4bb2-86a3-fec51c1c228e.png" />
@ -102,7 +92,7 @@ playwright codegen --color-scheme=dark playwright.dev
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --color-scheme=dark playwright.dev pwsh bin/Debug/netX/playwright.ps1 codegen --color-scheme=dark playwright.dev
``` ```
<img width="1258" alt="Codegen generating code for tests for playwright.dev website in dark mode" src="https://user-images.githubusercontent.com/13063165/182359371-0bb4a7a2-abbb-4f73-8550-d67e0101f0ad.png" /> <img width="1258" alt="Codegen generating code for tests for playwright.dev website in dark mode" src="https://user-images.githubusercontent.com/13063165/182359371-0bb4a7a2-abbb-4f73-8550-d67e0101f0ad.png" />
@ -124,7 +114,7 @@ playwright codegen --timezone="Europe/Rome" --geolocation="41.890221,12.492348"
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --lang="it-IT" maps.google.com pwsh bin/Debug/netX/playwright.ps1 codegen --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --lang="it-IT" maps.google.com
``` ```
<img width="1276" alt="Codegen generating code for tests for google maps showing timezone, geoloation as Rome, Italy and in Italian language" src="https://user-images.githubusercontent.com/13063165/182394434-73e1c2a8-767e-411a-94e4-0912c1c50ecc.png" /> <img width="1276" alt="Codegen generating code for tests for google maps showing timezone, geoloation as Rome, Italy and in Italian language" src="https://user-images.githubusercontent.com/13063165/182394434-73e1c2a8-767e-411a-94e4-0912c1c50ecc.png" />
@ -148,7 +138,7 @@ playwright codegen --save-storage=auth.json
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --save-storage=auth.json pwsh bin/Debug/netX/playwright.ps1 codegen --save-storage=auth.json
``` ```
<img width="1264" alt="Screenshot 2022-08-03 at 13 28 02" src="https://user-images.githubusercontent.com/13063165/182599605-df2fbd05-622b-4cd7-8a32-0abdfea7d38d.png" /> <img width="1264" alt="Screenshot 2022-08-03 at 13 28 02" src="https://user-images.githubusercontent.com/13063165/182599605-df2fbd05-622b-4cd7-8a32-0abdfea7d38d.png" />
@ -168,7 +158,7 @@ playwright codegen --load-storage=auth.json github.com/microsoft/playwright
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen --load-storage=auth.json github.com/microsoft/playwright pwsh bin/Debug/netX/playwright.ps1 codegen --load-storage=auth.json github.com/microsoft/playwright
``` ```
<img width="1261" alt="Screenshot 2022-08-03 at 13 33 40" src="https://user-images.githubusercontent.com/13063165/182599680-05297b4e-c258-4416-8daa-b8637c1db120.png" /> <img width="1261" alt="Screenshot 2022-08-03 at 13 33 40" src="https://user-images.githubusercontent.com/13063165/182599680-05297b4e-c258-4416-8daa-b8637c1db120.png" />
@ -188,7 +178,7 @@ playwright open --load-storage=auth.json github.com/microsoft/playwright
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 open --load-storage=auth.json github.com/microsoft/playwright pwsh bin/Debug/netX/playwright.ps1 open --load-storage=auth.json github.com/microsoft/playwright
``` ```
@ -285,7 +275,3 @@ await context.RouteAsync('**/*', route => route.ContinueAsync());
var page = await context.NewPageAsync(); var page = await context.NewPageAsync();
await page.PauseAsync(); await page.PauseAsync();
``` ```
## What's Next
- [See a trace of your tests](./trace-viewer.md)

View file

@ -193,7 +193,7 @@ playwright codegen wikipedia.org
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 codegen wikipedia.org pwsh bin/Debug/netX/playwright.ps1 codegen wikipedia.org
``` ```
### Stepping through the Playwright script ### Stepping through the Playwright script

View file

@ -14,19 +14,19 @@ This image is published on [Docker Hub].
### Pull the image ### Pull the image
```bash js ```bash js
docker pull mcr.microsoft.com/playwright:v1.25.0-focal docker pull mcr.microsoft.com/playwright:v1.25.2-focal
``` ```
```bash python ```bash python
docker pull mcr.microsoft.com/playwright/python:v1.25.0-focal docker pull mcr.microsoft.com/playwright/python:v1.25.2-focal
``` ```
```bash csharp ```bash csharp
docker pull mcr.microsoft.com/playwright/dotnet:v1.25.0-focal docker pull mcr.microsoft.com/playwright/dotnet:v1.25.2-focal
``` ```
```bash java ```bash java
docker pull mcr.microsoft.com/playwright/java:v1.25.0-focal docker pull mcr.microsoft.com/playwright/java:v1.25.2-focal
``` ```
### Run the image ### Run the image
@ -38,19 +38,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. 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 ```bash js
docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v1.25.2-focal /bin/bash
``` ```
```bash python ```bash python
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/python:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host mcr.microsoft.com/playwright/python:v1.25.2-focal /bin/bash
``` ```
```bash csharp ```bash csharp
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/dotnet:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host mcr.microsoft.com/playwright/dotnet:v1.25.2-focal /bin/bash
``` ```
```bash java ```bash java
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v1.25.2-focal /bin/bash
``` ```
#### Crawling and scraping #### Crawling and scraping
@ -58,19 +58,19 @@ docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v1.25.0-focal /
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. 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 ```bash js
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v1.25.2-focal /bin/bash
``` ```
```bash python ```bash python
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/python:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/python:v1.25.2-focal /bin/bash
``` ```
```bash csharp ```bash csharp
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/dotnet:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/dotnet:v1.25.2-focal /bin/bash
``` ```
```bash java ```bash java
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/java:v1.25.0-focal /bin/bash docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/java:v1.25.2-focal /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: [`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:

View file

@ -93,4 +93,4 @@ As you interact with the page Codegen will generate the test for you in the newl
- [Write tests using web first assertions, page fixtures and locators](./writing-tests.md) - [Write tests using web first assertions, page fixtures and locators](./writing-tests.md)
- [See test reports](./running-tests.md#test-reports) - [See test reports](./running-tests.md#test-reports)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -1,16 +0,0 @@
---
id: html-reporter
title: "HTML Reporter"
---
The HTML Reporter shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests. By default, the HTML report is opened automatically if some of the tests failed.
```bash
npx playwright show-report
```
<img width="739" alt="image" src="https://user-images.githubusercontent.com/13063165/178003817-3bd2f088-4173-406c-a9e9-74c89181f381.png" />
You can click on each test to get more info on the test and explore the errors section which will show you what errors there are and on what line as well as suggestions on how to fix the errors. Each step of the test can be expanded and looked into in detail.
<img width="747" alt="image" src="https://user-images.githubusercontent.com/13063165/178007807-b88e4d22-cd40-4a07-81ab-50096eb3ea1b.png" />

View file

@ -70,9 +70,11 @@ dotnet build
4. Install required browsers by replacing `netX` with the actual output folder name, e.g. `net6.0`: 4. Install required browsers by replacing `netX` with the actual output folder name, e.g. `net6.0`:
```bash ```bash
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
``` ```
If `pwsh` is not available, you have to [install PowerShell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell).
## Add Example Tests ## Add Example Tests
Edit the `UnitTest1.cs` file with the code below to create an example end-to-end test: Edit the `UnitTest1.cs` file with the code below to create an example end-to-end test:
@ -130,6 +132,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests; namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest public class UnitTest1 : PageTest
{ {
[TestMethod] [TestMethod]
@ -194,5 +197,5 @@ See our doc on [Test Runners](./test-runners.md) to learn more about running tes
- [Run single tests, multiple tests, headed mode](./running-tests.md) - [Run single tests, multiple tests, headed mode](./running-tests.md)
- [Learn more about the NUnit and MSTest base classes](./test-runners.md) - [Learn more about the NUnit and MSTest base classes](./test-runners.md)
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)
- [Using Playwright as library](./library.md) - [Using Playwright as library](./library.md)

View file

@ -62,13 +62,9 @@ tests-examples/
demo-todo-app.spec.ts demo-todo-app.spec.ts
``` ```
The playwright [playwright.config](./test-configuration.md) is where you can add configuration for Playwright including modifying which browsers you would like to run Playwright on. The [playwright.config](./test-configuration.md) is where you can add configuration for Playwright including modifying which browsers you would like to run Playwright on. If you are running tests inside an already existing project then dependencies will be added directly to your `package.json`.
If you are running tests inside an already existing project then dependencies will be added directly to your `package.json`. The `tests` folder contains a basic example test to help you get started with testing. For a more detailed example check out the `tests-examples` folder which contains tests written to test a todo app.
The `tests` folder contains a basic example test to help you get started with testing.
For a more detailed example check out the `tests-examples` folder which contains tests written to test a todo app.
## Running the Example Test ## Running the Example Test
@ -82,7 +78,7 @@ See our doc on [Running Tests](./running-tests.md) to learn more about running t
## HTML Test Reports ## HTML Test Reports
Once your test has finished running a [HTML Reporter](./html-reporter.md) will have been created which shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests. You can click on each test and explore the test's errors as well as each step of the test. By default, the HTML report is opened automatically if some of the tests failed. Once your test has finished running a [HTML Reporter](./test-reporters.md#html-reporter) will have been created which shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests. You can click on each test and explore the test's errors as well as each step of the test. By default, the HTML report is opened automatically if some of the tests failed.
```bash ```bash
npx playwright show-report npx playwright show-report
@ -96,4 +92,4 @@ npx playwright show-report
- [Write tests using web first assertions, page fixtures and locators](./writing-tests.md) - [Write tests using web first assertions, page fixtures and locators](./writing-tests.md)
- [Run single tests, multiple tests, headed mode](./running-tests.md) - [Run single tests, multiple tests, headed mode](./running-tests.md)
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -64,4 +64,4 @@ See our doc on [Running Tests](./running-tests.md) to learn more about running t
- [Write tests using web first assertions, page fixtures and locators](./writing-tests.md) - [Write tests using web first assertions, page fixtures and locators](./writing-tests.md)
- [Run single tests, multiple tests, headed mode](./running-tests.md) - [Run single tests, multiple tests, headed mode](./running-tests.md)
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -19,7 +19,7 @@ dotnet add package Microsoft.Playwright
# Build the project # Build the project
dotnet build dotnet build
# Install required browsers - replace netX with actual output folder name, e.g. net6.0. # Install required browsers - replace netX with actual output folder name, e.g. net6.0.
pwsh bin\Debug\netX\playwright.ps1 install pwsh bin/Debug/netX/playwright.ps1 install
# If the pwsh command does not work (throws TypeNotFound), make sure to use an up-to-date version of PowerShell. # If the pwsh command does not work (throws TypeNotFound), make sure to use an up-to-date version of PowerShell.
dotnet tool update --global PowerShell dotnet tool update --global PowerShell

View file

@ -5,7 +5,7 @@ title: "Mock APIs"
Playwright provides native support for most of the browser features. However, there are some experimental APIs Playwright provides native support for most of the browser features. However, there are some experimental APIs
and APIs which are not (yet) fully supported by all browsers. Playwright usually doesn't provide dedicated and APIs which are not (yet) fully supported by all browsers. Playwright usually doesn't provide dedicated
atomation APIs in such cases. You can use mocks to test behavior of your application in such cases. This guide automation APIs in such cases. You can use mocks to test behavior of your application in such cases. This guide
gives a few examples. gives a few examples.
<!-- TOC --> <!-- TOC -->

View file

@ -719,7 +719,7 @@ playwright open --save-har=example.har --save-har-glob="**/api/**" https://examp
```bash csharp ```bash csharp
# Save API requests from example.com as "example.har" archive. # Save API requests from example.com as "example.har" archive.
pwsh bin\Debug\netX\playwright.ps1 open --save-har=example.har --save-har-glob="**/api/**" https://example.com pwsh bin/Debug/netX/playwright.ps1 open --save-har=example.har --save-har-glob="**/api/**" https://example.com
``` ```
### Recording HAR with a script ### Recording HAR with a script

View file

@ -4,6 +4,52 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.25
### New .runsettings file support
`Microsoft.Playwright.NUnit` and `Microsoft.Playwright.MSTest` will now consider the `.runsettings` file and passed settings via the CLI when running end-to-end tests. See in the [documentation](https://playwright.dev/dotnet/docs/test-runners) for a full list of supported settings.
The following does now work:
```xml
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Playwright -->
<Playwright>
<BrowserName>chromium</BrowserName>
<ExpectTimeout>5000</ExpectTimeout>
<LaunchOptions>
<Headless>true</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
<!-- General run configuration -->
<RunConfiguration>
<EnvironmentVariables>
<!-- For debugging selectors, it's recommend to set the following environment variable -->
<DEBUG>pw:api</DEBUG>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>
```
### Announcements
* 🪦 This is the last release with macOS 10.15 support (deprecated as of 1.21).
* ⚠️ Ubuntu 18 is now deprecated and will not be supported as of Dec 2022.
### Browser Versions
* Chromium 105.0.5195.19
* Mozilla Firefox 103.0
* WebKit 16.0
This version was also tested against the following stable channels:
* Google Chrome 104
* Microsoft Edge 104
## Version 1.24 ## Version 1.24
<div className="embed-youtube"> <div className="embed-youtube">
@ -60,7 +106,7 @@ Now you can record network traffic into a HAR file and re-use this traffic in yo
To record network into HAR file: To record network into HAR file:
```bash ```bash
pwsh bin\Debug\netX\playwright.ps1 open --save-har=example.har --save-har-glob="**/api/**" https://example.com pwsh bin/Debug/netX/playwright.ps1 open --save-har=example.har --save-har-glob="**/api/**" https://example.com
``` ```
Alternatively, you can record HAR programmatically: Alternatively, you can record HAR programmatically:
@ -354,7 +400,7 @@ Playwright Trace Viewer is now **available online** at https://trace.playwright.
- Playwright now supports **Ubuntu 20.04 ARM64**. You can now run Playwright tests inside Docker on Apple M1 and on Raspberry Pi. - Playwright now supports **Ubuntu 20.04 ARM64**. You can now run Playwright tests inside Docker on Apple M1 and on Raspberry Pi.
- You can now use Playwright to install stable version of Edge on Linux: - You can now use Playwright to install stable version of Edge on Linux:
```bash ```bash
pwsh bin\Debug\netX\playwright.ps1 install msedge pwsh bin/Debug/netX/playwright.ps1 install msedge
``` ```
@ -381,7 +427,7 @@ Read more about [`method: Locator.waitFor`].
### 🎭 Playwright Trace Viewer ### 🎭 Playwright Trace Viewer
- run trace viewer with `pwsh bin\Debug\netX\playwright.ps1 show-trace` and drop trace files to the trace viewer PWA - run trace viewer with `pwsh bin/Debug/netX/playwright.ps1 show-trace` and drop trace files to the trace viewer PWA
- better visual attribution of action targets - better visual attribution of action targets
Read more about [Trace Viewer](./trace-viewer). Read more about [Trace Viewer](./trace-viewer).

View file

@ -4,6 +4,28 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.25
### New APIs & changes
- Default assertions timeout now can be changed with [`setDefaultAssertionTimeout`](./test-assertions#playwright-assertions-set-default-assertion-timeout).
### Announcements
* 🪦 This is the last release with macOS 10.15 support (deprecated as of 1.21).
* ⚠️ Ubuntu 18 is now deprecated and will not be supported as of Dec 2022.
### Browser Versions
* Chromium 105.0.5195.19
* Mozilla Firefox 103.0
* WebKit 16.0
This version was also tested against the following stable channels:
* Google Chrome 104
* Microsoft Edge 104
## Version 1.24 ## Version 1.24
<div className="embed-youtube"> <div className="embed-youtube">

View file

@ -4,6 +4,53 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.25
### VSCode Extension
* Watch your tests running live & keep devtools open.
* Pick selector.
* Record new test from current page state.
![vscode extension screenshot](https://user-images.githubusercontent.com/746130/183781999-1b9fdbc5-cfae-47d6-b4f7-5d4ae89716a8.jpg)
### Test Runner
* [`method: Test.step`] now returns the value of the step function:
```ts
test('should work', async ({ page }) => {
const pageTitle = await test.step('get title', async () => {
await page.goto('https://playwright.dev');
return await page.title();
});
console.log(pageTitle);
});
```
* Added [`method: Test.describe.fixme`].
* New `'interrupted'` test status.
* Enable tracing via CLI flag: `npx playwright test --trace=on`.
### Announcements
* 🎁 We now ship Ubuntu 22.04 Jammy Jellyfish docker image: `mcr.microsoft.com/playwright:v1.25.2-jammy`.
* 🪦 This is the last release with macOS 10.15 support (deprecated as of 1.21).
* 🪦 This is the last release with Node.js 12 support, we recommend upgrading to Node.js LTS (16).
* ⚠️ Ubuntu 18 is now deprecated and will not be supported as of Dec 2022.
### Browser Versions
* Chromium 105.0.5195.19
* Mozilla Firefox 103.0
* WebKit 16.0
This version was also tested against the following stable channels:
* Google Chrome 104
* Microsoft Edge 104
## Version 1.24 ## Version 1.24
<div className="embed-youtube"> <div className="embed-youtube">
@ -237,7 +284,7 @@ Read more about [component testing with Playwright](./test-components).
} }
}); });
``` ```
* Playwright now runs on Ubuntu 22 amd64 and Ubuntu 22 arm64. We also publish new docker image `mcr.microsoft.com/playwright:v1.25.0-jammy`. * Playwright now runs on Ubuntu 22 amd64 and Ubuntu 22 arm64. We also publish new docker image `mcr.microsoft.com/playwright:v1.25.2-jammy`.
### ⚠️ Breaking Changes ⚠️ ### ⚠️ Breaking Changes ⚠️

View file

@ -4,6 +4,25 @@ title: "Release notes"
toc_max_heading_level: 2 toc_max_heading_level: 2
--- ---
## Version 1.25
### Announcements
* 🎁 We now ship Ubuntu 22.04 Jammy Jellyfish docker image: `mcr.microsoft.com/playwright/python:v1.25.2-jammy`.
* 🪦 This is the last release with macOS 10.15 support (deprecated as of 1.21).
* ⚠️ Ubuntu 18 is now deprecated and will not be supported as of Dec 2022.
### Browser Versions
* Chromium 105.0.5195.19
* Mozilla Firefox 103.0
* WebKit 16.0
This version was also tested against the following stable channels:
* Google Chrome 104
* Microsoft Edge 104
## Version 1.24 ## Version 1.24
<div className="embed-youtube"> <div className="embed-youtube">

View file

@ -31,23 +31,13 @@ You can run a single test, a set of tests or all tests. Tests can be run on diff
- Running Tests on specific browsers - Running Tests on specific browsers
```bash tab=bash-bash ```bash
BROWSER=webkit dotnet test dotnet test -- Playwright.BrowserName=webkit
```
```batch tab=bash-batch
set BROWSER=webkit
dotnet test
```
```powershell tab=bash-powershell
$env:BROWSER="webkit"
dotnet test
``` ```
- Running Tests on multiple browsers - Running Tests on multiple browsers
To run your test on multiple browsers or configurations you need to invoke the `dotnet test` command multiple times. There you can then either specify the `BROWSER` environment variable (like the previous) or pass the `browser` via the runsettings file: To run your test on multiple browsers or configurations you need to invoke the `dotnet test` command multiple times. There you can then either specify the `BROWSER` environment variable or set the `Playwright.BrowserName` via the runsettings file:
```bash ```bash
dotnet test --settings:chromium.runsettings dotnet test --settings:chromium.runsettings
@ -58,10 +48,9 @@ You can run a single test, a set of tests or all tests. Tests can be run on diff
```xml ```xml
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RunSettings> <RunSettings>
<TestRunParameters> <Playwright>
<Parameter name="browser" value="chromium" /> <BrowserName>chromium</BrowserName>
<Parameter name="headless" value="false" /> </Playwright>
</TestRunParameters>
</RunSettings> </RunSettings>
``` ```
@ -93,4 +82,4 @@ Check out our [debugging guide](./debug.md) to learn more about the [Playwright
## What's Next ## What's Next
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -90,7 +90,7 @@ Check out our [debugging guide](./debug.md) to learn more about the [Playwright
## Test Reports ## Test Reports
The [HTML Reporter](./html-reporter.md) shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests. By default, the HTML report is opened automatically if some of the tests failed. The [HTML Reporter](././test-reporters.md#html-reporter) shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests. By default, the HTML report is opened automatically if some of the tests failed.
```bash ```bash
npx playwright show-report npx playwright show-report
@ -105,4 +105,4 @@ You can click on each test and explore the tests errors as well as each step of
## What's Next ## What's Next
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -83,4 +83,4 @@ Check out our [debugging guide](./debug.md) to learn more about the [Playwright
## What's Next ## What's Next
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -1457,6 +1457,7 @@ Optional description that will be reflected in a test report.
## async method: Test.step ## async method: Test.step
* since: v1.10 * since: v1.10
- returns: <[any]>
Declares a test step. Declares a test step.
@ -1480,6 +1481,32 @@ test('test', async ({ page }) => {
}); });
``` ```
The method returns value retuned by the step callback.
```js tab=js-js
const { test, expect } = require('@playwright/test');
test('test', async ({ page }) => {
const user = await test.step('Log in', async () => {
// ...
return 'john';
});
expect(user).toBe('john');
});
```
```js tab=js-ts
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
const user = await test.step('Log in', async () => {
// ...
return 'john';
});
expect(user).toBe('john');
});
```
### param: Test.step.title ### param: Test.step.title
* since: v1.10 * since: v1.10
- `title` <[string]> - `title` <[string]>

View file

@ -650,4 +650,5 @@ export default config;
## Third party reporter showcase ## Third party reporter showcase
* [Allure](https://www.npmjs.com/package/allure-playwright) * [Allure](https://www.npmjs.com/package/allure-playwright)
* [Monocart](https://github.com/cenfun/monocart-reporter)
* [Tesults](https://www.tesults.com/docs/playwright) * [Tesults](https://www.tesults.com/docs/playwright)

View file

@ -24,11 +24,13 @@ Playwright provides base classes to write tests with NUnit via the [`Microsoft.P
# Create a new project # Create a new project
dotnet new nunit -n PlaywrightTests dotnet new nunit -n PlaywrightTests
cd PlaywrightTests cd PlaywrightTests
# Add the required reference # Add the required reference
dotnet add package Microsoft.Playwright.NUnit dotnet add package Microsoft.Playwright.NUnit
dotnet build dotnet build
# Install the required browsers and operating system dependencies # Install the required browsers and operating system dependencies
pwsh bin\Debug\netX\playwright.ps1 install --with-deps pwsh bin/Debug/netX/playwright.ps1 install --with-deps
``` ```
Modify the UnitTest1.cs: Modify the UnitTest1.cs:
@ -104,7 +106,8 @@ dotnet test --filter "Name~Slogan"
### Running NUnit tests in Parallel ### Running NUnit tests in Parallel
By default NUnit will run all test files in parallel, while running tests inside each file sequentially. It will create as many processes as there are cores on the host system. You can adjust this behavior using the NUnit.NumberOfTestWorkers parameter. By default NUnit will run all test files in parallel, while running tests inside each file sequentially (`ParallelScope.Self`). It will create as many processes as there are cores on the host system. You can adjust this behavior using the NUnit.NumberOfTestWorkers parameter.
Running test in parallel using `ParallelScope.All` or `ParallelScope.Fixtures` is not supported.
For CPU-bound tests, we recommend using as many workers as there are cores on your system, divided by 2. For IO-bound tests you can use as many workers as you have cores. For CPU-bound tests, we recommend using as many workers as there are cores on your system, divided by 2. For IO-bound tests you can use as many workers as you have cores.
@ -151,24 +154,18 @@ CLI. See the following example:
```xml ```xml
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RunSettings> <RunSettings>
<TestRunParameters> <Playwright>
<Parameter name="browser" value="chromium" /> <BrowserName>chromium</BrowserName>
<Parameter name="headless" value="false" /> <LaunchOptions>
<Parameter name="channel" value="msedge" /> <Headless>false</Headless>
</TestRunParameters> <Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings> </RunSettings>
``` ```
```bash tab=bash-bash ```bash
dotnet test -- TestRunParameters.Parameter\(name=\"browser\", value=\"chromium\"\) TestRunParameters.Parameter\(name=\"headless\", value=\"false\"\) TestRunParameters.Parameter\(name=\"channel\", value=\"msedge\"\) dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Headless=false Playwright.LaunchOptions.Channel=msedge
```
```batch tab=bash-batch
dotnet test -- TestRunParameters.Parameter(name=\"browser\", value=\"chromium\") TestRunParameters.Parameter(name=\"headless\", value=\"false\") TestRunParameters.Parameter(name=\"channel\", value=\"msedge\")
```
```powershell tab=bash-powershell
dotnet test -- TestRunParameters.Parameter(name=\"browser\", value=\"chromium\") TestRunParameters.Parameter(name=\"headless\", value=\"false\") TestRunParameters.Parameter(name=\"channel\", value=\"msedge\")
``` ```
### Using Verbose API Logs ### Using Verbose API Logs
@ -177,29 +174,33 @@ When you have enabled the [verbose API log](./debug.md#verbose-api-logs), via th
### Using the .runsettings file ### Using the .runsettings file
When running tests from Visual Studio, you can take advantage of the `.runsettings` file. When running tests from Visual Studio, you can take advantage of the `.runsettings` file. The following shows a reference of the supported values.
For example, to specify the amount of workers (`NUnit.NumberOfTestWorkers`), you can use the following snippet: For example, to specify the amount of workers you can use `NUnit.NumberOfTestWorkers` or to enable `DEBUG` logs `RunConfiguration.EnvironmentVariables`.
```xml ```xml
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RunSettings> <RunSettings>
<!-- NUnit adapter -->
<NUnit> <NUnit>
<NumberOfTestWorkers>24</NumberOfTestWorkers> <NumberOfTestWorkers>24</NumberOfTestWorkers>
</NUnit> </NUnit>
</RunSettings> <!-- General run configuration -->
```
If you want to enable debugging, you can set the `DEBUG` variable to `pw:api` as documented, by doing:
```xml
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration> <RunConfiguration>
<EnvironmentVariables> <EnvironmentVariables>
<!-- For debugging selectors, it's recommend to set the following environment variable -->
<DEBUG>pw:api</DEBUG> <DEBUG>pw:api</DEBUG>
</EnvironmentVariables> </EnvironmentVariables>
</RunConfiguration> </RunConfiguration>
<!-- Playwright -->
<Playwright>
<BrowserName>chromium</BrowserName>
<ExpectTimeout>5000</ExpectTimeout>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings> </RunSettings>
``` ```
@ -224,11 +225,13 @@ Playwright provides base classes to write tests with MSTest via the [`Microsoft.
# Create a new project # Create a new project
dotnet new mstest -n PlaywrightTests dotnet new mstest -n PlaywrightTests
cd PlaywrightTests cd PlaywrightTests
# Add the required reference # Add the required reference
dotnet add package Microsoft.Playwright.MSTest dotnet add package Microsoft.Playwright.MSTest
dotnet build dotnet build
# Install the required browsers and operating system dependencies # Install the required browsers and operating system dependencies
pwsh bin\Debug\netX\playwright.ps1 install --with-deps pwsh bin/Debug/netX/playwright.ps1 install --with-deps
``` ```
Modify the UnitTest1.cs: Modify the UnitTest1.cs:
@ -304,7 +307,8 @@ dotnet test --filter "Name~Slogan"
### Running MSTest tests in Parallel ### Running MSTest tests in Parallel
By default MSTest will run all classes in parallel, while running tests inside each class sequentially. It will create as many processes as there are cores on the host system. You can adjust this behavior by using the following CLI parameter or using a `.runsettings` file, see below. By default MSTest will run all classes in parallel, while running tests inside each class sequentially (`ExecutionScope.ClassLevel`). It will create as many processes as there are cores on the host system. You can adjust this behavior by using the following CLI parameter or using a `.runsettings` file, see below.
Running tests in parallel at the method level (`ExecutionScope.MethodLevel`) is not supported.
```bash ```bash
dotnet test --settings:.runsettings -- MSTest.Parallelize.Workers=4 dotnet test --settings:.runsettings -- MSTest.Parallelize.Workers=4
@ -357,24 +361,18 @@ CLI. See the following example:
```xml ```xml
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RunSettings> <RunSettings>
<TestRunParameters> <Playwright>
<Parameter name="browser" value="chromium" /> <BrowserName>chromium</BrowserName>
<Parameter name="headless" value="false" /> <LaunchOptions>
<Parameter name="channel" value="msedge" /> <Headless>false</Headless>
</TestRunParameters> <Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings> </RunSettings>
``` ```
```bash tab=bash-bash ```bash
dotnet test -- TestRunParameters.Parameter\(name=\"browser\", value=\"chromium\"\) TestRunParameters.Parameter\(name=\"headless\", value=\"false\"\) TestRunParameters.Parameter\(name=\"channel\", value=\"msedge\"\) dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Headless=false Playwright.LaunchOptions.Channel=msedge
```
```batch tab=bash-batch
dotnet test -- TestRunParameters.Parameter(name=\"browser\", value=\"chromium\") TestRunParameters.Parameter(name=\"headless\", value=\"false\") TestRunParameters.Parameter(name=\"channel\", value=\"msedge\")
```
```powershell tab=bash-powershell
dotnet test -- TestRunParameters.Parameter(name=\"browser\", value=\"chromium\") TestRunParameters.Parameter(name=\"headless\", value=\"false\") TestRunParameters.Parameter(name=\"channel\", value=\"msedge\")
``` ```
### Using Verbose API Logs ### Using Verbose API Logs
@ -383,9 +381,9 @@ When you have enabled the [verbose API log](./debug.md#verbose-api-logs), via th
### Using the .runsettings file ### Using the .runsettings file
When running tests from Visual Studio, you can take advantage of the `.runsettings` file. When running tests from Visual Studio, you can take advantage of the `.runsettings` file. The following shows a reference of the supported values.
For example, to specify the amount of workers (`MSTest.Parallelize.Workers`), you can use the following snippet: For example, to specify the number of workers, you can use `MSTest.Parallelize.Workers`. You can also enable `DEBUG` logs using `RunConfiguration.EnvironmentVariables`.
```xml ```xml
<RunSettings> <RunSettings>
@ -396,19 +394,22 @@ For example, to specify the amount of workers (`MSTest.Parallelize.Workers`), yo
<Scope>ClassLevel</Scope> <Scope>ClassLevel</Scope>
</Parallelize> </Parallelize>
</MSTest> </MSTest>
</RunSettings> <!-- General run configuration -->
```
If you want to enable debugging, you can set the `DEBUG` variable to `pw:api` as documented, by doing:
```xml
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration> <RunConfiguration>
<EnvironmentVariables> <EnvironmentVariables>
<!-- For debugging selectors, it's recommend to set the following environment variable -->
<DEBUG>pw:api</DEBUG> <DEBUG>pw:api</DEBUG>
</EnvironmentVariables> </EnvironmentVariables>
</RunConfiguration> </RunConfiguration>
<!-- Playwright -->
<Playwright>
<BrowserName>chromium</BrowserName>
<ExpectTimeout>5000</ExpectTimeout>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings> </RunSettings>
``` ```

View file

@ -56,7 +56,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: If you are not on the same operating system as your CI system, you can use Docker to generate/update the screenshots:
```bash ```bash
docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.25.0-focal /bin/bash docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.25.2-focal /bin/bash
npm install npm install
npx playwright test --update-snapshots npx playwright test --update-snapshots
``` ```

View file

@ -0,0 +1,120 @@
---
id: trace-viewer-intro
title: "Trace Viewer"
---
Playwright Trace Viewer is a GUI tool that lets you explore recorded Playwright traces of your tests meaning you can go back and forward though each action of your test and visually see what was happening during each action.
**You will learn**
- How to record a trace
- How to open the HTML report
- How to open the trace viewer
## Recording a trace
Traces can be recorded using the [`property: BrowserContext.tracing`] API as follows:
```java
Browser browser = browserType.launch();
BrowserContext context = browser.newContext();
// Start tracing before creating / navigating a page.
context.tracing().start(new Tracing.StartOptions()
.setScreenshots(true)
.setSnapshots(true)
.setSources(true));
Page page = context.newPage();
page.navigate("https://playwright.dev");
// Stop tracing and export it into a zip archive.
context.tracing().stop(new Tracing.StopOptions()
.setPath(Paths.get("trace.zip")));
```
```python async
browser = await chromium.launch()
context = await browser.new_context()
# Start tracing before creating / navigating a page.
await context.tracing.start(screenshots=True, snapshots=True, sources=True)
await page.goto("https://playwright.dev")
# Stop tracing and export it into a zip archive.
await context.tracing.stop(path = "trace.zip")
```
```python sync
browser = chromium.launch()
context = browser.new_context()
# Start tracing before creating / navigating a page.
context.tracing.start(screenshots=True, snapshots=True, sources=True)
page.goto("https://playwright.dev")
# Stop tracing and export it into a zip archive.
context.tracing.stop(path = "trace.zip")
```
```csharp
await using var browser = playwright.Chromium.LaunchAsync();
await using var context = await browser.NewContextAsync();
// Start tracing before creating / navigating a page.
await context.Tracing.StartAsync(new()
{
Screenshots = true,
Snapshots = true,
Sources = true
});
var page = context.NewPageAsync();
await page.GotoAsync("https://playwright.dev");
// Stop tracing and export it into a zip archive.
await context.Tracing.StopAsync(new()
{
Path = "trace.zip"
});
```
This will record the trace and place it into the file named `trace.zip`.
## Opening the trace
You can open the saved trace using Playwright CLI or in your browser on [`trace.playwright.dev`](https://trace.playwright.dev).
```bash js
npx playwright show-trace trace.zip
```
```bash java
mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="show-trace trace.zip"
```
```bash python
playwright show-trace trace.zip
```
```bash csharp
pwsh bin/Debug/netX/playwright.ps1 show-trace trace.zip
```
## Viewing the trace
View traces of your test by clicking through each action or hovering using the timeline and see the state of the page before and after the action. Inspect the log, source and network during each step of the test. The trace viewer creates a DOM snapshot so you can fully interact with it, open devtools etc.
<img width="941" alt="image" src="https://user-images.githubusercontent.com/13063165/182618490-3340cfbf-7ac9-46e2-8157-6a8ce52dca28.png" />
To learn more check out our detailed guide on [Trace Viewer](/trace-viewer.md).

View file

@ -0,0 +1,89 @@
---
id: trace-viewer-intro
title: "Trace Viewer"
---
Playwright Trace Viewer is a GUI tool that lets you explore recorded Playwright traces of your tests meaning you can go back and forward though each action of your test and visually see what was happening during each action.
**You will learn**
- [How to record a trace](/trace-viewer-intro.md#recording-a-trace)
- [How to open the HTML report](/trace-viewer-intro.md#opening-the-html-report)
- [How to open and view the trace](/trace-viewer-intro.md#viewing-the-trace)
## Recording a Trace
By default the [playwright.config](/test-configuration.md#record-test-trace) file will contain the configuration needed to create a `trace.zip` file for each test. Traces are setup to run `on-first-retry` meaning they will be run on the first retry of a failed test. Also `retires` are set to 2 when running on CI and 0 locally. This means the traces will be recorded on the first retry of a failed test but not on the first run and not on the second retry.
```js tab=js-js
// @ts-check
/** @type {import('@playwright/test').PlaywrightTestConfig} */
const config = {
retries: process.env.CI ? 2 : 0, // set to 2 when running on CI
...
use: {
trace: 'on-first-retry', // record traces on first retry of each test
},
};
module.exports = config;
```
```js tab=js-ts
import type { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
retries: process.env.CI ? 2 : 0, // set to 2 when running on CI
...
use: {
trace: 'on-first-retry', // record traces on first retry of each test
},
};
export default config;
```
To learn more about available options to record a trace check out our detailed guide on [Trace Viewer](/trace-viewer.md).
Traces are normally run in a Continuous Integration(CI) environment as locally you can use [debugging](/debug.md) methods to debug tests. However should you want to run traces locally you can force tracing to be on with `--trace on`.
```bash
npx playwright test --trace on
```
:::note
The `trace-on` flag was introduced in Playwright v1.25. Check your `package.json` to sure you have at least this version of Playwright installed.
:::
## Opening the HTML Report
If you have a failed test then tests will run a total of 3 times. On the first retry the trace will be recorded. After the second retry the tests will stop running and a HTML report is available to view.
```bash
npx playwright show-report
```
In the HTML report click on the trace icon to directly open the trace file.
<img width="744" alt="image" src="https://user-images.githubusercontent.com/13063165/182853447-e26f4d39-b4e2-4d9b-a890-ac1838c088e1.png" />
You can also click on the test file and then click the 'Retry #1' tab which will show you a traces section in your html report. Here you can open the trace by clicking on the screenshot.
<img width="749" alt="image" src="https://user-images.githubusercontent.com/13063165/183130559-16a83a39-2f1d-4560-850c-d025fad789b3.png" />
To learn more about reporters check out our detailed guide on reporters including the [HTML Reporter](/test-reporters.md#html-reporter).
## Viewing the Trace
View traces of your test by clicking through each action or hovering using the timeline and see the state of the page before and after the action. Inspect the log, source and network during each step of the test. The trace viewer creates a DOM snapshot so you can fully interact with it, open devtools etc.
<img width="941" alt="image" src="https://user-images.githubusercontent.com/13063165/182618490-3340cfbf-7ac9-46e2-8157-6a8ce52dca28.png" />
To learn more about traces check out our detailed guide on [Trace Viewer](/trace-viewer.md).

View file

@ -52,13 +52,14 @@ await page.goto('https://playwright.dev');
await context.tracing.stop({ path: 'trace.zip' }); await context.tracing.stop({ path: 'trace.zip' });
``` ```
You can also use `trace: 'retain-on-failure'` if you do not enable retries but still want traces for failed tests.
Available options to record a trace: Available options to record a trace:
- `'off'` - Do not record a trace.
- `'on'` - Record a trace for each test.
- `'retain-on-failure'` - Record a trace for each test, but remove it from successful test runs.
- `'on-first-retry'` - Record a trace only when retrying a test for the first time. - `'on-first-retry'` - Record a trace only when retrying a test for the first time.
- `'off'` - Do not record a trace.
- `'on'` - Record a trace for each test. (not recommended as it's performance heavy)
- `'retain-on-failure'` - Record a trace for each test, but remove it from successful test runs.
You can also use `trace: 'retain-on-failure'` if you do not enable retries but still want traces for failed tests.
If you are not using Playwright Test, use the [`property: BrowserContext.tracing`] API instead. If you are not using Playwright Test, use the [`property: BrowserContext.tracing`] API instead.
@ -152,7 +153,7 @@ playwright show-trace trace.zip
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 show-trace trace.zip pwsh bin/Debug/netX/playwright.ps1 show-trace trace.zip
``` ```
## Actions ## Actions
@ -219,7 +220,7 @@ playwright show-trace https://example.com/trace.zip
``` ```
```bash csharp ```bash csharp
pwsh bin\Debug\netX\playwright.ps1 show-trace https://example.com/trace.zip pwsh bin/Debug/netX/playwright.ps1 show-trace https://example.com/trace.zip
``` ```
## Using [trace.playwright.dev](https://trace.playwright.dev) ## Using [trace.playwright.dev](https://trace.playwright.dev)

View file

@ -58,6 +58,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests; namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest public class UnitTest1 : PageTest
{ {
[TestMethod] [TestMethod]
@ -153,6 +154,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests; namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest public class UnitTest1 : PageTest
{ {
[TestMethod] [TestMethod]
@ -213,6 +215,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests; namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest public class UnitTest1 : PageTest
{ {
[TestMethod] [TestMethod]
@ -237,4 +240,4 @@ public class UnitTest1 : PageTest
- [Run single tests, multiple tests, headed mode](./running-tests.md) - [Run single tests, multiple tests, headed mode](./running-tests.md)
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -146,4 +146,4 @@ test.describe("navigation", () => {
- [Run single tests, multiple tests, headed mode](./running-tests.md) - [Run single tests, multiple tests, headed mode](./running-tests.md)
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

View file

@ -104,4 +104,4 @@ def test_main_navigation(page: Page):
- [Run single tests, multiple tests, headed mode](./running-tests.md) - [Run single tests, multiple tests, headed mode](./running-tests.md)
- [Generate tests with Codegen](./codegen.md) - [Generate tests with Codegen](./codegen.md)
- [See a trace of your tests](./trace-viewer.md) - [See a trace of your tests](./trace-viewer-intro.md)

60
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "playwright-internal", "name": "playwright-internal",
"version": "1.25.0-next", "version": "1.25.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "playwright-internal", "name": "playwright-internal",
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
@ -6431,11 +6431,11 @@
"version": "0.0.0" "version": "0.0.0"
}, },
"packages/playwright": { "packages/playwright": {
"version": "1.25.0-next", "version": "1.25.2",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -6445,11 +6445,11 @@
} }
}, },
"packages/playwright-chromium": { "packages/playwright-chromium": {
"version": "1.25.0-next", "version": "1.25.2",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -6459,7 +6459,7 @@
} }
}, },
"packages/playwright-core": { "packages/playwright-core": {
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -6470,10 +6470,10 @@
}, },
"packages/playwright-ct-react": { "packages/playwright-ct-react": {
"name": "@playwright/experimental-ct-react", "name": "@playwright/experimental-ct-react",
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@vitejs/plugin-react": "^1.0.7", "@vitejs/plugin-react": "^1.0.7",
"vite": "^2.9.5" "vite": "^2.9.5"
}, },
@ -6483,10 +6483,10 @@
}, },
"packages/playwright-ct-svelte": { "packages/playwright-ct-svelte": {
"name": "@playwright/experimental-ct-svelte", "name": "@playwright/experimental-ct-svelte",
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@sveltejs/vite-plugin-svelte": "^1.0.1", "@sveltejs/vite-plugin-svelte": "^1.0.1",
"vite": "^3.0.0" "vite": "^3.0.0"
}, },
@ -6565,10 +6565,10 @@
}, },
"packages/playwright-ct-vue": { "packages/playwright-ct-vue": {
"name": "@playwright/experimental-ct-vue", "name": "@playwright/experimental-ct-vue",
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^2.3.1",
"vite": "^2.9.5" "vite": "^2.9.5"
}, },
@ -6616,10 +6616,10 @@
}, },
"packages/playwright-ct-vue2": { "packages/playwright-ct-vue2": {
"name": "@playwright/experimental-ct-vue2", "name": "@playwright/experimental-ct-vue2",
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"vite": "^2.9.5", "vite": "^2.9.5",
"vite-plugin-vue2": "^2.0.1" "vite-plugin-vue2": "^2.0.1"
}, },
@ -6631,11 +6631,11 @@
} }
}, },
"packages/playwright-firefox": { "packages/playwright-firefox": {
"version": "1.25.0-next", "version": "1.25.2",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -6646,11 +6646,11 @@
}, },
"packages/playwright-test": { "packages/playwright-test": {
"name": "@playwright/test", "name": "@playwright/test",
"version": "1.25.0-next", "version": "1.25.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/node": "*", "@types/node": "*",
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -6660,11 +6660,11 @@
} }
}, },
"packages/playwright-webkit": { "packages/playwright-webkit": {
"version": "1.25.0-next", "version": "1.25.2",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@ -7478,7 +7478,7 @@
"@playwright/experimental-ct-react": { "@playwright/experimental-ct-react": {
"version": "file:packages/playwright-ct-react", "version": "file:packages/playwright-ct-react",
"requires": { "requires": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@vitejs/plugin-react": "^1.0.7", "@vitejs/plugin-react": "^1.0.7",
"vite": "^2.9.5" "vite": "^2.9.5"
} }
@ -7486,7 +7486,7 @@
"@playwright/experimental-ct-svelte": { "@playwright/experimental-ct-svelte": {
"version": "file:packages/playwright-ct-svelte", "version": "file:packages/playwright-ct-svelte",
"requires": { "requires": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@sveltejs/vite-plugin-svelte": "^1.0.1", "@sveltejs/vite-plugin-svelte": "^1.0.1",
"svelte": "^3.49.0", "svelte": "^3.49.0",
"vite": "^3.0.0" "vite": "^3.0.0"
@ -7522,7 +7522,7 @@
"@playwright/experimental-ct-vue": { "@playwright/experimental-ct-vue": {
"version": "file:packages/playwright-ct-vue", "version": "file:packages/playwright-ct-vue",
"requires": { "requires": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^2.3.1",
"vite": "^2.9.5" "vite": "^2.9.5"
}, },
@ -7561,7 +7561,7 @@
"@playwright/experimental-ct-vue2": { "@playwright/experimental-ct-vue2": {
"version": "file:packages/playwright-ct-vue2", "version": "file:packages/playwright-ct-vue2",
"requires": { "requires": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"vite": "^2.9.5", "vite": "^2.9.5",
"vite-plugin-vue2": "^2.0.1", "vite-plugin-vue2": "^2.0.1",
"vue": "^2.6.14" "vue": "^2.6.14"
@ -7571,7 +7571,7 @@
"version": "file:packages/playwright-test", "version": "file:packages/playwright-test",
"requires": { "requires": {
"@types/node": "*", "@types/node": "*",
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
}, },
"@rollup/pluginutils": { "@rollup/pluginutils": {
@ -10366,13 +10366,13 @@
"playwright": { "playwright": {
"version": "file:packages/playwright", "version": "file:packages/playwright",
"requires": { "requires": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
}, },
"playwright-chromium": { "playwright-chromium": {
"version": "file:packages/playwright-chromium", "version": "file:packages/playwright-chromium",
"requires": { "requires": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
}, },
"playwright-core": { "playwright-core": {
@ -10381,13 +10381,13 @@
"playwright-firefox": { "playwright-firefox": {
"version": "file:packages/playwright-firefox", "version": "file:packages/playwright-firefox",
"requires": { "requires": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
}, },
"playwright-webkit": { "playwright-webkit": {
"version": "file:packages/playwright-webkit", "version": "file:packages/playwright-webkit",
"requires": { "requires": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
}, },
"postcss": { "postcss": {

View file

@ -1,7 +1,7 @@
{ {
"name": "playwright-internal", "name": "playwright-internal",
"private": true, "private": true,
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-chromium", "name": "playwright-chromium",
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate Chromium", "description": "A high-level API to automate Chromium",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -28,6 +28,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-core", "name": "playwright-core",
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",

View file

@ -715,7 +715,7 @@ function buildBasePlaywrightCLICommand(cliTargetLang: string | undefined): strin
case 'java': case 'java':
return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="...options.."`; return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="...options.."`;
case 'csharp': case 'csharp':
return `pwsh bin\\Debug\\netX\\playwright.ps1`; return `pwsh bin/Debug/netX/playwright.ps1`;
default: default:
return `npx playwright`; return `npx playwright`;
} }

View file

@ -90,6 +90,51 @@ class ProtocolHandler {
constructor(playwright: Playwright) { constructor(playwright: Playwright) {
this._playwright = playwright; this._playwright = playwright;
playwright.instrumentation.addListener({
onPageOpen: () => this._sendSnapshot(),
onPageNavigated: () => this._sendSnapshot(),
onPageClose: () => this._sendSnapshot(),
}, null);
}
private _sendSnapshot() {
const browsers = [];
for (const browser of this._playwright.allBrowsers()) {
const b = {
name: browser.options.name,
guid: browser.guid,
contexts: [] as any[]
};
browsers.push(b);
for (const context of browser.contexts()) {
const c = {
guid: context.guid,
pages: [] as any[]
};
b.contexts.push(c);
for (const page of context.pages()) {
const p = {
guid: page.guid,
url: page.mainFrame().url()
};
c.pages.push(p);
}
}
}
process.send!({ method: 'browsersChanged', params: { browsers } });
}
async resetForReuse() {
const contexts = new Set<BrowserContext>();
for (const page of this._playwright.allPages())
contexts.add(page.context());
for (const context of contexts)
await context.resetForReuse(internalMetadata, null);
}
async navigate(params: { url: string }) {
for (const p of this._playwright.allPages())
await p.mainFrame().goto(internalMetadata, params.url);
} }
async setMode(params: { mode: Mode, language?: string, file?: string }) { async setMode(params: { mode: Mode, language?: string, file?: string }) {

View file

@ -100,6 +100,8 @@ export abstract class BrowserContext extends SdkObject {
setSelectors(selectors: Selectors) { setSelectors(selectors: Selectors) {
this._selectors = selectors; this._selectors = selectors;
for (const page of this.pages())
page.selectors = selectors;
} }
selectors(): Selectors { selectors(): Selectors {
@ -157,12 +159,14 @@ export abstract class BrowserContext extends SdkObject {
return JSON.stringify(paramsCopy); return JSON.stringify(paramsCopy);
} }
async resetForReuse(metadata: CallMetadata, params: channels.BrowserNewContextForReuseParams) { async resetForReuse(metadata: CallMetadata, params: channels.BrowserNewContextForReuseParams | null) {
this.setDefaultNavigationTimeout(undefined); this.setDefaultNavigationTimeout(undefined);
this.setDefaultTimeout(undefined); this.setDefaultTimeout(undefined);
if (params) {
for (const key of paramsThatAllowContextReuse) for (const key of paramsThatAllowContextReuse)
(this._options as any)[key] = params[key]; (this._options as any)[key] = params[key];
}
await this._cancelAllRoutesInFlight(); await this._cancelAllRoutesInFlight();

View file

@ -47,7 +47,7 @@ export class BrowserDispatcher extends Dispatcher<Browser, channels.BrowserChann
} }
async newContextForReuse(params: channels.BrowserNewContextForReuseParams, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> { async newContextForReuse(params: channels.BrowserNewContextForReuseParams, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> {
return newContextForReuse(this._object, this._scope, params, metadata); return newContextForReuse(this._object, this._scope, params, null, metadata);
} }
async close(): Promise<void> { async close(): Promise<void> {
@ -104,7 +104,7 @@ export class ConnectedBrowserDispatcher extends Dispatcher<Browser, channels.Bro
} }
async newContextForReuse(params: channels.BrowserNewContextForReuseParams, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> { async newContextForReuse(params: channels.BrowserNewContextForReuseParams, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> {
return newContextForReuse(this._object, this._scope, params, metadata); return newContextForReuse(this._object, this._scope, params, this.selectors, metadata);
} }
async close(): Promise<void> { async close(): Promise<void> {
@ -141,7 +141,7 @@ export class ConnectedBrowserDispatcher extends Dispatcher<Browser, channels.Bro
} }
} }
async function newContextForReuse(browser: Browser, scope: DispatcherScope, params: channels.BrowserNewContextForReuseParams, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> { async function newContextForReuse(browser: Browser, scope: DispatcherScope, params: channels.BrowserNewContextForReuseParams, selectors: Selectors | null, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> {
const { context, needsReset } = await browser.newContextForReuse(params, metadata); const { context, needsReset } = await browser.newContextForReuse(params, metadata);
if (needsReset) { if (needsReset) {
const oldContextDispatcher = existingDispatcher<BrowserContextDispatcher>(context); const oldContextDispatcher = existingDispatcher<BrowserContextDispatcher>(context);
@ -149,6 +149,8 @@ async function newContextForReuse(browser: Browser, scope: DispatcherScope, para
oldContextDispatcher._dispose(); oldContextDispatcher._dispose();
await context.resetForReuse(metadata, params); await context.resetForReuse(metadata, params);
} }
if (selectors)
context.setSelectors(selectors);
const contextDispatcher = new BrowserContextDispatcher(scope, context); const contextDispatcher = new BrowserContextDispatcher(scope, context);
return { context: contextDispatcher }; return { context: contextDispatcher };
} }

View file

@ -68,7 +68,7 @@ export class Firefox extends BrowserType {
throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --profile argument'); throw new Error('Pass userDataDir parameter to `browserType.launchPersistentContext(userDataDir, ...)` instead of specifying --profile argument');
if (args.find(arg => arg.startsWith('-juggler'))) if (args.find(arg => arg.startsWith('-juggler')))
throw new Error('Use the port parameter instead of -juggler argument'); throw new Error('Use the port parameter instead of -juggler argument');
const firefoxUserPrefs = isPersistent ? undefined : options.firefoxUserPrefs; const firefoxUserPrefs = isPersistent ? undefined : { ...kBandaidFirefoxUserPrefs, ...options.firefoxUserPrefs };
if (firefoxUserPrefs) { if (firefoxUserPrefs) {
const lines: string[] = []; const lines: string[] = [];
for (const [name, value] of Object.entries(firefoxUserPrefs)) for (const [name, value] of Object.entries(firefoxUserPrefs))
@ -92,3 +92,9 @@ export class Firefox extends BrowserType {
return firefoxArguments; return firefoxArguments;
} }
} }
// Prefs for quick fixes that didn't make it to the build.
// Should all be moved to `playwright.cfg`.
const kBandaidFirefoxUserPrefs = {
'network.cookie.cookieBehavior': 4,
};

View file

@ -239,7 +239,7 @@ export class FrameManager {
frame._onClearLifecycle(); frame._onClearLifecycle();
const navigationEvent: NavigationEvent = { url, name, newDocument: frame._currentDocument, isPublic: true }; const navigationEvent: NavigationEvent = { url, name, newDocument: frame._currentDocument, isPublic: true };
frame.emit(Frame.Events.InternalNavigation, navigationEvent); this._fireInternalFrameNavigation(frame, navigationEvent);
if (!initial) { if (!initial) {
debugLogger.log('api', ` navigated to "${url}"`); debugLogger.log('api', ` navigated to "${url}"`);
this._page.frameNavigatedToNewDocument(frame); this._page.frameNavigatedToNewDocument(frame);
@ -254,7 +254,7 @@ export class FrameManager {
return; return;
frame._url = url; frame._url = url;
const navigationEvent: NavigationEvent = { url, name: frame._name, isPublic: true }; const navigationEvent: NavigationEvent = { url, name: frame._name, isPublic: true };
frame.emit(Frame.Events.InternalNavigation, navigationEvent); this._fireInternalFrameNavigation(frame, navigationEvent);
debugLogger.log('api', ` navigated to "${url}"`); debugLogger.log('api', ` navigated to "${url}"`);
} }
@ -272,7 +272,7 @@ export class FrameManager {
isPublic: !(documentId && frame._redirectedNavigations.has(documentId)), isPublic: !(documentId && frame._redirectedNavigations.has(documentId)),
}; };
frame.setPendingDocument(undefined); frame.setPendingDocument(undefined);
frame.emit(Frame.Events.InternalNavigation, navigationEvent); this._fireInternalFrameNavigation(frame, navigationEvent);
} }
frameDetached(frameId: string) { frameDetached(frameId: string) {
@ -462,6 +462,12 @@ export class FrameManager {
if (ws) if (ws)
ws.error(errorMessage); ws.error(errorMessage);
} }
private _fireInternalFrameNavigation(frame: Frame, event: NavigationEvent) {
frame.emit(Frame.Events.InternalNavigation, event);
if (event.isPublic && !frame.parentFrame())
frame.instrumentation.onPageNavigated(frame._page, event.url);
}
} }
export class Frame extends SdkObject { export class Frame extends SdkObject {
@ -1708,8 +1714,8 @@ export class Frame extends SdkObject {
localStorage.clear(); localStorage.clear();
// Clean Service Workers // Clean Service Workers
const registrations = await navigator.serviceWorker.getRegistrations(); const registrations = navigator.serviceWorker ? await navigator.serviceWorker.getRegistrations() : [];
await Promise.all(registrations.map(r => r.unregister())); await Promise.all(registrations.map(r => r.unregister())).catch(() => {});
// Clean IndexedDB // Clean IndexedDB
for (const db of await indexedDB.databases?.() || []) { for (const db of await indexedDB.databases?.() || []) {
@ -1717,7 +1723,7 @@ export class Frame extends SdkObject {
if (db.name) if (db.name)
indexedDB.deleteDatabase(db.name!); indexedDB.deleteDatabase(db.name!);
} }
}); }).catch(() => {});
} }
} }

View file

@ -326,7 +326,7 @@ class Recorder {
if (event.key === 'Insert' && event.shiftKey) if (event.key === 'Insert' && event.shiftKey)
return false; return false;
} }
if (['Shift', 'Control', 'Meta', 'Alt'].includes(event.key)) if (['Shift', 'Control', 'Meta', 'Alt', 'Process'].includes(event.key))
return false; return false;
const hasModifier = event.ctrlKey || event.altKey || event.metaKey; const hasModifier = event.ctrlKey || event.altKey || event.metaKey;
if (event.key.length === 1 && !hasModifier) if (event.key.length === 1 && !hasModifier)

View file

@ -63,6 +63,7 @@ export interface Instrumentation {
onAfterCall(sdkObject: SdkObject, metadata: CallMetadata): Promise<void>; onAfterCall(sdkObject: SdkObject, metadata: CallMetadata): Promise<void>;
onEvent(sdkObject: SdkObject, metadata: CallMetadata): void; onEvent(sdkObject: SdkObject, metadata: CallMetadata): void;
onPageOpen(page: Page): void; onPageOpen(page: Page): void;
onPageNavigated(page: Page, url: string): void;
onPageClose(page: Page): void; onPageClose(page: Page): void;
onBrowserOpen(browser: Browser): void; onBrowserOpen(browser: Browser): void;
onBrowserClose(browser: Browser): void; onBrowserClose(browser: Browser): void;
@ -75,6 +76,7 @@ export interface InstrumentationListener {
onAfterCall?(sdkObject: SdkObject, metadata: CallMetadata): Promise<void>; onAfterCall?(sdkObject: SdkObject, metadata: CallMetadata): Promise<void>;
onEvent?(sdkObject: SdkObject, metadata: CallMetadata): void; onEvent?(sdkObject: SdkObject, metadata: CallMetadata): void;
onPageOpen?(page: Page): void; onPageOpen?(page: Page): void;
onPageNavigated?(page: Page, url: string): void;
onPageClose?(page: Page): void; onPageClose?(page: Page): void;
onBrowserOpen?(browser: Browser): void; onBrowserOpen?(browser: Browser): void;
onBrowserClose?(browser: Browser): void; onBrowserClose?(browser: Browser): void;

View file

@ -166,7 +166,7 @@ export class Page extends SdkObject {
_clientRequestInterceptor: network.RouteHandler | undefined; _clientRequestInterceptor: network.RouteHandler | undefined;
_serverRequestInterceptor: network.RouteHandler | undefined; _serverRequestInterceptor: network.RouteHandler | undefined;
_ownedContext: BrowserContext | undefined; _ownedContext: BrowserContext | undefined;
readonly selectors: Selectors; selectors: Selectors;
_pageIsError: Error | undefined; _pageIsError: Error | undefined;
_video: Artifact | null = null; _video: Artifact | null = null;
_opener: Page | undefined; _opener: Page | undefined;

View file

@ -853,7 +853,7 @@ export function buildPlaywrightCLICommand(sdkLanguage: string, parameters: strin
case 'java': case 'java':
return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="${parameters}"`; return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="${parameters}"`;
case 'csharp': case 'csharp':
return `pwsh bin\\Debug\\netX\\playwright.ps1 ${parameters}`; return `pwsh bin/Debug/netX/playwright.ps1 ${parameters}`;
default: default:
return `npx playwright ${parameters}`; return `npx playwright ${parameters}`;
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-react", "name": "@playwright/experimental-ct-react",
"version": "1.25.0-next", "version": "1.25.2",
"description": "Playwright Component Testing for React", "description": "Playwright Component Testing for React",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -27,7 +27,7 @@
}, },
"dependencies": { "dependencies": {
"@vitejs/plugin-react": "^1.0.7", "@vitejs/plugin-react": "^1.0.7",
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"vite": "^2.9.5" "vite": "^2.9.5"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-svelte", "name": "@playwright/experimental-ct-svelte",
"version": "1.25.0-next", "version": "1.25.2",
"description": "Playwright Component Testing for Svelte", "description": "Playwright Component Testing for Svelte",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -26,7 +26,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"@sveltejs/vite-plugin-svelte": "^1.0.1", "@sveltejs/vite-plugin-svelte": "^1.0.1",
"vite": "^3.0.0" "vite": "^3.0.0"
}, },

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-vue", "name": "@playwright/experimental-ct-vue",
"version": "1.25.0-next", "version": "1.25.2",
"description": "Playwright Component Testing for Vue", "description": "Playwright Component Testing for Vue",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -27,7 +27,7 @@
}, },
"dependencies": { "dependencies": {
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^2.3.1",
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"vite": "^2.9.5" "vite": "^2.9.5"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/experimental-ct-vue2", "name": "@playwright/experimental-ct-vue2",
"version": "1.25.0-next", "version": "1.25.2",
"description": "Playwright Component Testing for Vue2", "description": "Playwright Component Testing for Vue2",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -26,7 +26,7 @@
} }
}, },
"dependencies": { "dependencies": {
"@playwright/test": "1.25.0-next", "@playwright/test": "1.25.2",
"vite": "^2.9.5", "vite": "^2.9.5",
"vite-plugin-vue2": "^2.0.1" "vite-plugin-vue2": "^2.0.1"
}, },

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-firefox", "name": "playwright-firefox",
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate Firefox", "description": "A high-level API to automate Firefox",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -28,6 +28,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@playwright/test", "name": "@playwright/test",
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -34,6 +34,6 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/node": "*", "@types/node": "*",
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
} }

View file

@ -243,7 +243,7 @@ function restartWithExperimentalTsEsm(configFile: string | null): boolean {
return false; return false;
if (!fileIsModule(configFile)) if (!fileIsModule(configFile))
return false; return false;
const NODE_OPTIONS = (process.env.NODE_OPTIONS || '') + ` --experimental-loader=${url.pathToFileURL(require.resolve('@playwright/test/lib/experimentalLoader')).toString()}`; const NODE_OPTIONS = (process.env.NODE_OPTIONS || '') + experimentalLoaderOption();
const innerProcess = require('child_process').fork(require.resolve('playwright-core/cli'), process.argv.slice(2), { const innerProcess = require('child_process').fork(require.resolve('playwright-core/cli'), process.argv.slice(2), {
env: { env: {
...process.env, ...process.env,
@ -259,4 +259,16 @@ function restartWithExperimentalTsEsm(configFile: string | null): boolean {
return true; return true;
} }
export function experimentalLoaderOption() {
return ` --experimental-loader=${url.pathToFileURL(require.resolve('@playwright/test/lib/experimentalLoader')).toString()}`;
}
export function envWithoutExperimentalLoaderOptions(): NodeJS.ProcessEnv {
const substring = experimentalLoaderOption();
const result = { ...process.env };
if (result.NODE_OPTIONS)
result.NODE_OPTIONS = result.NODE_OPTIONS.replace(substring, '').trim() || undefined;
return result;
}
const kTraceModes: TraceMode[] = ['on', 'off', 'on-first-retry', 'retain-on-failure']; const kTraceModes: TraceMode[] = ['on', 'off', 'on-first-retry', 'retain-on-failure'];

View file

@ -25,6 +25,7 @@ export { expect } from './expect';
export const _baseTest: TestType<{}, {}> = rootTestType.test; export const _baseTest: TestType<{}, {}> = rootTestType.test;
export { addRunnerPlugin as _addRunnerPlugin } from './plugins'; export { addRunnerPlugin as _addRunnerPlugin } from './plugins';
import * as outOfProcess from 'playwright-core/lib/outofprocess'; import * as outOfProcess from 'playwright-core/lib/outofprocess';
import * as playwrightLibrary from 'playwright-core';
import type { TestInfoImpl } from './testInfo'; import type { TestInfoImpl } from './testInfo';
if ((process as any)['__pw_initiator__']) { if ((process as any)['__pw_initiator__']) {
@ -61,7 +62,9 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
const impl = await outOfProcess.start({ const impl = await outOfProcess.start({
NODE_OPTIONS: undefined // Hide driver process while debugging. NODE_OPTIONS: undefined // Hide driver process while debugging.
}); });
await use(impl.playwright as any); const pw = impl.playwright as any;
pw._setSelectors(playwrightLibrary.selectors);
await use(pw);
await impl.stop(); await impl.stop();
} else { } else {
await use(require('playwright-core')); await use(require('playwright-core'));
@ -106,7 +109,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
(browserType as any)._defaultLaunchOptions = undefined; (browserType as any)._defaultLaunchOptions = undefined;
}, { scope: 'worker', auto: true }], }, { scope: 'worker', auto: true }],
_connectedBrowser: [async ({ playwright, browserName, channel, headless, connectOptions, launchOptions }, use) => { _connectedBrowser: [async ({ playwright, browserName, connectOptions, _browserOptions }, use) => {
if (!connectOptions) { if (!connectOptions) {
await use(undefined); await use(undefined);
return; return;
@ -116,7 +119,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
const browser = await playwright[browserName].connect(connectOptions.wsEndpoint, { const browser = await playwright[browserName].connect(connectOptions.wsEndpoint, {
headers: { headers: {
'x-playwright-browser': browserName, 'x-playwright-browser': browserName,
'x-playwright-launch-options': JSON.stringify(launchOptions), 'x-playwright-launch-options': JSON.stringify(_browserOptions),
...connectOptions.headers, ...connectOptions.headers,
}, },
timeout: connectOptions.timeout ?? 3 * 60 * 1000, // 3 minutes timeout: connectOptions.timeout ?? 3 * 60 * 1000, // 3 minutes

View file

@ -110,10 +110,12 @@ export function createPlugin(
}; };
} }
const { build, preview } = require('vite'); const { build, preview } = require('vite');
if (sourcesDirty) { // Build config unconditionally, either build or build & preview will use it.
viteConfig.plugins = viteConfig.plugins || [ viteConfig.plugins = viteConfig.plugins || [
frameworkPluginFactory() frameworkPluginFactory()
]; ];
// But only add out own plugin when we actually build / transform.
if (sourcesDirty)
viteConfig.plugins.push(vitePlugin(registerSource, relativeTemplateDir, buildInfo, componentRegistry)); viteConfig.plugins.push(vitePlugin(registerSource, relativeTemplateDir, buildInfo, componentRegistry));
viteConfig.configFile = viteConfig.configFile || false; viteConfig.configFile = viteConfig.configFile || false;
viteConfig.define = viteConfig.define || {}; viteConfig.define = viteConfig.define || {};
@ -132,10 +134,13 @@ export function createPlugin(
}, },
sourcemap: true, sourcemap: true,
}; };
if (sourcesDirty)
await build(viteConfig); await build(viteConfig);
}
if (hasNewTests || hasNewComponents || sourcesDirty) if (hasNewTests || hasNewComponents || sourcesDirty)
await fs.promises.writeFile(buildInfoFile, JSON.stringify(buildInfo, undefined, 2)); await fs.promises.writeFile(buildInfoFile, JSON.stringify(buildInfo, undefined, 2));
const previewServer = await preview(viteConfig); const previewServer = await preview(viteConfig);
stoppableServer = stoppable(previewServer.httpServer, 0); stoppableServer = stoppable(previewServer.httpServer, 0);
const isAddressInfo = (x: any): x is AddressInfo => x?.address; const isAddressInfo = (x: any): x is AddressInfo => x?.address;

View file

@ -25,6 +25,7 @@ import { launchProcess } from 'playwright-core/lib/utils/processLauncher';
import type { FullConfig, Reporter } from '../../types/testReporter'; import type { FullConfig, Reporter } from '../../types/testReporter';
import type { TestRunnerPlugin } from '.'; import type { TestRunnerPlugin } from '.';
import type { FullConfigInternal } from '../types'; import type { FullConfigInternal } from '../types';
import { envWithoutExperimentalLoaderOptions } from '../cli';
export type WebServerPluginOptions = { export type WebServerPluginOptions = {
@ -91,7 +92,7 @@ export class WebServerPlugin implements TestRunnerPlugin {
command: this._options.command, command: this._options.command,
env: { env: {
...DEFAULT_ENVIRONMENT_VARIABLES, ...DEFAULT_ENVIRONMENT_VARIABLES,
...process.env, ...envWithoutExperimentalLoaderOptions(),
...this._options.env, ...this._options.env,
}, },
cwd: this._options.cwd, cwd: this._options.cwd,
@ -99,7 +100,7 @@ export class WebServerPlugin implements TestRunnerPlugin {
shell: true, shell: true,
attemptToGracefullyClose: async () => {}, attemptToGracefullyClose: async () => {},
log: () => {}, log: () => {},
onExit: code => processExitedReject(new Error(`Process from config.webServer was not able to start. Exit code: ${code}`)), onExit: code => processExitedReject(new Error(code ? `Process from config.webServer was not able to start. Exit code: ${code}` : 'Process from config.webServer exited early.')),
tempDirectories: [], tempDirectories: [],
}); });
this._killProcess = kill; this._killProcess = kill;

View file

@ -143,9 +143,9 @@ export class BaseReporter implements ReporterInternal {
tokens.push(colors.red(formatTestHeader(this.config, test, ' '))); tokens.push(colors.red(formatTestHeader(this.config, test, ' ')));
} }
if (interrupted.length) { if (interrupted.length) {
tokens.push(colors.red(` ${interrupted.length} interrupted`)); tokens.push(colors.yellow(` ${interrupted.length} interrupted`));
for (const test of interrupted) for (const test of interrupted)
tokens.push(colors.red(formatTestHeader(this.config, test, ' '))); tokens.push(colors.yellow(formatTestHeader(this.config, test, ' ')));
} }
if (flaky.length) { if (flaky.length) {
tokens.push(colors.yellow(` ${flaky.length} flaky`)); tokens.push(colors.yellow(` ${flaky.length} flaky`));

View file

@ -950,7 +950,7 @@ function createDuplicateTitlesError(config: FullConfigInternal, rootSuite: Suite
for (const fullTitle of testsByFullTitle.keys()) { for (const fullTitle of testsByFullTitle.keys()) {
const tests = testsByFullTitle.get(fullTitle); const tests = testsByFullTitle.get(fullTitle);
if (tests.length > 1) { if (tests.length > 1) {
lines.push(` - title: ${fullTitle}`); lines.push(` - title: ${fullTitle.replace(/\u001e/g, ' ')}`);
for (const test of tests) for (const test of tests)
lines.push(` - ${buildItemLocation(config.rootDir, test)}`); lines.push(` - ${buildItemLocation(config.rootDir, test)}`);
} }

View file

@ -100,7 +100,7 @@ export function resolveHook(filename: string, specifier: string): string | undef
if (!isTypeScript) if (!isTypeScript)
return; return;
const tsconfig = loadAndValidateTsconfigForFile(filename); const tsconfig = loadAndValidateTsconfigForFile(filename);
if (tsconfig) { if (tsconfig && !isRelativeSpecifier(specifier)) {
let longestPrefixLength = -1; let longestPrefixLength = -1;
let pathMatchedByLongestPrefix: string | undefined; let pathMatchedByLongestPrefix: string | undefined;
@ -258,3 +258,7 @@ export function belongsToNodeModules(file: string) {
return true; return true;
return false; return false;
} }
function isRelativeSpecifier(specifier: string) {
return specifier === '.' || specifier === '..' || specifier.startsWith('./') || specifier.startsWith('../');
}

View file

@ -2509,6 +2509,20 @@ export interface TestType<TestArgs extends KeyValue, WorkerArgs extends KeyValue
* }); * });
* ``` * ```
* *
* The method returns value retuned by the step callback.
*
* ```js
* import { test, expect } from '@playwright/test';
*
* test('test', async ({ page }) => {
* const user = await test.step('Log in', async () => {
* // ...
* return 'john';
* });
* expect(user).toBe('john');
* });
* ```
*
* @param title Step name. * @param title Step name.
* @param body Step body. * @param body Step body.
*/ */

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright-webkit", "name": "playwright-webkit",
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate WebKit", "description": "A high-level API to automate WebKit",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -28,6 +28,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "playwright", "name": "playwright",
"version": "1.25.0-next", "version": "1.25.2",
"description": "A high-level API to automate web browsers", "description": "A high-level API to automate web browsers",
"repository": "github:Microsoft/playwright", "repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev", "homepage": "https://playwright.dev",
@ -28,6 +28,6 @@
"install": "node install.js" "install": "node install.js"
}, },
"dependencies": { "dependencies": {
"playwright-core": "1.25.0-next" "playwright-core": "1.25.2"
} }
} }

View file

@ -1,8 +0,0 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example

View file

@ -1 +0,0 @@
engine-strict=true

View file

@ -1,40 +0,0 @@
# create-svelte
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm init svelte@next
# create a new project in my-app
npm init svelte@next my-app
```
> Note: the `@next` is temporary
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.

View file

@ -1,3 +0,0 @@
{
"extends": "./.svelte-kit/tsconfig.json"
}

View file

@ -1,21 +0,0 @@
{
"name": "ct-svelte-kit",
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"package": "svelte-kit package",
"preview": "svelte-kit preview",
"prepare": "svelte-kit sync"
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"svelte": "^3.44.0"
},
"@standaloneDevDependencies": {
"@playwright/experimental-ct-svelte": "^1.22.2",
"@playwright/test": "^1.22.2"
},
"type": "module"
}

View file

@ -1,44 +0,0 @@
/**
* 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 type { PlaywrightTestConfig } from '@playwright/experimental-ct-svelte';
import { devices } from '@playwright/test';
const config: PlaywrightTestConfig = {
testDir: 'src',
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
reporter: 'html',
use: {
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
};
export default config;

View file

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Svelte Test</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/playwright/index.ts"></script>
</body>
</html>

View file

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="" />
<link rel="icon" href="%svelte.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%svelte.head%
</head>
<body>
<div>%svelte.body%</div>
</body>
</html>

View file

@ -1,49 +0,0 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* 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 { test, expect } from '@playwright/experimental-ct-svelte';
import Counter from './Counter.svelte';
test.use({ viewport: { width: 500, height: 500 } });
test('should work', async ({ mount }) => {
const changes = [];
const component = await mount(Counter, {
props: {
units: 's',
},
on: {
changed: c => changes.push(c)
}
});
const increment = component.locator('button[aria-label*=Increase]');
const decrement = component.locator('button[aria-label*=Decrease]');
await expect(component).toContainText('0s');
await increment.click();
await expect(component).toContainText('1s');
expect(changes).toEqual([{ count: 1 }]);
await increment.click();
await expect(component).toContainText('2s');
expect(changes).toEqual([{ count: 1 }, { count: 2 }]);
await decrement.click();
await expect(component).toContainText('1s');
expect(changes).toEqual([{ count: 1 }, { count: 2 }, { count: 1 }]);
});

View file

@ -1,113 +0,0 @@
<script>
import { spring } from 'svelte/motion';
import { createEventDispatcher } from 'svelte';
export let units = '';
let count = 0;
const dispatch = createEventDispatcher();
const increment = () => {
++count;
dispatch('changed', { count });
};
const decrement = () => {
--count;
dispatch('changed', { count });
};
const displayed_count = spring();
$: displayed_count.set(count);
$: offset = modulo($displayed_count, 1);
function modulo(n, m) {
// handle negative numbers
return ((n % m) + m) % m;
}
</script>
<div class="counter">
<button on:click={() => decrement()} aria-label="Decrease the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5" />
</svg>
</button>
<div class="counter-viewport">
<div class="counter-digits" style="transform: translate(0, {100 * offset}%)">
<strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}{units}</strong>
<strong>{Math.floor($displayed_count)}{units}</strong>
</div>
</div>
<button on:click={() => increment()} aria-label="Increase the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
</svg>
</button>
</div>
<style>
.counter {
display: flex;
border-top: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
margin: 1rem 0;
}
.counter button {
width: 2em;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border: 0;
background-color: transparent;
color: var(--text-color);
font-size: 2rem;
}
.counter button:hover {
background-color: var(--secondary-color);
}
svg {
width: 25%;
height: 25%;
}
path {
vector-effect: non-scaling-stroke;
stroke-width: 2px;
stroke: var(--text-color);
}
.counter-viewport {
width: 8em;
height: 4em;
overflow: hidden;
text-align: center;
position: relative;
}
.counter-viewport strong {
position: absolute;
display: flex;
width: 100%;
height: 100%;
font-weight: 400;
color: var(--accent-color);
font-size: 4rem;
align-items: center;
justify-content: center;
}
.counter-digits {
position: absolute;
width: 100%;
height: 100%;
}
.hidden {
top: -100%;
user-select: none;
}
</style>

View file

@ -1,2 +0,0 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,10 +0,0 @@
import adapter from '@sveltejs/adapter-auto';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
}
};
export default config;

View file

@ -54,12 +54,12 @@ const test = baseTest.extend<BrowserTestTestFixtures, BrowserTestWorkerFixtures>
}, { scope: 'worker' } ], }, { scope: 'worker' } ],
allowsThirdParty: [async ({ browserName, browserMajorVersion, channel }, run) => { allowsThirdParty: [async ({ browserName, browserMajorVersion, channel }, run) => {
if (browserName !== 'firefox') if (browserName === 'firefox' && !channel)
await run(browserMajorVersion >= 103);
else if (browserName === 'firefox' && channel === 'firefox-beta')
await run(browserMajorVersion >= 97 && browserMajorVersion < 103);
else
await run(false); await run(false);
else if (channel === 'firefox-beta' && (browserMajorVersion >= 97 && browserMajorVersion < 103))
await run(true);
else if (browserMajorVersion >= 103)
await run(true);
}, { scope: 'worker' } ], }, { scope: 'worker' } ],
defaultSameSiteCookieValue: [async ({ browserName, browserMajorVersion, channel }, run) => { defaultSameSiteCookieValue: [async ({ browserName, browserMajorVersion, channel }, run) => {

View file

@ -17,6 +17,7 @@
import { test } from '@playwright/test'; import { test } from '@playwright/test';
import type { TestModeName } from './testMode'; import type { TestModeName } from './testMode';
import { DefaultTestMode, DriverTestMode } from './testMode'; import { DefaultTestMode, DriverTestMode } from './testMode';
import * as playwrightLibrary from 'playwright-core';
export type TestModeWorkerOptions = { export type TestModeWorkerOptions = {
mode: TestModeName; mode: TestModeName;
@ -42,6 +43,7 @@ export const testModeTest = test.extend<TestModeTestFixtures, TestModeWorkerOpti
}[mode]; }[mode];
require('playwright-core/lib/utils').setUnderTest(); require('playwright-core/lib/utils').setUnderTest();
const playwright = await testMode.setup(); const playwright = await testMode.setup();
playwright._setSelectors(playwrightLibrary.selectors);
await run(playwright); await run(playwright);
await testMode.teardown(); await testMode.teardown();
}, { scope: 'worker' } ], }, { scope: 'worker' } ],

View file

@ -320,3 +320,32 @@ it('should add cookies with an expiration', async ({ context }) => {
expires: -42, expires: -42,
}])).rejects.toThrow(/Cookie should have a valid expires/); }])).rejects.toThrow(/Cookie should have a valid expires/);
}); });
it('should be able to send third party cookies via an iframe', async ({ browser, httpsServer, browserName, isMac }) => {
it.fixme(browserName === 'webkit' && isMac);
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/16937' });
const context = await browser.newContext({
ignoreHTTPSErrors: true,
});
try {
const page = await context.newPage();
await page.goto(httpsServer.EMPTY_PAGE);
await context.addCookies([{
domain: new URL(httpsServer.CROSS_PROCESS_PREFIX).hostname,
path: '/',
name: 'cookie1',
value: 'yes',
httpOnly: true,
secure: true,
sameSite: 'None'
}]);
const [response] = await Promise.all([
httpsServer.waitForRequest('/grid.html'),
page.setContent(`<iframe src="${httpsServer.CROSS_PROCESS_PREFIX}/grid.html"></iframe>`)
]);
expect(response.headers['cookie']).toBe('cookie1=yes');
} finally {
await context.close();
}
});

View file

@ -260,6 +260,50 @@ test.describe('cli codegen', () => {
expect(message.text()).toBe('John'); expect(message.text()).toBe('John');
}); });
test('should fill japanese text', async ({ page, openRecorder }) => {
const recorder = await openRecorder();
// In Japanese, "てすと" or "テスト" means "test".
await recorder.setContentAndWait(`<input id="input" name="name" oninput="input.value === 'てすと' && console.log(input.value)"></input>`);
const selector = await recorder.focusElement('input');
expect(selector).toBe('input[name="name"]');
async function inputText(text: string) {
await recorder.page.dispatchEvent(selector, 'keydown', { key: 'Process' });
await recorder.page.keyboard.insertText(text);
await recorder.page.dispatchEvent(selector, 'keyup', { key: 'Process' });
}
const [message, sources] = await Promise.all([
page.waitForEvent('console', msg => msg.type() !== 'error'),
recorder.waitForOutput('JavaScript', 'fill'),
(async () => {
await inputText('て');
await inputText('す');
await inputText('と');
})()
]);
expect(sources.get('JavaScript').text).toContain(`
// Fill input[name="name"]
await page.locator('input[name="name"]').fill('てすと');`);
expect(sources.get('Java').text).toContain(`
// Fill input[name="name"]
page.locator("input[name=\\\"name\\\"]").fill("てすと");`);
expect(sources.get('Python').text).toContain(`
# Fill input[name="name"]
page.locator(\"input[name=\\\"name\\\"]\").fill(\"てすと\")`);
expect(sources.get('Python Async').text).toContain(`
# Fill input[name="name"]
await page.locator(\"input[name=\\\"name\\\"]\").fill(\"てすと\")`);
expect(sources.get('C#').text).toContain(`
// Fill input[name="name"]
await page.Locator(\"input[name=\\\"name\\\"]\").FillAsync(\"てすと\");`);
expect(message.text()).toBe('てすと');
});
test('should fill textarea', async ({ page, openRecorder }) => { test('should fill textarea', async ({ page, openRecorder }) => {
const recorder = await openRecorder(); const recorder = await openRecorder();

View file

@ -17,7 +17,6 @@
import { browserTest as it, expect } from '../config/browserTest'; import { browserTest as it, expect } from '../config/browserTest';
it('should work', async ({ playwright, browser }) => {
const createTagSelector = () => ({ const createTagSelector = () => ({
query(root, selector) { query(root, selector) {
return root.querySelector(selector); return root.querySelector(selector);
@ -26,6 +25,8 @@ it('should work', async ({ playwright, browser }) => {
return Array.from(root.querySelectorAll(selector)); return Array.from(root.querySelectorAll(selector));
} }
}); });
it('should work', async ({ playwright, browser }) => {
// Register one engine before creating context. // Register one engine before creating context.
await playwright.selectors.register('tag', `(${createTagSelector.toString()})()`); await playwright.selectors.register('tag', `(${createTagSelector.toString()})()`);
@ -51,6 +52,27 @@ it('should work', async ({ playwright, browser }) => {
await context.close(); await context.close();
}); });
it('should work when registered on global', async ({ browser }) => {
await require('@playwright/test').selectors.register('oop-tag', `(${createTagSelector.toString()})()`);
const context = await browser.newContext();
// Register another engine after creating context.
await require('@playwright/test').selectors.register('oop-tag2', `(${createTagSelector.toString()})()`);
const page = await context.newPage();
await page.setContent('<div><span></span></div><div></div>');
expect(await page.$eval('oop-tag=DIV', e => e.nodeName)).toBe('DIV');
expect(await page.$eval('oop-tag=SPAN', e => e.nodeName)).toBe('SPAN');
expect(await page.$$eval('oop-tag=DIV', es => es.length)).toBe(2);
expect(await page.$eval('oop-tag2=DIV', e => e.nodeName)).toBe('DIV');
expect(await page.$eval('oop-tag2=SPAN', e => e.nodeName)).toBe('SPAN');
expect(await page.$$eval('oop-tag2=DIV', es => es.length)).toBe(2);
await context.close();
});
it('should work with path', async ({ playwright, browser, asset }) => { it('should work with path', async ({ playwright, browser, asset }) => {
const page = await browser.newPage(); const page = await browser.newPage();
await playwright.selectors.register('foo', { path: asset('sectionselectorengine.js') }); await playwright.selectors.register('foo', { path: asset('sectionselectorengine.js') });

View file

@ -411,3 +411,34 @@ test('should work with cross-imports - 2', async ({ runInlineTest }) => {
expect(result.output).toContain('TEST-1'); expect(result.output).toContain('TEST-1');
expect(result.output).toContain('TEST-2'); expect(result.output).toContain('TEST-2');
}); });
test('should load web server w/o esm loader in ems module', async ({ runInlineTest, nodeVersion }) => {
// We only support experimental esm mode on Node 16+
test.skip(nodeVersion.major < 16);
const result = await runInlineTest({
'playwright.config.ts': `
//@no-header
export default {
webServer: {
command: 'node ws.js',
port: 9876,
timeout: 100,
},
projects: [{name: 'foo'}]
}`,
'package.json': `{ "type": "module" }`,
'ws.js': `
//@no-header
console.log('NODE_OPTIONS ' + process.env.NODE_OPTIONS);
setTimeout(() => {}, 100000);
`,
'a.test.ts': `
const { test } = pwt;
test('passes', () => {});
`
}, {}, { ...process.env, DEBUG: 'pw:webserver' });
expect(result.exitCode).toBe(1);
expect(result.passed).toBe(0);
expect(result.output).toContain('NODE_OPTIONS undefined');
});

View file

@ -267,3 +267,30 @@ test('should cache build', async ({ runInlineTest }, testInfo) => {
expect(output, 'should rebuild bundle').toContain('modules transformed'); expect(output, 'should rebuild bundle').toContain('modules transformed');
}); });
}); });
test('should not use global config for preview', async ({ runInlineTest }) => {
const result1 = await runInlineTest({
'playwright/index.html': `<script type="module" src="/playwright/index.js"></script>`,
'playwright/index.js': ``,
'vite.config.js': `
export default {
plugins: [{
configurePreviewServer: () => {
throw new Error('Original preview throws');
}
}]
};
`,
'a.test.ts': `
//@no-header
import { test, expect } from '@playwright/experimental-ct-react';
test('pass', async ({ mount }) => {});
`,
}, { workers: 1 });
expect(result1.exitCode).toBe(0);
expect(result1.passed).toBe(1);
const result2 = await runInlineTest({}, { workers: 1 });
expect(result2.exitCode).toBe(0);
expect(result2.passed).toBe(1);
});

View file

@ -298,8 +298,8 @@ test('should not use baseurl for relative imports', async ({ runInlineTest }) =>
}); });
test('should not use baseurl for relative imports when dir with same name exists', async ({ runInlineTest }) => { test('should not use baseurl for relative imports when dir with same name exists', async ({ runInlineTest }) => {
test.fail();
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/15891' }); test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/15891' });
const result = await runInlineTest({ const result = await runInlineTest({
'frontend/tsconfig.json': `{ 'frontend/tsconfig.json': `{
"compilerOptions": { "compilerOptions": {
@ -309,15 +309,31 @@ test('should not use baseurl for relative imports when dir with same name exists
'frontend/src/utils/foo.js': ` 'frontend/src/utils/foo.js': `
export const foo = -1; export const foo = -1;
`, `,
'frontend/src/index.js': `
export const index = -1;
`,
'frontend/src/.bar.js': `
export const bar = 42;
`,
'frontend/playwright/tests/utils.ts': ` 'frontend/playwright/tests/utils.ts': `
export const foo = 42; export const foo = 42;
`, `,
'frontend/playwright/tests/index.js': `
export const index = 42;
`,
'frontend/playwright/tests/forms_cms_standard.spec.ts': ` 'frontend/playwright/tests/forms_cms_standard.spec.ts': `
// This relative import should not use baseUrl // These relative imports should not use baseUrl
import { foo } from './utils'; import { foo } from './utils';
import { index } from '.';
// This absolute import should use baseUrl
import { bar } from '.bar';
const { test } = pwt; const { test } = pwt;
test('test', ({}, testInfo) => { test('test', ({}, testInfo) => {
expect(foo).toBe(42); expect(foo).toBe(42);
expect(index).toBe(42);
expect(bar).toBe(42);
}); });
`, `,
}); });
@ -325,4 +341,5 @@ test('should not use baseurl for relative imports when dir with same name exists
expect(result.exitCode).toBe(0); expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1); expect(result.passed).toBe(1);
expect(result.output).not.toContain(`Could not`); expect(result.output).not.toContain(`Could not`);
expect(result.output).not.toContain(`Cannot`);
}); });

View file

@ -20,15 +20,19 @@ test('it should not allow multiple tests with the same name per suite', async ({
const result = await runInlineTest({ const result = await runInlineTest({
'tests/example.spec.js': ` 'tests/example.spec.js': `
const { test } = pwt; const { test } = pwt;
test.describe('suite', () => {
test('i-am-a-duplicate', async () => {}); test('i-am-a-duplicate', async () => {});
});
test.describe('suite', () => {
test('i-am-a-duplicate', async () => {}); test('i-am-a-duplicate', async () => {});
});
` `
}); });
expect(result.exitCode).toBe(1); expect(result.exitCode).toBe(1);
expect(result.output).toContain('duplicate test titles are not allowed'); expect(result.output).toContain('duplicate test titles are not allowed');
expect(result.output).toContain(`- title: i-am-a-duplicate`); expect(result.output).toContain(`- title: suite i-am-a-duplicate`);
expect(result.output).toContain(` - tests${path.sep}example.spec.js:6`);
expect(result.output).toContain(` - tests${path.sep}example.spec.js:7`); expect(result.output).toContain(` - tests${path.sep}example.spec.js:7`);
expect(result.output).toContain(` - tests${path.sep}example.spec.js:10`);
}); });
test('it should not allow multiple tests with the same name in multiple files', async ({ runInlineTest }) => { test('it should not allow multiple tests with the same name in multiple files', async ({ runInlineTest }) => {