With this patch:
- `npx playwright install-deps` will install deps on Ubuntu 21.04
- launch doctor knows the package<->lib mapping for Ubuntu 21.04
**NOTE:** our webkit build, however, doesn't work on Ubuntu 21.04. Since
this is not LTS release, we're doing best-effort here.
Fixes#6405
There are a few ways for `connect()` to finish:
- `Browser.close()` from the client side.
- Browser on the server side did exit (e.g. crashed).
- Connection was dropped by either of the sides.
We reduce all the cases to the last one by dropping the
connection when client wants calls `Browser.close()` or
server-side browser exits.
In all these cases we should properly cleanup on the server side,
and ensure that all promises reject on the client side.
We have `CRBrowserContext` that extends `BrowserContext`, and
it sometimes fails beacause `BrowserContext` is undefined, depending
on the require order. Below is the require cycle.
```log
server/browserContext.ts
server/supplements/recorderSupplement.ts
server/supplements/recorder/recorderApp.ts
server/playwright.ts
server/android/android.ts
server/chromium/crBrowser.ts
server/browserContext.ts
```
Fixing this by using `require`.
On a slow page that does a lot of things before navigating upon click,
it is common to move mouse away from the click point. Previously,
we would commit the click action and record a `page.goto()` for the
navigation. Now we attribute any signals, even after accidental mouse move,
to the previous action, in the 5-seconds time window.
This supports `PWDEBUG=console` that:
- runs headed;
- disables timeouts;
- adds `playwright` console helper.
When using `PWDEBUG=anything-but-console`, we open inspector.
Docs keep suggesting `PWDEBUG=1`.
This fixes the compatibility on Vercel with Next.js when it's used in
a serverless function.
Next.js uses https://github.com/vercel/nft to trace down the
dependencies which a serverless function is using which
is currently not capable of detecting the browsers.json in our current
setup. Previously we used require to load the browers.json which was
replaced by readFileSync in #5318. Since then it was broken.
Fixes#5862
We await the predicate now. For synchronous predicates,
nothing should change becase the await will finish before
the next protocol message arrives (thanks to `makeWaitForNextTask`).
Since check/uncheck does click under the hood, sometimes it might
need to click at a different position. One example would be a long
label that contains links inside, and clicking in the center happens
to hit the link instead of the label itself.
This changes the root object from RemoteBrowser to Playwright,
similar to local driver connection. This way, any remote connection
gets a Playwright object.
This also starts reusing PlaywrightServer class, and introduces
`cli run-server` hidden command that runs ws server on the
specified port.
Previous structure:
```
RemoteBrowser
- browser (using ConnectedBrowser for remote-specific behavior)
- selectors (special instance for this remote connection)
```
New structure:
```
Playwright
- ...
- selectors (special instance for this remote connection)
- preLaunchedBrowser (using ConnectedBrowser for remote-specific behavior)
```
This makes it much nicer to use `BrowserType` because it no longer has a template.
Technically a breaking change because of the rare edge case where someone used their own non-browser type inside the template, but I don't consider that intended behavior and think this is fine.
This roll required us pass a new flag - `--allow-pre-commit-input`. Otherwise, keyboard tests won't pass.
Co-authored-by: Joel Einbinder <joel.einbinder@gmail.com>
This patch adds support for `technology preview` webkit channel, which
we will keep close to the actual Safari Technology Preview releases.
This channel does not install by default. It is supposed to be installed
with the following CLI command:
```sh
$ npx playwright install webkit-technology-preview
```
Once the channel is installed, it can be used the following way:
```js
const browser = await playwright.webkit.launch({
channel: 'technology-preview',
});
```
**NOTE:** if clients attempt using the channel without installing it,
it'll throw an error with a copyable instructions to install via CLI.
References #5884
These methods are safe to call while the page is still open, or when it is
already closed. Works in remotely connected browser as well.
Also makes video.path() to throw for remotely connected browser.
Under the hood migrated Download and Video to use the common Artifact object.
There are two problems, exposed by existing tests:
- We do not send Page.startScreeencast before Runtime.runIfWaitingForDebugger
because we launch video recorder in between. This stalls when the page is busy
immediately after resuming, e.g. with alert().
Fixed by starting video recorder in advance.
- We wait for the first frame that may not come - for example, context-wide interception
is blocking essential resource and first frame.
Fixed by only waiting for the first frame before reporting the video, not the page.
For some reason typescript can't find electron types when using
nested tsconfig - workaround the bug.
Drive-by: surface installer compilation problems.
Browser registry is responsible for 3 things:
1. Remove downloaded browsers if there are no packages that refer to them
2. Install default browsers needed for the current package
3. Install browsers on-demand when used through Playwright CLI
Currently, registry relies on a single "download" field in `browsers.json`
to carry both (1) and (2). However, browsers in (3) are marked as
`download: false` so that they aren't installed automatically in (2), so
auto-remove procedure in (1) removes them on subsequent installation.
One possible approach to fix this would be modifying package's `browsers.json` to
change `download: false` to `true` when browsers are installed with
Playwright CLI. This approach was explored here:
bc04a51800
We decided against this since we have a history of issues related to
package modifications after NPM installation. This breaks all
sorts of yarn/npm caching mechanisms.
Instead, this patch is a two-step refactor:
- remove the "download" field in `browsers.json`. Now, all registries
(including old ones from previously-released versions) will retain any
browsers that are mentioned in the `browsers.json`.
- add a new flag "installByDefault", that is **only used** for default
installation.
With this change, the registry tasks are done like this:
- (1) auto-removal: if browser has a back reference, it is retained,
otherwise it is removed from registry
- (2) default installation: use only `installByDefault` to carry default installations
- (3) CLI installation: simply installs browsers. Since we retain
everythings that's referenced in (1), browsers aren't removed.
Fixes#5902
This patch rolls Firefox to r1237. Upstream firefox still struggles
with crashes with certain videos: https://bugzilla.mozilla.org/show_bug.cgi?id=1697004
This PR also workarounds this crash by disabling webrender.
References #5721
This change turns quoted match to be case-sensitive (as before),
but not strictly full-string for the whole element's text.
This is a fix for a case where element contains text nodes and child elements:
```html
<div>text1<span>child node</span>text2</div>
```
We now match this div by `text="text1"` and `text="text2"`.
Cookies have a "Secure" attribute which tells the browsers
that a given cookie should only be sent via HTTPS. In it's
absense "Secure" is falsy and these cookies should be sent
with both HTTP and HTTPS requests. Playwright now returns
only the "Non-Secure" cookies for HTTP URLs, and both
"Secure" and "Non-Secure" cookies for HTTPS URLs.
Fixes#5504
- List all actions we are interested in
- Fix timeline hover flicker
- Extract tabbed pane component
- Preview snapshots without clicking on the action
We might not ever get the "download finished" event when closing the context:
- in Chromium, for any ongoing download;
- in all browsers, for failed downloads.
This should not prevent closing the context. Instead of waiting for the
download and then deleting it, we force delete it immediately and reject
any promises waiting for the download completion.
We get relative registry path when PLAYWRIGHT_BROWSERS_PATH or HOME is relative.
In this case, it would be good to resolve to the same absolute path
during installation and execution, and we can usually do that using INIT_CWD.
- Introduce internal "out of process" start()/stop() mode.
- This mode is used both in regular tests and installation tests.
- Emulate basic driver installation, browser download and running.
- Remove label retargeting, as it does not play nicely with recorder.
- nth-match() is now correctly chained.
- Performance improvements around parent selectors and regex text matches.
- Do not check children when parent does not contain the text we look for.
- Minor caching improvements in evaluator.
This gives up to 5X performance boost on text-heavy pages.
- Snap to buttons, inputs, selects, etc.
- Try `<label>` selector in addition to the element.
- Use parent selectors when needed.
- Remove xpath fallback as it should be covered with css.
Consider the following situation (one among many possible).
- FrameA has an oopif child FrameB;
- FrameA navigates to same-process origin (e.g. about:blank);
- at the same time, FrameC is attached to the FrameB in the
FrameB's process.
In this case, we get `frameNavigated` event for FrameA, immediately
followed by `frameAttached` event for FrameC. Since we detach all
FrameA's child frames on navigation, including the oopif FrameB,
there is no parent frame for FrameC to attach to.
In general, multiple processes coming from oopif may send their
events in wildly different order, and their view about the frame
tree may not always correspond to the "up to date" frame tree as
seen from the main frame's process. We try to keep our frame tree
aligned with what main process thinks, and ignore events that
reference frames absent in this tree.
Drive-by: handle filechooser exceptions because of async processing.
This changes `text=` and `:text()` selectors to match the element when:
- it's combined text content matches the text;
- combined text content of any immediate child does not match the text.
This allows the following markup to match "Some bold and italics text":
`<div>Some <b>bold</b> and <i>italics</i> text</div>`.
For the reference, "combined text content" is almost equal to `element.textContent`,
but with some changes like using value of `<input type=button>` or ignoring `<head>`.
This also includes some caching optimizations, meaningful in complex matches
that involve multiple calls to the text engine.
Performance changes (measured on large page with ~25000 elements):
- `:has-text()` - 14% faster.
- `text=` - 50% faster.
- `:text()` - 0-35% slower.
- `:text-matches()` - 28% slower.
This makes dialogs disappear and prevents stalling.
Pros:
- No need to worry about dialogs for most users.
- Those that wait for a specific dialog still get to control it.
Cons:
- Those who use Playwright to show interactive browser will have
to add an empty 'dialog' handler to prevent auto-dismiss.
We do this in cli.
This patch starts downloading FFMPEG like we download our browsers
instead of bundling it in the NPM package.
With this patch, NPM size is reduced from 8.8MB to 1.7MB.
Consequences:
- `npx playwright` is drastically faster now
- playwright driver for language bindings is way smaller
- projects that bundle Playwright can pass Apple Notorization
Fixes#5193
- We don't need this, since it should propagate from the main frame.
- Forcing focus in oopif immediately focuses it and blurs currently
focused frame. This leads to undesired side effects, e.g. selects
being closed.
This switches vp8 to "realtime" mode that works fast, adapting to
the speed of incoming frames, and produces the best quality in can
given realtime constraints.
In practice, this gives 2x larger video files but no noticible quality
difference. It also eliminates huge delays for encoding the video.
Drive-by: document our ffmpeg option choices and add some links
to documentation for future use.
This fix restores the ability to display images in the Network Tab inside Trace Viewer. Previously data returned from the server was coming back as base64 encoded string, but now it is returned as a Buffer object. This required convertion to either base64 encoded string or utf8 encoded string on the frontend.
Co-authored-by: Dominik Deren <dominik.deren@live.com>
Everything but attributes in the light dom is manually compared during
DOM traversal, for example child nodes or scroll offset.
This way we get a bullet-proof solution that works with input values,
scroll offsets, shadow dom and anything else web comes up with.
We also restore scroll only on the document scrolling element, for
performance reasons. We should figure out the story around scrolling.
Changes stationary snapshots from ~0.5ms to ~2.5ms due to DOM traversal.
- Intercept CSSOM modifications and recalculate overridden css text.
- When css text does not change, use "backwards reference" similar
to node references.
- Set 'Cache-Control: no-cache' for resources that could be overridden.
- Switch from html to json ml format.
- Allow node reuse between snapshots with `[nSnapshotsBefore, nodeWithIndexM]`.
- Service worker now lazily serializes snapshot chunks into a single html.
This decreases total snapshot size on random scripts ~10x.
This also decreases snapshot collecting time on mostly static pages to ~0.3ms.
Unfortunate downside for now is that we have to intercept
`Element.prototype.attachShadow` to invalidate nodes. This
also temporary breaks scroll restoration. Needs more research.
- Move service worker under /snapshot/ instead of /.
- Fix stylesheet base uri bug, where we inherited the wrong base url.
- Introduce TraceServer and routes there, split the actual routes
between snapshot, ui and action previews.
This change is adding a new property on the BrowserContextOptions class called `_debugName`. This property allows defining a user-friendly name for the browser context, and currently it is being used in one place, the Trace Viewer. When user provides the new value in the following way:
```typescript
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext({ _traceDir: __dirname, _debugName: 'My custom testcase name' });
await context.close();
await browser.close();
})();
```
The `_debugName` will be saved in the `*.trace` file for this browser context, on the `context-created` event, under the key `debugName`.
Later, when such a trace is displayed using Trace Viewer, the `debugName` will be displayed in the dropdown in the top right part of the app instead of the actual trace filename.
Fixes#5157.
Installer has a code to download browsers from the old version of
playwright. This, however, is never needed, since installer only
installs browsers from its own version.
This introduces an http server that serves our frontend and our snapshots. There is more work to untangle the big server into a few modules.
This change allows us:
- Maybe eventually serve the trace viewer as a web page.
- Rely on browser caches for fast snapshot rendering. This PR also adds "snapshot on hover" feature, subject to change.
feat(trace viewer): Extending existing NetworkTab view
Currently the network tab contains a limited amount of information on the resources that were loaded in the browser. This change proposes extending the details displayed for each resource, to include:
- HTTP method,
- Full url,
- Easily visible response content type,
- Request headers,
- Request & response bodies.
Such level of information could help quickly understand what happened in the application, when it was communicating with backend services. This can help debug tests quicker to figure out why they are failing.
This implementation still needs some clean up & tests improvement, but I wanted to propose such changes and gather your feedback before going too far.
- Instead of capturing snapshots on demand, we now stream them
from each frame every 100ms.
- Certain actions can also force snapshots at particular moment using
"checkpoints".
- Trace viewer is able to show the page snapshot at a particular
timestamp, or using a "checkpoint" snapshot.
- Small optimization to not process stylesheets if CSSOM was not used.
There still is a lot of room for improvement.
When `page.reload()` is racing against the renderer-initiated
navigation, we might end up with `waitForNavigation()` being rejected
before the reload implementation is able to catch it.
To avoid that, carefully use Promise.all and await `waitForNavigation`
from the get go.
Same happens to `page.goForward()` and `page.goBack()`.