Previously, any unpaired quote in the text selector "escaped"
everything till the end of the selector string, and so any
subsequent chained selectors, including ">>" separator were ignored.
An example of misbehaving selector: `text=19" >> nth=1`.
Now, when text selector contains a non-leading quote, selector parser
does not assume it should escape ">>" separator and correctly
tokenizes all selectors from the chain.
Note that this behavior is a workaround for the fact that our
text selectors is somewhat poorly defined in this area. That said,
this workaround seems to be safe enough. It still does not work for
unpaired leading quotes like this: `text="19 >> nth=1`.
This has two values:
- `"hide"` to hide input caret for taking screenshot
- `"initial"` to keep caret behavior unchanged
Defaults to `"hide"`.
Fixes#12643
This introduces `role=button[name="Click me"][pressed]` attribute-style
role selector. It is only available under `env.PLAYWRIGHT_EXPERIMENTAL_FEATURES`.
Supported attributes:
- `role` is required, for example `role=button`;
- `name` is accessible name, supports matching operators and regular expressions:
`role=button[name=/Click(me)?/]`;
- `checked` boolean/mixed, for example `role=checkbox[checked=false]`;
- `selected` boolean, for example `role=option[selected]`;
- `expanded` boolean, for example `role=button[expanded=true]`;
- `disabled` boolean, for example `role=button[disabled]`;
- `level` number, for example `role=heading[level=3]`;
- `pressed` boolean/mixed, for example `role=button[pressed="mixed"]`;
- `includeHidden` - by default, only non-hidden elements are considered.
Passing `role=button[includeHidden]` matches hidden elements as well.
This patch prints a friendly instructions in case Docker image version
mismatches Playwright version and there are missing browser
dependencies.
With this patch, Playwright will yield the following error:
```
root@f0774d2b2097:~# node a.mjs
node:internal/process/promises:279
triggerUncaughtException(err, true /* fromPromise */);
^
browserType.launch:
╔════════════════════════════════════════════════════════════════════════════════════════════╗
║ Host system is missing dependencies to run browsers. ║
║ This is most likely due to docker image version not matching Playwright version: ║
║ - Playwright: 1.22.0 ║
║ - Docker: 1.21.0 ║
║ ║
║ Either: ║
║ - (recommended) use docker image "mcr.microsoft.com/playwright:v1.22.0-focal" ║
║ - (alternative 1) run the following command inside docker to install missing dependencies: ║
║ ║
║ npx playwright install-deps ║
║ ║
║ - (alternative 2) use Aptitude inside docker: ║
║ ║
║ apt-get install libgbm1 ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════════════════════════════════════╝
at file:///root/a.mjs:3:10 {
name: 'Error'
}```
Fixes#12796
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
This patch:
- Adds 3 new host platform types:
* `generic-linux` and `generic-linux-arm64` for the unsupported
linux distributions
* `<unknown>` for non-supported OS versions
- Prints a warning when downloading Ubuntu browser builds on
unsupported Linux distribution
- Makes sure launch doctor prints all missing shared libraries
on unknown Linux distributions
- Also prints an `apt` command as an alternative to Playwright CLI
dependency installation.
Supports inline regex in addition to string: `_react=BookItem[author = /Ann?a/i]`.
This is similar to `text=` selector, but applies to `_react` and `_vue`
selectors. In the future, will also apply to `role=` selector.
Previously, we preserved input/textarea values by providing
`value` attribute or text child. This produces DOM that does not
actually match the original page.
This change starts using special attributes to modify values
directly when rendering.
Same treatment is also applied to options in `select` and
`checked` property of checkboxes and radio buttons.
This patch aligns the strategies that are used to generate new
screnshot expectations and to compare screenshot expectations against
baseline.
With this patch, `toHaveScreenshot` will:
- when generating a new expectation: will wait for 2 consecutive
screenshots to match and accept the last one as expectation.
- when given an expectation:
* will compare first screenshot against expectation. If matches,
resolve successfully
* if first screenshot doesn't match, then wait for 2 consecutive
screenshots to match and then compare last screenshot with the
expectation.
An example of a new detailed call log:
```
1) a.spec.ts:3:1 › should work ===================================================================
Error: Screenshot comparison failed:
20000 pixels (ratio 0.03 of all image pixels) are different
Call log:
- expect.toHaveScreenshot with timeout 5000ms
- verifying given screenshot expectation
- fast-path: checking first screenshot to match expectation
- taking page screenshot
- disabled all CSS animations
- waiting for fonts to load...
- fonts in all frames are loaded
- fast-path failed: first screenshot did not match expectation - 20000 pixels (ratio 0.03 of all image pixels) are different
- waiting for 2 consecutive screenshots to match
- waiting 100ms before taking screenshot
- taking page screenshot
- disabled all CSS animations
- waiting for fonts to load...
- fonts in all frames are loaded
- 2 consecutive screenshots matched
- final screenshot did not match expectation - 20000 pixels (ratio 0.03 of all image pixels) are different
- 20000 pixels (ratio 0.03 of all image pixels) are different
Expected: /Users/andreylushnikov/tmp/test-results/a-should-work/should-work-1-expected.png
Received: /Users/andreylushnikov/tmp/test-results/a-should-work/should-work-1-actual.png
Diff: /Users/andreylushnikov/tmp/test-results/a-should-work/should-work-1-diff.png
3 | test('should work', async ({ page }) => {
4 | await page.goto('file:///Users/andreylushnikov/prog/playwright/tests/assets/rotate-z.html');
> 5 | await expect(page).toHaveScreenshot();
| ^
6 | });
7 |
```
Turns out relying on PWTRAP in stack is not reliable: depending on the
call structure, the stack might be cut unpredictably by Node.js.
This patch removes PWTRAP and instead plumbs explicit stack and
pre-set `apiName` all the way down to `wrapApiCall`.
This patch:
- adds call logs to track screenshot timeouts, e.g. due to
waiting for web fonts
- makes sure all snapshot expectations have `.png` extension
- throws a polite error when given a buffer or a string instead of a
page or a locator
- removes stray NL between error description and call log
- makes sure `apiName` is always correct (and adds a test for it)
* Revert "fix(hooks): separate test timeout from beforeAll/afterAll timeouts (#12413)"
This reverts commit 73dee69558.
* Revert "fix(test-runner): rely on test title paths instead of ordinal (#12414)"
This reverts commit d744a87aee.
* Revert "chore(test runner): run hooks/modifiers as a part of the test (#12329)"
This reverts commit 47045ba48d.
It's a straightforward change to support new, common, keyboard commands
Note that I've tested this locally with Chrome on my Mac but it seems that CI doesn't want to pass Chrome tests - it's running on ubuntu though. Does this mean that I should introduce per-platform editing commands? At the moment there is only a single [`macEditingCommands`](0ed33522c5/packages/playwright-core/src/server/macEditingCommands.ts) file.
References https://github.com/microsoft/playwright/issues/12000
Co-authored-by: Andrey Lushnikov <aslushnikov@gmail.com>
This uses `Module._resolveFilename` to intercept module resolution and
check `tsconfig.paths` similarly to pirates usage ot `Module._compile`.
Previously, we resolved during compilation that required reproducible
resolution due to caching. Now we can resolve as we go and support
all `tsconfig.paths`.
This reverts commit e5c9d1e39f.
Reason for revert: turns out this fix results in a 5-second delay
when starting tests in docker, with `test-results` folder being
a non-removable mount.
The reason for the delay is the `maxBusyTries` option that we
supply by default to rimraf when trying to remove the folder.
While this option might come handy when removing temporary
browser profile folder, it doesn't serve us well in this particular
usecase.
References #12106
In experimental ESM mode a child process is forked in order to run the tests. Currently the exit code of this child process is not propagated to the exit code of the parent process, which means that the process exits with a status code of `0` even if some of the tests failed.
This makes it difficult to use Playwright in CI in experimental mode, as the CI pipeline as a whole will pass despite the test failures.
This change addresses this by propagating the exit code in the case where it is non-zero.
This changes PlaywrigtServer to serve connections like `ws://localhost:3333/?browser=chromium`:
- launches the browser;
- talks `browserType.connect`-style protocol over websocket;
- compatible with `connectOptions` fixture.
```js
await playwright.chromium.connect({ wsEndpoint: 'ws://localhost:3333/?browser=chrome' });
```
This option stops all kinds of CSS animations while doing screenshot:
- CSS animations
- CSS transitions
- Web Animations
Animations get different treatment depending on animation duration:
- finite animations are fast-forwarded to its end, issuing the
`transitionend` event.
- Infinite animations are resetted to its beginning, and then
resumed after the screenshot.
References #9938, fixes#11912
This introduces `locator('div', { has: locator })` syntax that matches elements containing other elements.
Can be used together with `hasText`.
Internally, has selector engine takes an inner selector escaped with double-quotes:
`div >> has="li >> span >> text=Foo" >> span`.
When element that is being dragged stays under the mouse,
it prevents the hit target check on drop from working,
because drop target is overlayed by the dragged element.
To workaround this, we perform a one-time hit target check
before moving for the drop, as we used to.
These variables aren't CLI-only anymore, so pick some more general
names for them.
Note: all language ports would need to follow-up with the rename
after the next roll.
Fixes#11450
This reworks DeadlineRunner to use exception to signal timeout. This way,
we'll be able to run fixtures against a shared deadline vs their own
deadline and still get an easy control-flow timeout handling.
In several of the Playwright APIs, falsey values were not handled correctly. This changeset adds tests (and some fixes):
- route.continue: If options.postData was the empty string, the continue failed to override the post data.
- page.post (application/json with options.data: false|''|0|null): Raw falsey values were getting dropped (i.e. you can't do the equivalent of curl --header application/json … -d 'false'). This has been fixed with most values across all browsers, but an additional fix is needed for 'null' which the channel serializer treats extra specially.
- testInfo.attach: This didn't get reported as an error when options.path was the empty string, but should have been.
#11413 (and its fix#11414) inspired this search as they are the same
class of bug.
- Use file path, not content to calculate the attachment hash.
- Always cleanup fixture from the list on teardown, to avoid reporting
teardown error multiple times: from the test, and from the cleanup.
We do not have a timeout for any other close method, such as
browserContext.close or browser.close, and hitting default
30 seconds is very realistic with large Electron apps.
In case of self-hosted github runners, it's much easier to checkout
under `playwright-internal` folder name instead of a default
`playwright` name. This confuses our stack collection.
This patch makes it generic.
This changes previous layout shift attempt (see #9546)
to account for more valid usecases:
- On the first event that is intercepted we enforce the hit target. This
is similar to the current mode that checks hit target before the action,
but is better timed.
- On subsequent events we assume that everything is fine. This covers more
scenarios like react rerender, glass pane on mousedown, detach on mouseup.
This check is enabled by default, with `process.env.PLAYWRIGHT_NO_LAYOUT_SHIFT_CHECK`
to opt out.
## Before
* When docker wasn't running: crashed with a TypeError
* When any image without `RepoTags` was present: crashed with TypeError
* Typo in recommended command ("playwight")
* No indication of `PW_TEST_IMAGE` env var in error output
<details>
<summary>Docker not running</summary>
```
Using config at ~redacted/playwright.config.ts
ERROR get /images/json 500 dial unix docker.raw.sock: connect: connection refused
TypeError: Cannot read property 'find' of null
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:67:26)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:43:9)
at GridServer.createAgent (~redacted/node_modules/playwright-core/lib/grid/gridServer.js:356:5)
at launchDockerContainer (~redacted/node_modules/@playwright/test/lib/cli.js:259:3)
at Runner._run (~redacted/node_modules/@playwright/test/lib/runner.js:236:98)
Running 1 test using 1 worker
test.ts:9:1 › some redacted description
ERROR get /images/json 500 dial unix docker.raw.sock: connect: connection refused
TypeError: Cannot read property 'find' of null
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:67:26)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js
```
</details>
<details>
<summary>Image without repo tags</summary>
```
Using config at ~redacted/playwright.config.ts
TypeError: Cannot read property 'includes' of undefined
at ~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:67:55
at Array.find (<anonymous>)
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:67:26)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:43:9)
at GridServer.createAgent (~redacted/node_modules/playwright-core/lib/grid/gridServer.js:356:5)
at launchDockerContainer (~redacted/node_modules/@playwright/test/lib/cli.js:259:3)
at Runner._run (~redacted/node_modules/@playwright/test/lib/runner.js:236:98)
Running 1 test using 1 worker
some-test.ts › some description
TypeError: Cannot read property 'includes' of undefined
at ~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:67:55
at Array.find (<anonymous>)
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:67:26)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.j ✘ editor-editor-wysiwyg--editor-wysiwyg.vr.ts:9:1 › actual element matches expected element (26ms)
1) some-test.ts › some description =====
'Grid agent creation failed'
1 failed
some-test.ts › some description ======
```
</details>
## After
* Helpful error message if docker isn't running
* Doesn't crash when local-only images in list
* No typo in `playwright install docker-image` command
* When other playwright images are found they are listed and `PW_TEST_IMAGE` is mentioned
### After: Docker not running
```
Using config at ~redacted/playwright.config.ts
Error fetching json: Error: connect ECONNREFUSED /var/run/docker.sock
Error:
╔═════════════════════════════════════════╗
║ Failed to list docker images ║
║ Please ensure docker daemon is running. ║
║ ║
║ <3 Playwright Team ║
╚═════════════════════════════════════════╝
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:61:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:43:9)
at GridServer.createAgent (~redacted/node_modules/playwright-core/lib/grid/gridServer.js:356:5)
at launchDockerContainer (~redacted/node_modules/@playwright/test/lib/cli.js:259:3)
at Runner._run (~redacted/node_modules/@playwright/test/lib/runner.js:236:98)
Running 1 test using 1 worker
test.ts:9:1 › description
Error fetching json: Error: connect ECONNREFUSED /var/run/docker.sock
Error:
╔═════════════════════════════════════════╗
║ Failed to list docker images ║
║ Please ensure docker daemon is running. ║
║ ║
║ <3 Playwright Team ║
╚═════════════════════════════════════════╝
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:61:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.j ✘ test.ts:9:1 › description
1) test.ts:9:1 › description =====
'Grid agent creation failed'
1 failed
test.ts:9:1 › description ======
```
## After: No exact match found
```
Using config at ~redacted/playwright.config.ts
Error:
╔════════════════════════════════════════════════════════════════════════════╗
║ Failed to find mcr.microsoft.com/playwright:v1.16.3-focal docker image. ║
║ ║
║ Available images: ║
║ - mcr.microsoft.com/playwright:v1.16.3 ║
║ - mcr.microsoft.com/playwright:v1.16.2-focal ║
║ ║
║ Use available images via PWTEST_IMAGE_NAME environment variable: ║
║ PWTEST_IMAGE_NAME=mcr.microsoft.com/playwright:v1.16.3 playwright test ║
║ ║
║ Alternatively, please pull docker image with the following command: ║
║ ║
║ npx playwright install docker-image ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════════════════════╝
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:92:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:43:9)
at GridServer.createAgent (~redacted/node_modules/playwright-core/lib/grid/gridServer.js:356:5)
at launchDockerContainer (~redacted/node_modules/@playwright/test/lib/cli.js:259:3)
at Runner._run (~redacted/node_modules/@playwright/test/lib/runner.js:236:98)
Running 1 test using 1 worker
editor-editor-wysiwyg--editor-wysiwyg.vr.ts:9:1 › actual element matches expected element
Error:
╔════════════════════════════════════════════════════════════════════════════╗
║ Failed to find mcr.microsoft.com/playwright:v1.16.3-focal docker image. ║
║ ║
║ Available images: ║
║ - mcr.microsoft.com/playwright:v1.16.3 ║
║ - mcr.microsoft.com/playwright:v1.16.2-focal ║
║ ║
║ Use available images via PWTEST_IMAGE_NAME environment variable: ║
║ PWTEST_IMAGE_NAME=mcr.microsoft.com/playwright:v1.16.3 playwright test ║
║ ║
║ Alternatively, please pull docker image with the following command: ║
║ ║
║ npx playwright install docker-image ║
║ ║
║ <3 Playwright Team ║
╚════════════════════════════════════════════════════════════════════════════╝
at launchDockerGridAgent (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.js:92:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Object.launch (~redacted/node_modules/playwright-core/lib/grid/dockerGridFactory.j ✘ test.ts:9:1 › description
1) test.ts:9:1 › description =====
'Grid agent creation failed'
1 failed
test.ts:9:1 › description ======
```
When configuring a proxy, Chromium requires a magic tokens to get some
local network requests to go through the proxy. This has tripped up a
few users, so we make the behavior default to the expected: proxy
everything including the local requests. This matches the other vendors
as well.
NB: This can be disabled via
`PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK=1`
Supercedes: #8345Fixes: #10631