There are a few issues this covers:
- Some fixtures like `page` and `context` are not allowed in `beforeAll`
hooks, so using them in automatic fixture makes it throw.
- Running automatic fixture solely for `afterAll` is unexpected.
This currently happens when `afterAll` is run for cleanup after
fixture timeout/throw.
For built-in playwright fixture, we keep `'all-hooks-included'` auto mode.
Added a doc explaining the execution order.
References #14037.
We used to query and save all non-zero `scrollTop`/`scrollLeft` to restore the page perfectly. However, this became very slow with Chromium v100 regression (see issue).
This change only queries and stores `scrollTop`/`scrollLeft` for elements that are ancestors of the action target. The resulting snapshot does not perfectly recreate the original screen, but should be good enough to inspect the action.
fix(chromium): work around about:blank issue on Chromium
We don't receive the `loaderId` which translates to `newDocumentId`,
so we expect the same-document navigation. Instead, we can wait
for any new-document navigation as a workaround, only for `about:blank`.
This also reverts commit f0f65fa247.
This patch:
- adds a hard dependency from `experimental-ct-*` packages to the
same-version of `@playwright/test`
- aligns `experimental-ct-*` package versions with main package
version
- starts publishing experimental CT packages together with other
packages
We should not fast-return if someone tries to run
`npx playwright install-deps` on Debian.
Instead, we should warn users, fallback to Ubuntu 20.04 dependencies,
and proceed.
Note: all toHaveScreenshot tests still use `__screenshots__` directory
for their expectations. One more test was added to make sure that
by default, `toHaveScreenshot` uses old snapshots.
Currently, when I choose "Java" in the sources list and then
click on the page to generate the "click" action, sources reset
to "JavaScript". This is very inconvenient.
This changes the logic to only forcefully change files if either
old or new file is a user file, not a generated one.
Use cases considered:
- run `codegen`, click around, choose different language, click more;
- run script with inspector, pause, click "Record" and record an action;
- same as above, but then continue and see that user source is revealed.
This fixes a few issues:
- strict mode was producing false negatives if multiple query paths
lead to the same element being picked;
- in some cases the number of intermediate items in the list was
exponential and crashed quickly.
What changed:
- `visible` engine is a real engine now;
- `capture` selectors are transformed to `has=` selectors for
easier implementation;
- chained querying switched from a list to a set to avoid
exponential size.
This allows us to use the full retry logic of rimraf in the `onexit` handler.
Note this is already covered by failing on Windows test
`should remove temp dir on process.exit`.
We skip waiting for "visible" state that enforces non-zero size.
Other invisible conditions like "display:none" fail during the
actual "scrolling" step and will retry.
Prior to this change, we were pre-maturely stopping a worker (since it
was deemed redundant under a race condition), and then we immediately
created a new worker with the same hash to finish off the test run. The
worker creation is expensive, so this slowed down the overall test run
time.
See the following for logs of the old code illustrating the extra stops and starts: https://gist.github.com/rwoll/1c592ed9e8f9169274fa972674de6703
feat: support experimental doc entries
- Params/options/members are marked as experimental in the docs.
- `experimental.d.ts` is generated that contains all types and
includes experimental features.
- `experimental.d.ts` is references in our tests so that we
can test experimental features.
- `fonts` option is restored as experimental.
- Always show a fixture that was running during timeout.
- Give custom titles to built-in fixtures.
- Specify setup/teardown fixture phase in the message.
- Split connect vs launch browser fixtures for better naming.
Example timeout message:
```log
Timeout of 2000ms exceeded while running fixture "built-in playwright configuration" teardown.
```
Reason: turns out Debian Buster requires just one source list to
install `ttf-ubuntu-font-family` font.
All other dependencies are satisfied.
Fixes#13530
Firefox has a bug: calling `node.focus()` does make the node focused,
but some internal "current contenteditable node" is not changed.
Blurring the previous one and focusing the new one helps.
To make launch/connect not affect the test timeout:
- `browser` fixture is declared with `timeout: 0`.
- Default timeouts are set to 30sec for launch and 3min for connect.
This was introduced in #7500 to fight `ERROR: The process "4436" not found.`
messages when killing a process that did already exit.
Since then, we no longer inherit stdout/stderr, so the error message
should not appear anymore.
This is a speculative fix to leftover tmp directories.
When users issues SIGINT twice, we enter `gracefullyClose()`
twice, and shortcut the second time. It turns out, we do
not wait for directories removal.
Note: it is unknown how often we reach this codepath in practice.
Previously, we were guessing whether something is optional from the
comment (looking for stuff like "defaults to" or "optional").
To remove this error-prone technique, every optional property or
argument (but not option) is explicitly marked with "?".
As a result, fix documentation issues:
- Removed `TestStep.data` that is not a thing.
- Added `TestConfig.name` documentation.
- Refined a lot of optional types in the documentation.
- Aligned `test.fail()` and `test.slow()` docs with `test.skip()`.
- Strict set of docs vs types inconsistensies in the generator
A few changes:
- `Matchers<R, T>` now carries both return and argument type.
- Based on the argument type, we apply playwright-specific Page/Locator matchers.
- Return type is usually void, unless wrapped with `expect.resolves`,
`expect.rejects` or `expect.poll()`.
- To preserve compatibility with any extended types in the wild,
argument type is optional.
fix: wait for worker to be ready before initializing
The test dispatcher waits until a worker is ready before sending the
`init` message. This guarantees that the worker process is listening for the
message. Otherwise, the worker process might miss the `init` message and
the subsequent `run` message would crash the worker.
If you typo'd an `expect` property, you got a cryptic error message:
```
Uncaught TypeError: Cannot create proxy with a non-object as target or handler
```
Now we get this nice friendly message:
```
1) a.spec.ts:6:9 › explodes ======================================================================
Error: expect: Property 'toBeLessThen' not found.
Did you mean 'toBeLessThan'?
See https://playwright.dev/docs/test-assertions for available options and documentation.
5 | const { test } = pwt;
6 | test('explodes', () => {
> 7 | expect.soft(1).toBeLessThen();
| ^
8 | });
9 |
```
Fixes#13218
- This supports `role=button[name=Hello]` similarly to CSS selectors.
- Does not change `_react` or `_vue` behavior that insist on quoting the string.
- Uses CSS notion of "identifier" characters.
This patch will check if browser channel is already installed.
If it is, it'll abort installation with the following error:
```
aslushnikov:~/prog/playwright$ npx playwright install msedge
Failed to install browsers
Error:
╔═════════════════════════════════════════════════════════════════╗
║ ATTENTION: "msedge" is already installed on the system! ║
║ ║
║ "msedge" installation is not hermetic; installing newer version ║
║ requires *removal* of a current installation first. ║
║ ║
║ To *uninstall* current version and re-install latest "msedge": ║
║ ║
║ - Close all running instances of "msedge", if any ║
║ - Use "--force" to install browser: ║
║ ║
║ npx playwright install --force msedge ║
║ ║
║ <3 Playwright Team ║
╚═════════════════════════════════════════════════════════════════╝
```
To re-install browser channel, use `--force`.
Fixes https://github.com/microsoft/playwright/issues/13061
It turns out that "non stalling evaluate" can stall in Chromium
in some weird conditions, like `document.open` after some weird
`iframe.src` value.
We now only hide highlight in those frames where we did install
highlight in the first place.
- Added docs to `selectors.md`.
- `[pressed]` and `[checked]` do not match `"mixed"` states.
- Disallow `[name]` shorthand without a value.
- Renamed `includeHidden` to `include-hidden`.
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
Previously, we always formed groups consisting of a single test.
Now, we group tests that share `beforeAll`/`afterAll` hooks into
`config.workers` equally-sized groups.
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:
- starts using directory of `package.json` to resolve default
output directory path
- starts using either `package.json` directory or configuration
directory to resolve all relative paths
References #12970
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.
Resolves#11318.
* Adds `TestConfig.attachments` public API. (We opted to not implement an analog to the async `TestInfo.attach(…)` API.)
* Adds `TestConfig.attachments` to common reporters.
* Dogfoods some git and CI-info inference to generate useful atttachments
* Updates HTML Reporter to include a side bar to present a pre-defined set of attachments (a.k.a git/commit context sidebar)
Here's what it looks like:
<img width="1738" alt="Screen Shot 2022-03-21 at 3 23 28 PM" src="https://user-images.githubusercontent.com/11915034/159373291-8b937d30-fba3-472a-853a-766018f6b3e2.png">
See `tests/playwright-test/reporter-html.spec.ts` for an example of usage (for dogfood-ing only). In the future, if this becomes user-facing, there the Global Setup bit would likely become unnecessary (as would interaction with attachments array); there would likely just be a nice top-level config and/or CLI flag to enable collecting of info.
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 |
```
By default, fixtures share timeout with the test they are instantiated for.
However, for more heavy fixtures, especially worker-scoped ones, it makes
sense to have a separate timeout.
This introduces `{ timeout: number }` option to the list of fixture options
that opts the fixture into a dedicated timeout rather than sharing it
with the test.
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`.
Currently, running `npx playwright test` in a subfolder of your project
will result in a `test-results` folder created in your `cwd`.
This is unexpected; instead, we should always resolve all paths
against `rootDir` - directory that contains config.
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)
- Line reporter now shows stats in addition to the test name:
```log
[chromium] › page/page-click-react.spec.ts:108:1 › should not retarget when element changes on hover
23% [21/93] Passed: 17 Flaky: 0 Failed: 0 Skipped: 4 (7s)
```
- When connected to a TTY or with `env.PLAYWRIGHT_LIVE_TERMINAL`
set to anything but `'0'` or `'false'`, line reporter updates in place.
- When not connected to a TTY, line reporter prints an update
after each ~1% of tests done, so it never prints more than 100 lines.
- Updated tests to the golden style.
This patch adds support to multiple diffs. These are possible
due to soft assertions.
Drive-by: rename second screenshot in `toHaveScreenshot` failure when
re-generating expectations from "expected" to "previous".
This patch:
- Enables configuration of certain defaults for some options of `expect.toHaveScreenshot` method via `TestProject.expect.toHaveScreenshot` property
- Sets sensible defaults for these options:
* `fonts: "ready"`
* `animations: "disabled"`
* `size: "css"`
New default is based on the very (unscientific) output of repeated a few
times:
```
$ for i in `seq 5 13`; do time npm run ctest -- --reporter=line --workers=$i 'page/*' 'selector*' 'channels*' 'resource-timing*'; done
```
This patch reverts 2 commits that removed the feature from the method:
- "fix: explicitly ignore maxDiffPixels in toMatchSnapshot (#12570)"
commit b8af8458d6.
- "chore: remove `maxDiffPixels` from toMatchSnapshot (#12539)"
commit a3dff45974.
The `screenshotsDir` option controls the expectation storage
for `toHaveScreenshot()` function.
The new expectation management for screenshots has the following
key properties:
- All screenshots are stored in a single folder called `screenshotsDir`.
- Screenshot names **do not** respect `snapshotDir` and `snapshotSuffix`
configurations.
- `screenshotsDir` is configurable per project. This way a "smoke tests"
project can re-use screenshots from "all tests" project.
- Host platform is a top-level folder.
For example, given the following config:
```js
// playwright.config.ts
module.exports = {
projects: [
{ name: 'Mobile Safari' },
{ name: 'Desktop Chrome' },
],
};
```
And the following test structure:
```
smoke-tests/
└── basic.spec.ts
```
Will result in the following screenshots folder structure by default:
```
__screenshots__/
└── darwin/
├── Mobile Safari/
│ └── smoke-tests/
│ └── basic.spec.ts/
│ └── screenshot-expectation.png
└── Desktop Chrome/
└── smoke-tests/
└── basic.spec.ts/
└── screenshot-expectation.png
```
Previously, we used to skip all the tests from the same file when
any `beforeAll` fails in the file.
Now, we only skip the rest of the tests affected by this particular
`beforeAll` and continue with other tests in the new worker.
Reland: worker.stop() before worker.run() was hanging because
`_runFinished` promise was not initially resolved.
---
This moves `beforeAll`, `afterAll` and some modifiers from running
as a separate entity into running inside a test.
Pros:
- All errors are reported as test errors.
- All artifacts are collected as test artifacts.
- Reporters support this out of the box.
Details:
- Each test computes the necessary hooks to run and runs them.
- Teardown is usually performed during the test (on test failure or worker stop).
- `skipRemaining` is added to `DonePayload` to preserve the behavior
where `beforeAll` hook failure skips subsequent tests.
This behavior can now be improved to only target tests affected by this hook.
* 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>
chore(test runner): run hooks/modifiers as a part of the test
This moves `beforeAll`, `afterAll` and some modifiers from running
as a separate entity into running inside a test.
Pros:
- All errors are reported as test errors.
- All artifacts are collected as test artifacts.
- Reporters support this out of the box.
Details:
- Each test computes the necessary hooks to run and runs them.
- Teardown is usually performed during the test (on test failure or worker stop).
- `skipRemaining` is added to `DonePayload` to preserve the behavior
where `beforeAll` hook failure skips subsequent tests.
This behavior can now be improved to only target tests affected by this hook.
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`.
- `stdout.isTTY` controls whether list reporter updates lines or just adds them;
- `env.CI` is used in a few places to affect the defaults:
- whether to open interactive html;
- default reporter dot/line;
- default terminal reporter added to non-terminal reporters;
- `env.PWTEST_SKIP_TEST_OUTPUT` is removed;
- `env.PW_TEST_DEBUG_REPORTERS` is introduced specifically for tests.
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
This way we control the timeout error message from the runner,
so that later on we can differentiate between test timeout, fixture
timeout and hook timeout.
This patch prepares for the `toHaveScreenshot` implementation
by splitting common parts from `toMatchSnapshot`.
Drive-by: fix default extension generation from `.bin` to `.dat`
for unknown buffers.
This patch adds additional options to `toMatchSnapshot` method:
- `pixelCount` - acceptable number of pixels that differ to still
consider images equal. Unset by default.
- `pixelRatio` - acceptable ratio of all image pixels (from 0 to 1) that differ to still
consider images equal. Unset by default.
Fixes#12167, #10219
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' });
```