We populate `localStorage` using an init script. Currently, this script
isn't just run for the UI though, but also for all iframes. So we're
resetting `localStorage` every time the UI loads an iframe.
This hasn't been a problem in the past, because the only consumer of
`localStorage`, `Settings`, only read from `localStorage` once and kept
most state in `useState` afterwards. With
https://github.com/microsoft/playwright/pull/31911, this is no longer
true, so the bug starts biting us!
The fix is to ensure the init script isn't run on iframes.
Motivation: When using client-certificates on a website on port `443`,
we would normalise the user input with `new URL` but still generate a
"bad" representation of the "origin" internally, since the just do
concatenated "host:port".
(The origin doesn't contain the port in case of :443)
We use `clientCertificatesToTLSOptions` in two places:
a) for APIRequestContext, there we pass one from the URL constructor
over and
b) from the socks proxy, there we **now** also pass a "good one" over.
Test plan: We don't want to run the tests on port :443, so only manually
validated the fix.
Relates https://github.com/microsoft/playwright/issues/31906
This reverts commit 0aa2f06f68.
Discussed the new permission in the API review and decided not to
proceed with the feature as we are not ready to commit to supporting it
yet:
* the API is Chromium specific
* the API is still experimental
* there is no clarity to what extend the screen manipulation APIs will
work in old headless which is our main test environment
We'll keep an eye on the demand for the feature and may get back to
implementing it in the future.
Reference: https://github.com/microsoft/playwright/issues/27198
The following actions keep `noWaitAfter` option: `click`, `selectOption`
and `press`.
All other actions that used to have `noWaitAfter` now behave like it was
set to true, not waiting for follow-up navigations. In the docs, this
option is marked as completely ignored.
A small logic change was made to compensate for this behavior: when
waiting for the `hitTargetInterceptor`, we now race it against
navigations to avoid stalling when navigation stalls. Previously,
waiting for the interceptor was disabled when `noWaitAfter` was passed,
and since it's impossible to pass this option now, we mitigate by never
stalling instead.
Fixes#31469.
Retaining traces in the following scenarios:
- browser crash;
- manual `browser.close()`;
- implicit `browser.close()` from the `browser` fixture upon test end.
This does not affect the library, where `browser.close()` will not
retain the trace and will close the browser as fast as possible.
References #31541, #31535, #31537.
Redirects are always autoresumed, so the will always receive extra info
with raw headers. We only want to make raw headers available immediately
when there is a route.
Reference https://github.com/microsoft/playwright/issues/31351
* Revert harTracer change from
aeba083da0
to make sure that har.Entry._monotonicTime always represents request
start time. The issue from the corresponding report was due to HEAD and
GET request sent for the same URL, that use case is still addressed as
we match by url + method
* Adjust resources monotonic time as well when several contexts are
shown in the trace viewer.
Fixes https://github.com/microsoft/playwright/issues/31133
Fixes https://github.com/microsoft/playwright/issues/31355
All changes were done with the Android Studio upgrade assistant. It
updates it to the latest Gradle to make it compatible with recent Java
while keeping the `targetSdkVersion` unchanged.
**Investigation**
~~We use `nonStallingEvaluateInExistingContext` as of today, which does
`eval()` inside (from our utilityScript) which breaks for some sites. It
causes a hang, since the returned `Promise` of `eval()` hangs. We don't
know as of today why this happens. Without wrapping it ini `eval()` it
does not hang.~~
~~Workaround: Do a plain Runtime.evaluate instead.~~
workaround: Only wait on main frame.
Relates https://github.com/microsoft/playwright/issues/28995 (keeping it
open until they confirm that it helps)
When a signal arrives late enough, after the last action was committed
in 5 seconds, we should still account for it. This includes downloads,
popups and dialogs, but not navigations.
Exposed by a flaky test "should record open in a new tab with url".
This includes two major changes:
- reuse `SerializedFS` for live test runner tracing;
- merge scheduled `appendFile` operations into a single `fs` call.
In some cases, this improves performance of UI mode by 61% and
performance of `trace: on` mode by 38%. Note that performance
improvement on the average test will not be as noticeable.
References #30875, #30635.
Chromium's `DevTools listening on` message sometimes arrives before
Playwright is finished connecting to Node. Without this patch, it would
miss the message and fail to connect.
This is a follow up #29564
I did a deep dive on a redirect issue I observed in my infrastructure
and originally attributed to some configuration mistakes on my part.
I have code hosted on `example.com/code` and use subdomain proxying.
This leads to the uimode being exposed on
`example.com/code/proxy/{{port}}`.
Clicking on the open uimode link shown by vscode redirected with a 302
to `example.com/proxy/{{port}}`
The absolute redirect url overruled the relative path handling reverse
proxies rely on.
This PR turns the absolute into a relative url to avoid this issue.
Matching bu `apiName@wallTime` fails when two actions start at the same
time, e.g. two parallel api requests. Moreover, it results in trace
actions that have parent set to themselves, which in turn causes
infinite loop in the trace viewer. To avoid this problems we write
stepId explicitly to the library trace and use those step ids to find
corresponding test runner steps.
The stepId is passed via zone in case of expect, because the protocol
step is quite deep in the call chain after or explicitly in case of API
call steps created by the test runner instrumentation.
Similarly to page.close, we pass test-runner specific reason to
facilitate better error messages.
```
1) a.test.ts:10:11 › test
Error: apiRequestContext.fetch: Fixture { request } from beforeAll cannot be reused in a test.
- Recommended fix: use a separate { request } in the test.
- Alternatively, manually create APIRequestContext in beforeAll and dispose it in afterAll.
See https://playwright.dev/docs/api-testing#sending-api-requests-from-ui-tests for more details.
9 |
10 | test('test', async () => {
> 11 | await context.fetch('http://example.com');
| ^
12 | });
13 |
```
Closes#29260.
- Automatically waiting for the overlay locator to be hidden, with
`allowStayingVisible` opt-out.
- `times: 1` option.
- `removeLocatorHandler(locator, handler)` method.
- Passing `locator` as first argument to `handler`.
Fixes#30471. Fixes#30424. Fixes#29779.
There are new "non-manual" WPT accname tests that we now mostly pass,
which required a few tweeks in calculating role and name.
Also implemented accessible description computation, which is just a
small addition on top of accessible name, and passed respective wpt
tests.
References #18332.
According to the spec, such controls should use the native value as long
as they have "aria-label". The relevant spec section is 2D.
However, there is an open issue that claims this should always apply,
and all browsers and wpt test actually do that:
https://github.com/w3c/accname/issues/64.
Fixes#28848.
The accessible name computation spec has changed to explicitly mention
this case:
Step 2A. Hidden Not Referenced. If the current node is hidden and is:
- Not part of an aria-labelledby or aria-describedby traversal, where
the node directly referenced by that relation was hidden.
- Nor part of a native host language text alternative element (e.g.
label in HTML) or attribute traversal, where the root of that traversal
was hidden.
See https://w3c.github.io/accname/#computation-steps. Chromium, Firefox
and Safari all agree with the spec.
Fixes#29796.
When websocket disconnects during `browserType.connect()` call, the
error looks like this now:
```
browserType.connect: Custom error message received over WebSocket
```
Previously, it was a generic error:
```
browserType.connect: Target page, context or browser has been closed
```
Workers use page's session for `Fetch` domain and worker's session for
`Network` domain. Therefore, `CRNetworkManager` should keep track of the
right session for each domain separately.
This is covered by currently flaky tests:
- `should report and intercept network from nested worker`,
- `should intercept network activity from worker`,
- `should intercept network activity from worker 2`.
This helps in a case where navigating to an origin fails for some
reason, for example because a registered service worker loads some
content into the supposedly blank page.
Fixes#29402.
This covers blocked requests, e.g. mixed-content, that receive
`loadingFailed` with empty `errorText`.
Also, forcefully resolve `allHeaders()` in this case, since we know
there will be no actual network headers.
Fixes#29833.
This PR is a fix proposal for a bug when trying to record a omnibox
navigation after a recorded action (e.g., `fill`).
The following test, included in this PR, reproduces the problem:
```ts
test('should record omnibox navigations after recordAction', async ({ page, openRecorder, server }) => {
const recorder = await openRecorder();
await recorder.setContentAndWait(`<textarea></textarea>`);
await Promise.all([
recorder.waitForOutput('JavaScript', 'fill'),
page.locator('textarea').fill('Hello world'),
]);
// for performed actions, 5 seconds is the time needed to ensure they are committed
await page.waitForTimeout(5000);
await page.goto(server.PREFIX + `/empty.html`);
await recorder.waitForOutput('JavaScript', `await page.goto('${server.PREFIX}/empty.html');`);
});
```
After performed actions (e.g., `click`), it successfully records the
navigation as long as there's at least a 5 sec. gap between both
actions. That happens because after that 5 sec. interval the performed
action is automatically commited and therefore the navigation is not
stored as a signal of that action.
The proposed fix for recorded actions also forces that action to be
automatically commited after 5 sec (for testing, I'm using 500ms to
speed up the test execution).
It was already handling worker sessions, but not OOPIFs. As a result,
some functionality was properly implemented only for OOPIFs and not for
workers.
This change removes OOPIFs fanout for network-related calls from CRPage
and moves that to the CRNetworkManager, now also covering workers.
The metadata.error change was brought back in
https://github.com/microsoft/playwright/pull/29271and it broke java port
as we could have error and result set simulteniously. This PR moves the
logic to the trace recorder instead and keeps the protocol contract
clear that either error or result is present, but not both.
We stopped catching all exceptions in
https://github.com/microsoft/playwright/pull/28539 in hope that we'll
get loadingFailed even before Fetch.continue/fulfill command's error.
Turns out this is racy and may fail if the test cancels the request
while we are continuing it. The following test could in theory reproduce
it if stars align and the timing is good:
```js
it('page.continue on canceled request', async ({ page }) => {
let resolveRoute;
const routePromise = new Promise<Route>(f => resolveRoute = f);
await page.route('http://test.com/x', resolveRoute);
const evalPromise = page.evaluate(async () => {
const abortController = new AbortController();
(window as any).abortController = abortController;
return fetch('http://test.com/x', { signal: abortController.signal }).catch(e => 'cancelled');
});
const route = await routePromise;
void page.evaluate(() => (window as any).abortController.abort());
await new Promise(f => setTimeout(f, 10));
await route.continue();
const req = await evalPromise;
expect(req).toBe('cancelled');
});
```
Fixes https://github.com/microsoft/playwright/issues/29123
Motivation: On Windows we call around 50 times `PrintDeps.exe` which
takes on a very fast machine 500+ms. On Linux we do it around 120 times
(`ldd`) which takes around 150ms.
This change validates the dependencies once on browser install (`npx
playwright install`). In case its failing, it will emit a warning, in
case of a success, it will create a marker file that the binary has been
validated. For future `launch()` calls, we'll read this file and if
exists, we'll not validate again. Otherwise we'll validate again.
Note: If the marker file is older than 30 days, the browser will be
validated again.
This will now yield:
```
root@a85fb37f0c96:/work# npx playwright install
Failed to install browsers
Error: ERROR: Playwright does not support chromium on ubuntu18.04-x64
```
On Ubuntu 18.04.
Previously, new `Recorder` instance was given an existing
`InjectedScript`. However, we built a separate source for
`InjectedScript` vs `Recorder`, and both bundles contain their own copy
of all helper modules, e.g. `roleUtils`.
This resulted in two copies of helper modules, which is troublesome for
any module-level globals like a top-level cache. Depending on whether
`Recorder` or `InjectedScript` called into the helper, they would access
the different value of a module global, which lead to bugs.
To prevent this, we force any external dependencies to be imported
through the `InjectedScript.utils`.