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
uses: actions/github-script@v4
with:
github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: |
const { data } = await github.git.getCommit({
owner: context.repo.owner,

View file

@ -78,9 +78,9 @@ jobs:
run: bash utils/build/deploy-trace-viewer.sh --canary
if: contains(github.ref, 'main')
env:
GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
- name: Deploy BETA
run: bash utils/build/deploy-trace-viewer.sh --beta
if: contains(github.ref, 'release')
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
run: bash utils/build/deploy-trace-viewer.sh --stable
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
uses: actions/github-script@v4
with:
github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: |
const response = await github.pulls.create({
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:
```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.
```bash csharp
# 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:
```bash csharp
# Install WebKit
pwsh bin\Debug\netX\playwright.ps1 install webkit
pwsh bin/Debug/netX/playwright.ps1 install webkit
```
See all supported browsers:
```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --help
pwsh bin/Debug/netX/playwright.ps1 install --help
```
## Install browsers via API
@ -236,17 +236,17 @@ mvn test
```bash tab=bash-bash lang=csharp
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
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
$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.
@ -405,17 +405,17 @@ mvn test
```
```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
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
$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:
@ -500,17 +500,17 @@ mvn test
```
```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
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
$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
@ -584,19 +584,19 @@ mvn test
```
```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
set PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST=203.0.113.3
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
$env:PLAYWRIGHT_DOWNLOAD_HOST="192.0.2.1"
$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
@ -638,17 +638,17 @@ mvn test
```
```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
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
$env:PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
pwsh bin\Debug\netX\playwright.ps1 install
pwsh bin/Debug/netX/playwright.ps1 install
```
## 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"
```
```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --with-deps
pwsh bin/Debug/netX/playwright.ps1 install --with-deps
```
1. **Run your tests**:
@ -176,7 +176,7 @@ steps:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v2
@ -194,7 +194,7 @@ steps:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
steps:
- uses: actions/checkout@v3
- name: Set up Python
@ -218,7 +218,7 @@ steps:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
@ -239,7 +239,7 @@ steps:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
steps:
- uses: actions/checkout@v3
- name: Setup dotnet
@ -264,7 +264,7 @@ steps:
name: 'Playwright Tests - ${{ matrix.project }} - Shard ${{ matrix.shardIndex }} of ${{ matrix.shardTotal }}'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
strategy:
fail-fast: false
matrix:
@ -297,7 +297,7 @@ Alternatively, you can use [Command line tools](./cli.md#install-system-dependen
pool:
vmImage: 'ubuntu-20.04'
container: mcr.microsoft.com/playwright:v1.25.0-focal
container: mcr.microsoft.com/playwright:v1.25.2-focal
steps:
...
@ -311,7 +311,7 @@ Running Playwright on CircleCI requires the following steps:
```yml
docker:
- image: mcr.microsoft.com/playwright:v1.25.0-focal
- image: mcr.microsoft.com/playwright:v1.25.2-focal
environment:
NODE_ENV: development # Needed if playwright is in `devDependencies`
```
@ -333,7 +333,7 @@ to run tests on Jenkins.
```groovy
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright:v1.25.0-focal' } }
agent { docker { image 'mcr.microsoft.com/playwright:v1.25.2-focal' } }
stages {
stage('e2e-tests') {
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)).
```yml
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
```
### GitLab CI
@ -364,7 +364,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright:v1.25.0-focal
image: mcr.microsoft.com/playwright:v1.25.2-focal
script:
...
```

View file

@ -23,7 +23,7 @@ playwright
```bash csharp
# Use the tools.
pwsh bin\Debug\netX\playwright.ps1 --help
pwsh bin/Debug/netX/playwright.ps1 --help
```
```json js
@ -56,7 +56,7 @@ playwright install
```bash csharp
# 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:
@ -78,7 +78,7 @@ playwright install webkit
```bash csharp
# Install WebKit
pwsh bin\Debug\netX\playwright.ps1 install webkit
pwsh bin/Debug/netX/playwright.ps1 install webkit
```
See all supported browsers:
@ -96,7 +96,7 @@ playwright install --help
```
```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --help
pwsh bin/Debug/netX/playwright.ps1 install --help
```
## Install system dependencies
@ -120,7 +120,7 @@ playwright install-deps
```bash csharp
# 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:
@ -138,7 +138,7 @@ playwright install-deps chromium
```
```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.
@ -156,7 +156,7 @@ playwright install --with-deps chromium
```
```bash csharp
pwsh bin\Debug\netX\playwright.ps1 install --with-deps chromium
pwsh bin/Debug/netX/playwright.ps1 install --with-deps chromium
```
## Generate code
@ -174,7 +174,7 @@ playwright codegen wikipedia.org
```
```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.
@ -204,7 +204,7 @@ playwright codegen --save-storage=auth.json
```
```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.
# auth.json will contain the storage state.
```
@ -231,8 +231,8 @@ playwright codegen --load-storage=auth.json my.web.app
```
```bash csharp
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 open --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.
```
@ -351,7 +351,7 @@ playwright open example.com
```bash csharp
# Open page in Chromium
pwsh bin\Debug\netX\playwright.ps1 open example.com
pwsh bin/Debug/netX/playwright.ps1 open example.com
```
```bash js
@ -371,7 +371,7 @@ playwright wk example.com
```bash csharp
# Open page in WebKit
pwsh bin\Debug\netX\playwright.ps1 wk example.com
pwsh bin/Debug/netX/playwright.ps1 wk example.com
```
### Emulate devices
@ -394,7 +394,7 @@ playwright open --device="iPhone 11" wikipedia.org
```bash csharp
# 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
@ -416,7 +416,7 @@ playwright open --viewport-size=800,600 --color-scheme=dark twitter.com
```bash csharp
# 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
@ -442,7 +442,7 @@ playwright open --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --l
```bash csharp
# Emulate timezone, language & location
# 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
@ -542,7 +542,7 @@ playwright screenshot \
```bash csharp
# 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" \
--color-scheme=dark \
--wait-for-timeout=3000 \
@ -566,7 +566,7 @@ playwright screenshot --full-page en.wikipedia.org wiki-full.png
```bash csharp
# 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
@ -590,5 +590,5 @@ playwright pdf https://en.wikipedia.org/wiki/PDF wiki.pdf
```bash csharp
# 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.
**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
```bash js
@ -30,7 +20,7 @@ playwright codegen playwright.dev
```
```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.
@ -55,7 +45,7 @@ playwright codegen --viewport-size=800,600 playwright.dev
```
```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
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" />
@ -102,7 +92,7 @@ playwright codegen --color-scheme=dark playwright.dev
```
```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" />
@ -124,7 +114,7 @@ playwright codegen --timezone="Europe/Rome" --geolocation="41.890221,12.492348"
```
```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" />
@ -148,7 +138,7 @@ playwright codegen --save-storage=auth.json
```
```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" />
@ -168,7 +158,7 @@ playwright codegen --load-storage=auth.json github.com/microsoft/playwright
```
```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" />
@ -188,7 +178,7 @@ playwright open --load-storage=auth.json github.com/microsoft/playwright
```
```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();
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
pwsh bin\Debug\netX\playwright.ps1 codegen wikipedia.org
pwsh bin/Debug/netX/playwright.ps1 codegen wikipedia.org
```
### Stepping through the Playwright script

View file

@ -14,19 +14,19 @@ This image is published on [Docker Hub].
### Pull the image
```bash js
docker pull mcr.microsoft.com/playwright:v1.25.0-focal
docker pull mcr.microsoft.com/playwright:v1.25.2-focal
```
```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
docker pull mcr.microsoft.com/playwright/dotnet:v1.25.0-focal
docker pull mcr.microsoft.com/playwright/dotnet:v1.25.2-focal
```
```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
@ -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.
```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
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
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
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
@ -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.
```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
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
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
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:

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)
- [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`:
```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
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;
[TestClass]
public class UnitTest1 : PageTest
{
[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)
- [Learn more about the NUnit and MSTest base classes](./test-runners.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)

View file

@ -62,13 +62,9 @@ tests-examples/
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
@ -82,7 +78,7 @@ See our doc on [Running Tests](./running-tests.md) to learn more about running t
## 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
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)
- [Run single tests, multiple tests, headed mode](./running-tests.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)
- [Run single tests, multiple tests, headed mode](./running-tests.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
dotnet build
# 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.
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
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.
<!-- TOC -->

View file

@ -719,7 +719,7 @@ playwright open --save-har=example.har --save-har-glob="**/api/**" https://examp
```bash csharp
# 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

View file

@ -4,6 +4,52 @@ title: "Release notes"
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
<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:
```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:
@ -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.
- You can now use Playwright to install stable version of Edge on Linux:
```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
- 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
Read more about [Trace Viewer](./trace-viewer).

View file

@ -4,6 +4,28 @@ title: "Release notes"
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
<div className="embed-youtube">

View file

@ -4,6 +4,53 @@ title: "Release notes"
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
<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 ⚠️

View file

@ -4,6 +4,25 @@ title: "Release notes"
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
<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
```bash tab=bash-bash
BROWSER=webkit dotnet test
```
```batch tab=bash-batch
set BROWSER=webkit
dotnet test
```
```powershell tab=bash-powershell
$env:BROWSER="webkit"
dotnet test
```bash
dotnet test -- Playwright.BrowserName=webkit
```
- 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
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 version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="browser" value="chromium" />
<Parameter name="headless" value="false" />
</TestRunParameters>
<Playwright>
<BrowserName>chromium</BrowserName>
</Playwright>
</RunSettings>
```
@ -93,4 +82,4 @@ Check out our [debugging guide](./debug.md) to learn more about the [Playwright
## What's Next
- [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
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
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
- [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
- [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
* since: v1.10
- returns: <[any]>
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
* since: v1.10
- `title` <[string]>

View file

@ -650,4 +650,5 @@ export default config;
## Third party reporter showcase
* [Allure](https://www.npmjs.com/package/allure-playwright)
* [Monocart](https://github.com/cenfun/monocart-reporter)
* [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
dotnet new nunit -n PlaywrightTests
cd PlaywrightTests
# Add the required reference
dotnet add package Microsoft.Playwright.NUnit
dotnet build
# 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:
@ -104,7 +106,8 @@ dotnet test --filter "Name~Slogan"
### 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.
@ -151,24 +154,18 @@ CLI. See the following example:
```xml
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="browser" value="chromium" />
<Parameter name="headless" value="false" />
<Parameter name="channel" value="msedge" />
</TestRunParameters>
<Playwright>
<BrowserName>chromium</BrowserName>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings>
```
```bash tab=bash-bash
dotnet test -- TestRunParameters.Parameter\(name=\"browser\", value=\"chromium\"\) TestRunParameters.Parameter\(name=\"headless\", value=\"false\"\) TestRunParameters.Parameter\(name=\"channel\", value=\"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\")
```bash
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Headless=false Playwright.LaunchOptions.Channel=msedge
```
### 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
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 version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- NUnit adapter -->
<NUnit>
<NumberOfTestWorkers>24</NumberOfTestWorkers>
</NUnit>
</RunSettings>
```
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>
<!-- General run configuration -->
<RunConfiguration>
<EnvironmentVariables>
<!-- For debugging selectors, it's recommend to set the following environment variable -->
<DEBUG>pw:api</DEBUG>
</EnvironmentVariables>
</RunConfiguration>
<!-- Playwright -->
<Playwright>
<BrowserName>chromium</BrowserName>
<ExpectTimeout>5000</ExpectTimeout>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings>
```
@ -224,11 +225,13 @@ Playwright provides base classes to write tests with MSTest via the [`Microsoft.
# Create a new project
dotnet new mstest -n PlaywrightTests
cd PlaywrightTests
# Add the required reference
dotnet add package Microsoft.Playwright.MSTest
dotnet build
# 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:
@ -304,7 +307,8 @@ dotnet test --filter "Name~Slogan"
### 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
dotnet test --settings:.runsettings -- MSTest.Parallelize.Workers=4
@ -357,24 +361,18 @@ CLI. See the following example:
```xml
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="browser" value="chromium" />
<Parameter name="headless" value="false" />
<Parameter name="channel" value="msedge" />
</TestRunParameters>
<Playwright>
<BrowserName>chromium</BrowserName>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings>
```
```bash tab=bash-bash
dotnet test -- TestRunParameters.Parameter\(name=\"browser\", value=\"chromium\"\) TestRunParameters.Parameter\(name=\"headless\", value=\"false\"\) TestRunParameters.Parameter\(name=\"channel\", value=\"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\")
```bash
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Headless=false Playwright.LaunchOptions.Channel=msedge
```
### Using Verbose API Logs
@ -383,32 +381,35 @@ When you have enabled the [verbose API log](./debug.md#verbose-api-logs), via th
### 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
<RunSettings>
<!-- MSTest adapter -->
<!-- MSTest adapter -->
<MSTest>
<Parallelize>
<Workers>4</Workers>
<Scope>ClassLevel</Scope>
</Parallelize>
</MSTest>
</RunSettings>
```
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>
<!-- General run configuration -->
<RunConfiguration>
<EnvironmentVariables>
<!-- For debugging selectors, it's recommend to set the following environment variable -->
<DEBUG>pw:api</DEBUG>
</EnvironmentVariables>
</RunConfiguration>
<!-- Playwright -->
<Playwright>
<BrowserName>chromium</BrowserName>
<ExpectTimeout>5000</ExpectTimeout>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</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:
```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
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' });
```
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:
- `'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.
- `'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.
@ -152,7 +153,7 @@ playwright show-trace trace.zip
```
```bash csharp
pwsh bin\Debug\netX\playwright.ps1 show-trace trace.zip
pwsh bin/Debug/netX/playwright.ps1 show-trace trace.zip
```
## Actions
@ -219,7 +220,7 @@ playwright show-trace https://example.com/trace.zip
```
```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)

View file

@ -58,6 +58,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest
{
[TestMethod]
@ -153,6 +154,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest
{
[TestMethod]
@ -213,6 +215,7 @@ using Microsoft.Playwright.MSTest;
namespace PlaywrightTests;
[TestClass]
public class UnitTest1 : PageTest
{
[TestMethod]
@ -237,4 +240,4 @@ public class UnitTest1 : PageTest
- [Run single tests, multiple tests, headed mode](./running-tests.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)
- [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)
- [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",
"version": "1.25.0-next",
"version": "1.25.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "playwright-internal",
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"workspaces": [
"packages/*"
@ -6431,11 +6431,11 @@
"version": "0.0.0"
},
"packages/playwright": {
"version": "1.25.0-next",
"version": "1.25.2",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
},
"bin": {
"playwright": "cli.js"
@ -6445,11 +6445,11 @@
}
},
"packages/playwright-chromium": {
"version": "1.25.0-next",
"version": "1.25.2",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
},
"bin": {
"playwright": "cli.js"
@ -6459,7 +6459,7 @@
}
},
"packages/playwright-core": {
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"bin": {
"playwright": "cli.js"
@ -6470,10 +6470,10 @@
},
"packages/playwright-ct-react": {
"name": "@playwright/experimental-ct-react",
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"dependencies": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"@vitejs/plugin-react": "^1.0.7",
"vite": "^2.9.5"
},
@ -6483,10 +6483,10 @@
},
"packages/playwright-ct-svelte": {
"name": "@playwright/experimental-ct-svelte",
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"dependencies": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"vite": "^3.0.0"
},
@ -6565,10 +6565,10 @@
},
"packages/playwright-ct-vue": {
"name": "@playwright/experimental-ct-vue",
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"dependencies": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"@vitejs/plugin-vue": "^2.3.1",
"vite": "^2.9.5"
},
@ -6616,10 +6616,10 @@
},
"packages/playwright-ct-vue2": {
"name": "@playwright/experimental-ct-vue2",
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"dependencies": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"vite": "^2.9.5",
"vite-plugin-vue2": "^2.0.1"
},
@ -6631,11 +6631,11 @@
}
},
"packages/playwright-firefox": {
"version": "1.25.0-next",
"version": "1.25.2",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
},
"bin": {
"playwright": "cli.js"
@ -6646,11 +6646,11 @@
},
"packages/playwright-test": {
"name": "@playwright/test",
"version": "1.25.0-next",
"version": "1.25.2",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "*",
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
},
"bin": {
"playwright": "cli.js"
@ -6660,11 +6660,11 @@
}
},
"packages/playwright-webkit": {
"version": "1.25.0-next",
"version": "1.25.2",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
},
"bin": {
"playwright": "cli.js"
@ -7478,7 +7478,7 @@
"@playwright/experimental-ct-react": {
"version": "file:packages/playwright-ct-react",
"requires": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"@vitejs/plugin-react": "^1.0.7",
"vite": "^2.9.5"
}
@ -7486,7 +7486,7 @@
"@playwright/experimental-ct-svelte": {
"version": "file:packages/playwright-ct-svelte",
"requires": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"svelte": "^3.49.0",
"vite": "^3.0.0"
@ -7522,7 +7522,7 @@
"@playwright/experimental-ct-vue": {
"version": "file:packages/playwright-ct-vue",
"requires": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"@vitejs/plugin-vue": "^2.3.1",
"vite": "^2.9.5"
},
@ -7561,7 +7561,7 @@
"@playwright/experimental-ct-vue2": {
"version": "file:packages/playwright-ct-vue2",
"requires": {
"@playwright/test": "1.25.0-next",
"@playwright/test": "1.25.2",
"vite": "^2.9.5",
"vite-plugin-vue2": "^2.0.1",
"vue": "^2.6.14"
@ -7571,7 +7571,7 @@
"version": "file:packages/playwright-test",
"requires": {
"@types/node": "*",
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
}
},
"@rollup/pluginutils": {
@ -10366,13 +10366,13 @@
"playwright": {
"version": "file:packages/playwright",
"requires": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
}
},
"playwright-chromium": {
"version": "file:packages/playwright-chromium",
"requires": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
}
},
"playwright-core": {
@ -10381,13 +10381,13 @@
"playwright-firefox": {
"version": "file:packages/playwright-firefox",
"requires": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
}
},
"playwright-webkit": {
"version": "file:packages/playwright-webkit",
"requires": {
"playwright-core": "1.25.0-next"
"playwright-core": "1.25.2"
}
},
"postcss": {

View file

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

View file

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

View file

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

View file

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

View file

@ -90,6 +90,51 @@ class ProtocolHandler {
constructor(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 }) {

View file

@ -100,6 +100,8 @@ export abstract class BrowserContext extends SdkObject {
setSelectors(selectors: Selectors) {
this._selectors = selectors;
for (const page of this.pages())
page.selectors = selectors;
}
selectors(): Selectors {
@ -157,12 +159,14 @@ export abstract class BrowserContext extends SdkObject {
return JSON.stringify(paramsCopy);
}
async resetForReuse(metadata: CallMetadata, params: channels.BrowserNewContextForReuseParams) {
async resetForReuse(metadata: CallMetadata, params: channels.BrowserNewContextForReuseParams | null) {
this.setDefaultNavigationTimeout(undefined);
this.setDefaultTimeout(undefined);
for (const key of paramsThatAllowContextReuse)
(this._options as any)[key] = params[key];
if (params) {
for (const key of paramsThatAllowContextReuse)
(this._options as any)[key] = params[key];
}
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> {
return newContextForReuse(this._object, this._scope, params, metadata);
return newContextForReuse(this._object, this._scope, params, null, metadata);
}
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> {
return newContextForReuse(this._object, this._scope, params, metadata);
return newContextForReuse(this._object, this._scope, params, this.selectors, metadata);
}
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);
if (needsReset) {
const oldContextDispatcher = existingDispatcher<BrowserContextDispatcher>(context);
@ -149,6 +149,8 @@ async function newContextForReuse(browser: Browser, scope: DispatcherScope, para
oldContextDispatcher._dispose();
await context.resetForReuse(metadata, params);
}
if (selectors)
context.setSelectors(selectors);
const contextDispatcher = new BrowserContextDispatcher(scope, context);
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');
if (args.find(arg => arg.startsWith('-juggler')))
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) {
const lines: string[] = [];
for (const [name, value] of Object.entries(firefoxUserPrefs))
@ -92,3 +92,9 @@ export class Firefox extends BrowserType {
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();
const navigationEvent: NavigationEvent = { url, name, newDocument: frame._currentDocument, isPublic: true };
frame.emit(Frame.Events.InternalNavigation, navigationEvent);
this._fireInternalFrameNavigation(frame, navigationEvent);
if (!initial) {
debugLogger.log('api', ` navigated to "${url}"`);
this._page.frameNavigatedToNewDocument(frame);
@ -254,7 +254,7 @@ export class FrameManager {
return;
frame._url = url;
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}"`);
}
@ -272,7 +272,7 @@ export class FrameManager {
isPublic: !(documentId && frame._redirectedNavigations.has(documentId)),
};
frame.setPendingDocument(undefined);
frame.emit(Frame.Events.InternalNavigation, navigationEvent);
this._fireInternalFrameNavigation(frame, navigationEvent);
}
frameDetached(frameId: string) {
@ -462,6 +462,12 @@ export class FrameManager {
if (ws)
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 {
@ -1708,8 +1714,8 @@ export class Frame extends SdkObject {
localStorage.clear();
// Clean Service Workers
const registrations = await navigator.serviceWorker.getRegistrations();
await Promise.all(registrations.map(r => r.unregister()));
const registrations = navigator.serviceWorker ? await navigator.serviceWorker.getRegistrations() : [];
await Promise.all(registrations.map(r => r.unregister())).catch(() => {});
// Clean IndexedDB
for (const db of await indexedDB.databases?.() || []) {
@ -1717,7 +1723,7 @@ export class Frame extends SdkObject {
if (db.name)
indexedDB.deleteDatabase(db.name!);
}
});
}).catch(() => {});
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "@playwright/test",
"version": "1.25.0-next",
"version": "1.25.2",
"description": "A high-level API to automate web browsers",
"repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev",
@ -34,6 +34,6 @@
"license": "Apache-2.0",
"dependencies": {
"@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;
if (!fileIsModule(configFile))
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), {
env: {
...process.env,
@ -259,4 +259,16 @@ function restartWithExperimentalTsEsm(configFile: string | null): boolean {
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'];

View file

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

View file

@ -110,32 +110,37 @@ export function createPlugin(
};
}
const { build, preview } = require('vite');
if (sourcesDirty) {
viteConfig.plugins = viteConfig.plugins || [
frameworkPluginFactory()
];
// Build config unconditionally, either build or build & preview will use it.
viteConfig.plugins = viteConfig.plugins || [
frameworkPluginFactory()
];
// But only add out own plugin when we actually build / transform.
if (sourcesDirty)
viteConfig.plugins.push(vitePlugin(registerSource, relativeTemplateDir, buildInfo, componentRegistry));
viteConfig.configFile = viteConfig.configFile || false;
viteConfig.define = viteConfig.define || {};
viteConfig.define.__VUE_PROD_DEVTOOLS__ = true;
viteConfig.css = viteConfig.css || {};
viteConfig.css.devSourcemap = true;
viteConfig.build = {
...viteConfig.build,
target: 'esnext',
minify: false,
rollupOptions: {
treeshake: false,
input: {
index: path.join(templateDir, 'index.html')
},
viteConfig.configFile = viteConfig.configFile || false;
viteConfig.define = viteConfig.define || {};
viteConfig.define.__VUE_PROD_DEVTOOLS__ = true;
viteConfig.css = viteConfig.css || {};
viteConfig.css.devSourcemap = true;
viteConfig.build = {
...viteConfig.build,
target: 'esnext',
minify: false,
rollupOptions: {
treeshake: false,
input: {
index: path.join(templateDir, 'index.html')
},
sourcemap: true,
};
},
sourcemap: true,
};
if (sourcesDirty)
await build(viteConfig);
}
if (hasNewTests || hasNewComponents || sourcesDirty)
await fs.promises.writeFile(buildInfoFile, JSON.stringify(buildInfo, undefined, 2));
const previewServer = await preview(viteConfig);
stoppableServer = stoppable(previewServer.httpServer, 0);
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 { TestRunnerPlugin } from '.';
import type { FullConfigInternal } from '../types';
import { envWithoutExperimentalLoaderOptions } from '../cli';
export type WebServerPluginOptions = {
@ -91,7 +92,7 @@ export class WebServerPlugin implements TestRunnerPlugin {
command: this._options.command,
env: {
...DEFAULT_ENVIRONMENT_VARIABLES,
...process.env,
...envWithoutExperimentalLoaderOptions(),
...this._options.env,
},
cwd: this._options.cwd,
@ -99,7 +100,7 @@ export class WebServerPlugin implements TestRunnerPlugin {
shell: true,
attemptToGracefullyClose: async () => {},
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: [],
});
this._killProcess = kill;

View file

@ -143,9 +143,9 @@ export class BaseReporter implements ReporterInternal {
tokens.push(colors.red(formatTestHeader(this.config, test, ' ')));
}
if (interrupted.length) {
tokens.push(colors.red(` ${interrupted.length} interrupted`));
tokens.push(colors.yellow(` ${interrupted.length} 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) {
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()) {
const tests = testsByFullTitle.get(fullTitle);
if (tests.length > 1) {
lines.push(` - title: ${fullTitle}`);
lines.push(` - title: ${fullTitle.replace(/\u001e/g, ' ')}`);
for (const test of tests)
lines.push(` - ${buildItemLocation(config.rootDir, test)}`);
}

View file

@ -100,7 +100,7 @@ export function resolveHook(filename: string, specifier: string): string | undef
if (!isTypeScript)
return;
const tsconfig = loadAndValidateTsconfigForFile(filename);
if (tsconfig) {
if (tsconfig && !isRelativeSpecifier(specifier)) {
let longestPrefixLength = -1;
let pathMatchedByLongestPrefix: string | undefined;
@ -258,3 +258,7 @@ export function belongsToNodeModules(file: string) {
return true;
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 body Step body.
*/

View file

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

View file

@ -1,6 +1,6 @@
{
"name": "playwright",
"version": "1.25.0-next",
"version": "1.25.2",
"description": "A high-level API to automate web browsers",
"repository": "github:Microsoft/playwright",
"homepage": "https://playwright.dev",
@ -28,6 +28,6 @@
"install": "node install.js"
},
"dependencies": {
"playwright-core": "1.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' } ],
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);
else if (channel === 'firefox-beta' && (browserMajorVersion >= 97 && browserMajorVersion < 103))
await run(true);
else if (browserMajorVersion >= 103)
await run(true);
}, { scope: 'worker' } ],
defaultSameSiteCookieValue: [async ({ browserName, browserMajorVersion, channel }, run) => {

View file

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

View file

@ -320,3 +320,32 @@ it('should add cookies with an expiration', async ({ context }) => {
expires: -42,
}])).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');
});
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 }) => {
const recorder = await openRecorder();

View file

@ -17,15 +17,16 @@
import { browserTest as it, expect } from '../config/browserTest';
const createTagSelector = () => ({
query(root, selector) {
return root.querySelector(selector);
},
queryAll(root, selector) {
return Array.from(root.querySelectorAll(selector));
}
});
it('should work', async ({ playwright, browser }) => {
const createTagSelector = () => ({
query(root, selector) {
return root.querySelector(selector);
},
queryAll(root, selector) {
return Array.from(root.querySelectorAll(selector));
}
});
// Register one engine before creating context.
await playwright.selectors.register('tag', `(${createTagSelector.toString()})()`);
@ -51,6 +52,27 @@ it('should work', async ({ playwright, browser }) => {
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 }) => {
const page = await browser.newPage();
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-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');
});
});
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.fail();
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/15891' });
const result = await runInlineTest({
'frontend/tsconfig.json': `{
"compilerOptions": {
@ -309,15 +309,31 @@ test('should not use baseurl for relative imports when dir with same name exists
'frontend/src/utils/foo.js': `
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': `
export const foo = 42;
`,
'frontend/playwright/tests/index.js': `
export const index = 42;
`,
'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 { index } from '.';
// This absolute import should use baseUrl
import { bar } from '.bar';
const { test } = pwt;
test('test', ({}, testInfo) => {
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.passed).toBe(1);
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({
'tests/example.spec.js': `
const { test } = pwt;
test('i-am-a-duplicate', async () => {});
test('i-am-a-duplicate', async () => {});
test.describe('suite', () => {
test('i-am-a-duplicate', async () => {});
});
test.describe('suite', () => {
test('i-am-a-duplicate', async () => {});
});
`
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain('duplicate test titles are not allowed');
expect(result.output).toContain(`- title: i-am-a-duplicate`);
expect(result.output).toContain(` - tests${path.sep}example.spec.js:6`);
expect(result.output).toContain(`- title: suite i-am-a-duplicate`);
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 }) => {