@e2e-dev/web 0.11.0-canary-20260929180659 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -12
- package/dist/.build.json +1 -1
- package/dist/browser-connection.d.ts.map +1 -1
- package/dist/browser-connection.js +12 -1
- package/dist/browser-connection.js.map +1 -1
- package/dist/{web.d.ts → browser.d.ts} +18 -9
- package/dist/browser.d.ts.map +1 -0
- package/dist/{web.js → browser.js} +23 -16
- package/dist/browser.js.map +1 -0
- package/dist/downloads.d.ts +29 -0
- package/dist/downloads.d.ts.map +1 -0
- package/dist/downloads.js +74 -0
- package/dist/downloads.js.map +1 -0
- package/dist/engine.d.ts +2 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +53 -17
- package/dist/engine.js.map +1 -1
- package/dist/in-page/read-semantics.d.ts.map +1 -1
- package/dist/in-page/read-semantics.js +101 -15
- package/dist/in-page/read-semantics.js.map +1 -1
- package/dist/index.d.ts +18 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/locators.d.ts.map +1 -1
- package/dist/locators.js +26 -7
- package/dist/locators.js.map +1 -1
- package/dist/protected-app.d.ts +5 -3
- package/dist/protected-app.d.ts.map +1 -1
- package/dist/protected-app.js +16 -2
- package/dist/protected-app.js.map +1 -1
- package/dist/provider.d.ts +74 -4
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +110 -14
- package/dist/provider.js.map +1 -1
- package/dist/surface.d.ts +17 -9
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +19 -5
- package/dist/surface.js.map +1 -1
- package/dist/video.d.ts +1 -1
- package/dist/video.js +1 -1
- package/package.json +10 -8
- package/dist/web.d.ts.map +0 -1
- package/dist/web.js.map +0 -1
package/README.md
CHANGED
|
@@ -25,16 +25,18 @@ import type { E2EConfig } from 'e2e';
|
|
|
25
25
|
import { web } from '@e2e-dev/web';
|
|
26
26
|
|
|
27
27
|
export default {
|
|
28
|
-
targets: [{ name: 'web', engine: web({ url: 'http://localhost:3000' }
|
|
28
|
+
targets: [{ name: 'web', engine: web(), app: { url: 'http://localhost:3000' } }],
|
|
29
29
|
} satisfies E2EConfig;
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
The
|
|
33
|
-
`app.open()` opens; required
|
|
34
|
-
runner starts before the run and stops after it,
|
|
35
|
-
default `url`), `environment`
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
The target declares the app; the engine only drives it. The target's `app`
|
|
33
|
+
takes `url` (the base URL `app.open()` opens; required on a `web()` target),
|
|
34
|
+
`command` (a process the runner starts before the run and stops after it,
|
|
35
|
+
with `readyUrl` to poll, default `url`), `environment` (`test`, `staging`,
|
|
36
|
+
`production`; inferred from the host), and `identity` (a stable cache and
|
|
37
|
+
session key when the origin is ephemeral). `web({ url })` and the other old
|
|
38
|
+
app options are `INVALID_CONFIG`. A target with `app.url` is a `browser`
|
|
39
|
+
target, so a test can `requires: ['browser']`. Browser options:
|
|
38
40
|
`browser` (`chromium`, `firefox`, `webkit`; default `chromium`; or a
|
|
39
41
|
`BrowserProvider` that leases hosted browsers, see below), `viewport`
|
|
40
42
|
(`{ width, height }`; default 1280x720), `testIdAttribute` (the attribute
|
|
@@ -100,10 +102,10 @@ engine: web({
|
|
|
100
102
|
});
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
## The `
|
|
105
|
+
## The `browser` fixture
|
|
104
106
|
|
|
105
|
-
The engine contributes `
|
|
106
|
-
downloads, keyboard and mouse, plus `expect(
|
|
107
|
+
The engine contributes `browser`: navigation, routes, cookies, dialogs, frames,
|
|
108
|
+
downloads, keyboard and mouse, plus `expect(browser).toHaveURL()` and
|
|
107
109
|
`toHaveTitle()` and `toHaveClass()`. Import `test` from this package to have it
|
|
108
110
|
typed; it is the same runtime `test` as `e2e`'s.
|
|
109
111
|
|
|
@@ -111,10 +113,10 @@ typed; it is the same runtime `test` as `e2e`'s.
|
|
|
111
113
|
import { test } from '@e2e-dev/web';
|
|
112
114
|
import { expect } from 'e2e';
|
|
113
115
|
|
|
114
|
-
test('signs in', async ({ app, screen,
|
|
116
|
+
test('signs in', async ({ app, screen, browser }) => {
|
|
115
117
|
await app.open('/login');
|
|
116
118
|
await screen.getByLabel('Email').fill('user@example.test');
|
|
117
|
-
await expect(
|
|
119
|
+
await expect(browser).toHaveURL('/dashboard');
|
|
118
120
|
});
|
|
119
121
|
```
|
|
120
122
|
|
package/dist/.build.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.11.
|
|
1
|
+
{"version":"0.11.1"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-connection.d.ts","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAA8B,MAAM,YAAY,CAAC;AAGlE,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-connection.d.ts","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAA8B,MAAM,YAAY,CAAC;AAGlE,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAc5D;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAA+B;IAE9C;;;;;;OAMG;IACG,OAAO,CACX,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAC/B,OAAO,CAAC,OAAO,CAAC,CAkBlB;IAED,6FAA6F;IACvF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ7B;CACF;AAED,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,QAAQ,CAI9D;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtF"}
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
/** Shares one browser process connection across a worker's attempts. */
|
|
2
2
|
import { chromium, firefox, selectors, webkit } from 'playwright';
|
|
3
3
|
import { SELECTOR_ENGINES } from './selector-engines.js';
|
|
4
|
+
/**
|
|
5
|
+
* Playwright's default SIGINT handler closes the browser and exits the
|
|
6
|
+
* process, and its SIGTERM handler closes the browser. A terminal Ctrl-C
|
|
7
|
+
* reaches the worker's whole process group, so they would end the test
|
|
8
|
+
* mid-step before the runner's interrupt reports it. The runner owns those
|
|
9
|
+
* interrupts; the browser runs in its own process group, so the signal never
|
|
10
|
+
* reaches it, and the engine's `dispose` closes it. SIGHUP stays Playwright's:
|
|
11
|
+
* the runner does not handle a hangup, and its handler is what closes the
|
|
12
|
+
* browser when the terminal goes away.
|
|
13
|
+
*/
|
|
14
|
+
const RUNNER_OWNS_SIGNALS = { handleSIGINT: false, handleSIGTERM: false };
|
|
4
15
|
/**
|
|
5
16
|
* Launching a browser process costs hundreds of milliseconds; per-attempt
|
|
6
17
|
* isolation lives in browser contexts, so every attempt a worker runs can
|
|
@@ -28,7 +39,7 @@ export class BrowserConnection {
|
|
|
28
39
|
this.pending = undefined;
|
|
29
40
|
}
|
|
30
41
|
await registerSelectorEngines();
|
|
31
|
-
const launching = connect !== undefined ? connect() : browserType(name).launch({ headless: !headed, timeout: timeoutMs });
|
|
42
|
+
const launching = connect !== undefined ? connect() : browserType(name).launch({ headless: !headed, timeout: timeoutMs, ...RUNNER_OWNS_SIGNALS });
|
|
32
43
|
this.pending = launching;
|
|
33
44
|
try {
|
|
34
45
|
return await launching;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-connection.js","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAGxE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIzD;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IACpB,OAAO,CAA+B;IAE9C;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CACX,IAAiB,EACjB,MAAe,EACf,SAAiB,EACjB,OAAgC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE;gBAAE,OAAO,OAAO,CAAC;YAC9D,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;gBAAE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACnF,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QAC3B,CAAC;QACD,MAAM,uBAAuB,EAAE,CAAC;QAChC,MAAM,SAAS,GACb,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-connection.js","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAGxE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIzD;;;;;;;;;GASG;AACH,MAAM,mBAAmB,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAW,CAAC;AAEnF;;;;;;GAMG;AACH,MAAM,OAAO,iBAAiB;IACpB,OAAO,CAA+B;IAE9C;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CACX,IAAiB,EACjB,MAAe,EACf,SAAiB,EACjB,OAAgC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE;gBAAE,OAAO,OAAO,CAAC;YAC9D,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;gBAAE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACnF,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QAC3B,CAAC;QACD,MAAM,uBAAuB,EAAE,CAAC;QAChC,MAAM,SAAS,GACb,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,mBAAmB,EAAE,CAAC,CAAC;QAClI,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;YACzD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,6FAA6F;IAC7F,KAAK,CAAC,OAAO;QACX,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,CAAC,MAAM,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;QACtD,CAAC;IACH,CAAC;CACF;AAED,yDAAyD;AACzD,MAAM,UAAU,WAAW,CAAC,IAAiB;IAC3C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACvC,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IACrC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB,EAAE,SAAiB;IAClE,MAAM,uBAAuB,EAAE,CAAC;IAChC,OAAO,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,mGAAmG;AACnG,IAAI,eAA0C,CAAC;AAE/C;;;;GAIG;AACH,SAAS,uBAAuB;IAC9B,6EAA6E;IAC7E,4EAA4E;IAC5E,yEAAyE;IACzE,eAAe,KAAK,OAAO,CAAC,GAAG,CAC7B,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CACxC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC,UAAU,MAAM,GAAG,CAAC,EAAmB,CAAC,CAC/E,CACF,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACxB,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `
|
|
2
|
+
* The `browser` fixture: the browser-shaped deterministic surface this engine
|
|
3
3
|
* contributes. It lives here, not in core, because the harness knows the
|
|
4
4
|
* engine contract and never a platform's fixture shape. Every async method
|
|
5
|
-
* runs as a harness-recorded `
|
|
5
|
+
* runs as a harness-recorded `browser.<method>` step; `expect(browser)` reaches the
|
|
6
6
|
* matchers attached through `context.expectable`.
|
|
7
7
|
*
|
|
8
8
|
* Layering rule: validation (`resolveUrl`, JSON checks, cookie URLs, the
|
|
@@ -80,9 +80,9 @@ export type Cookie = CookieFields & ({
|
|
|
80
80
|
domain: string;
|
|
81
81
|
path?: string;
|
|
82
82
|
});
|
|
83
|
-
export interface
|
|
83
|
+
export interface BrowserExpectation {
|
|
84
84
|
/** Inverts the matcher. */
|
|
85
|
-
readonly not:
|
|
85
|
+
readonly not: BrowserExpectation;
|
|
86
86
|
/** Waits for the current URL to match. */
|
|
87
87
|
toHaveURL(expected: string | RegExp, options?: {
|
|
88
88
|
timeout?: number;
|
|
@@ -97,7 +97,7 @@ export interface WebExpectation {
|
|
|
97
97
|
}): Promise<void>;
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
|
-
* The screen scope `
|
|
100
|
+
* The screen scope `browser.frameLocator` returns. Every `Screen` query answers
|
|
101
101
|
* from inside the frame, and because the frame's document is Playwright's,
|
|
102
102
|
* the web-only escape hatches follow it in: `locator` for a CSS or XPath
|
|
103
103
|
* selector on a control with no accessible name, `frameLocator` for a frame
|
|
@@ -109,7 +109,16 @@ export interface FrameScreen extends Screen {
|
|
|
109
109
|
/** Creates a screen query scope inside an iframe nested in this frame. */
|
|
110
110
|
frameLocator(selector: string): FrameScreen;
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
/**
|
|
113
|
+
* The browser the attempt drives, showing one active tab. Navigation, reads,
|
|
114
|
+
* `locator`, `frameLocator`, `evaluate`, `waitForResponse`, `waitForDownload`,
|
|
115
|
+
* the keyboard and mouse, `expect(browser)`, and `screen` act on the active
|
|
116
|
+
* tab; cookies, routes, and dialog handlers cover the whole browser, every
|
|
117
|
+
* tab included. A tab the app opens itself (a `target="_blank"` link,
|
|
118
|
+
* `window.open`) is not followed: the active tab stays the one the attempt
|
|
119
|
+
* opened.
|
|
120
|
+
*/
|
|
121
|
+
export interface Browser extends Expectable<BrowserExpectation> {
|
|
113
122
|
/** Navigates to an allowed URL. */
|
|
114
123
|
goto(url: string, options?: {
|
|
115
124
|
waitUntil?: 'load' | 'domcontentloaded' | 'networkidle';
|
|
@@ -186,6 +195,6 @@ export interface Web extends Expectable<WebExpectation> {
|
|
|
186
195
|
up(): Promise<void>;
|
|
187
196
|
};
|
|
188
197
|
}
|
|
189
|
-
/** Builds the `
|
|
190
|
-
export declare function
|
|
191
|
-
//# sourceMappingURL=
|
|
198
|
+
/** Builds the `browser` fixture for one attempt over the shared surface. */
|
|
199
|
+
export declare function createBrowserFixture(surface: PlaywrightSurface, context: EngineFixtureContext): Browser;
|
|
200
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `
|
|
2
|
+
* The `browser` fixture: the browser-shaped deterministic surface this engine
|
|
3
3
|
* contributes. It lives here, not in core, because the harness knows the
|
|
4
4
|
* engine contract and never a platform's fixture shape. Every async method
|
|
5
|
-
* runs as a harness-recorded `
|
|
5
|
+
* runs as a harness-recorded `browser.<method>` step; `expect(browser)` reaches the
|
|
6
6
|
* matchers attached through `context.expectable`.
|
|
7
7
|
*
|
|
8
8
|
* Layering rule: validation (`resolveUrl`, JSON checks, cookie URLs, the
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* says which URLs a test may open.
|
|
13
13
|
*/
|
|
14
14
|
import { Deadline, describePattern, EngineError, matchesText, pollCondition, TestError, toTextPattern, urlMatches, validateJsonValue, } from 'e2e/engine';
|
|
15
|
+
import { saveDownloadsTo, saveFromBrowser, saveLocally } from './downloads.js';
|
|
15
16
|
import { isTestErrorCode, message as causeMessage, translatePwError } from './support.js';
|
|
16
17
|
import { compileEvaluation } from './evaluation.js';
|
|
17
18
|
import { routePatternMatches, routePatternsEqual } from './route-pattern.js';
|
|
@@ -37,8 +38,8 @@ async function readResponseBody(response) {
|
|
|
37
38
|
return () => Promise.reject(error);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
/** Builds the `
|
|
41
|
-
export function
|
|
41
|
+
/** Builds the `browser` fixture for one attempt over the shared surface. */
|
|
42
|
+
export function createBrowserFixture(surface, context) {
|
|
42
43
|
const latch = surface.latch;
|
|
43
44
|
const routes = [];
|
|
44
45
|
/**
|
|
@@ -60,8 +61,8 @@ export function createWebFixture(surface, context) {
|
|
|
60
61
|
const deadlineFor = (timeout) => new Deadline(context.operation(timeout ?? context.timeouts.assertion).timeoutMs);
|
|
61
62
|
const currentUrl = () => surface.guard(context.operation(), 'url', async () => surface.requirePage().url());
|
|
62
63
|
const currentTitle = () => surface.guard(context.operation(), 'title', () => surface.requirePage().title());
|
|
63
|
-
const expectation =
|
|
64
|
-
const
|
|
64
|
+
const expectation = createBrowserExpectation({ currentUrl, currentTitle, baseHref, deadlineFor, context });
|
|
65
|
+
const browser = {
|
|
65
66
|
goto(url, options) {
|
|
66
67
|
const resolved = context.app.resolveUrl(url);
|
|
67
68
|
return navigation(options, async (operation) => {
|
|
@@ -83,10 +84,10 @@ export function createWebFixture(surface, context) {
|
|
|
83
84
|
}),
|
|
84
85
|
url: currentUrl,
|
|
85
86
|
title: currentTitle,
|
|
86
|
-
// The same poll as `expect(
|
|
87
|
+
// The same poll as `expect(browser).toHaveURL`, exposed as a wait.
|
|
87
88
|
waitForURL: (url, options) => expectation.toHaveURL(url, options),
|
|
88
|
-
locator: (selector) => context.locator({ kind: 'selector', selector: requireSelector('
|
|
89
|
-
frameLocator: (selector) => frameScreen(context, [requireSelector('
|
|
89
|
+
locator: (selector) => context.locator({ kind: 'selector', selector: requireSelector('browser.locator', selector) }),
|
|
90
|
+
frameLocator: (selector) => frameScreen(context, [requireSelector('browser.frameLocator', selector)]),
|
|
90
91
|
async evaluate(fn, arg) {
|
|
91
92
|
const source = typeof fn === 'string' ? fn : fn.toString();
|
|
92
93
|
validateJsonValue(arg, 'evaluate argument');
|
|
@@ -233,7 +234,7 @@ export function createWebFixture(surface, context) {
|
|
|
233
234
|
await surface.setViewport(size);
|
|
234
235
|
context.attachViewport({ width: size.width, height: size.height, scale: 1 });
|
|
235
236
|
}),
|
|
236
|
-
// Async so the harness records the registration as a `
|
|
237
|
+
// Async so the harness records the registration as a `browser.onDialog` step.
|
|
237
238
|
async onDialog(handler) {
|
|
238
239
|
const unsubscribe = surface.dialogs.add(handler);
|
|
239
240
|
return async () => unsubscribe();
|
|
@@ -243,6 +244,9 @@ export function createWebFixture(surface, context) {
|
|
|
243
244
|
let triggerFailure;
|
|
244
245
|
let awaiting;
|
|
245
246
|
return surface.guard(operation, 'download', async (currentOperation) => {
|
|
247
|
+
const remote = surface.remoteDownloads();
|
|
248
|
+
if (remote !== undefined)
|
|
249
|
+
await saveDownloadsTo(surface.requirePage(), remote.dir);
|
|
246
250
|
const waiter = surface.requirePage()
|
|
247
251
|
.waitForEvent('download', { timeout: currentOperation.timeoutMs });
|
|
248
252
|
// The trigger may fail before the waiter settles; absorb its later rejection.
|
|
@@ -260,7 +264,10 @@ export function createWebFixture(surface, context) {
|
|
|
260
264
|
awaiting = undefined;
|
|
261
265
|
const suggestedFilename = download.suggestedFilename();
|
|
262
266
|
const { relative, absolute } = surface.artifactPath('downloads', suggestedFilename, '');
|
|
263
|
-
|
|
267
|
+
if (remote === undefined)
|
|
268
|
+
await saveLocally(download, absolute, surface.unservedDownloads());
|
|
269
|
+
else
|
|
270
|
+
await saveFromBrowser(download, remote, absolute, currentOperation.signal);
|
|
264
271
|
context.attachArtifact('download', relative);
|
|
265
272
|
return { path: relative, suggestedFilename };
|
|
266
273
|
}, (cause, label) => {
|
|
@@ -294,7 +301,7 @@ export function createWebFixture(surface, context) {
|
|
|
294
301
|
toHaveClass: { kind: 'assertion', timeout: false, label: (_target, expected) => String(expected) },
|
|
295
302
|
get not() { return matchers; },
|
|
296
303
|
};
|
|
297
|
-
return context.fixture('
|
|
304
|
+
return context.fixture('browser', context.expectable(browser, () => context.fixture('expect', expectation, matchers)), {
|
|
298
305
|
goto: { ...navigationCall, label: (url) => url },
|
|
299
306
|
reload: navigationCall,
|
|
300
307
|
back: navigationCall,
|
|
@@ -315,8 +322,8 @@ export function createWebFixture(surface, context) {
|
|
|
315
322
|
mouse: { move: action, wheel: action, down: action, up: action },
|
|
316
323
|
});
|
|
317
324
|
}
|
|
318
|
-
/** `expect(
|
|
319
|
-
function
|
|
325
|
+
/** `expect(browser)` matchers: URL, title, and class polling against the assertion budget. */
|
|
326
|
+
function createBrowserExpectation(deps, negated = false) {
|
|
320
327
|
const poll = async (api, label, condition, observed, timeout) => {
|
|
321
328
|
await pollCondition({
|
|
322
329
|
deadline: deps.deadlineFor(timeout),
|
|
@@ -328,7 +335,7 @@ function createWebExpectation(deps, negated = false) {
|
|
|
328
335
|
};
|
|
329
336
|
return {
|
|
330
337
|
get not() {
|
|
331
|
-
return
|
|
338
|
+
return createBrowserExpectation(deps, !negated);
|
|
332
339
|
},
|
|
333
340
|
toHaveURL(expected, options) {
|
|
334
341
|
const label = typeof expected === 'string' ? expected : String(expected);
|
|
@@ -388,4 +395,4 @@ function frameScreen(context, frames) {
|
|
|
388
395
|
frameLocator: (selector) => frameScreen(context, [...frames, requireSelector('frameLocator', selector)]),
|
|
389
396
|
});
|
|
390
397
|
}
|
|
391
|
-
//# sourceMappingURL=
|
|
398
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downloads from a browser on another machine. Playwright asks a CDP-attached
|
|
3
|
+
* browser to save each file under a directory of the runner's, which a
|
|
4
|
+
* remote browser does not have, so the download is canceled. A provider
|
|
5
|
+
* that serves downloads names a directory on the browser's own disk; the
|
|
6
|
+
* browser saves there, and the provider reads each finished file back.
|
|
7
|
+
*/
|
|
8
|
+
import type { Download, Page } from 'playwright';
|
|
9
|
+
import type { LeaseDownloads } from './provider.ts';
|
|
10
|
+
/**
|
|
11
|
+
* Has the browser behind `page` save the downloads of the page's context
|
|
12
|
+
* under `dir` on its own disk, each file named by its download id, with the
|
|
13
|
+
* download events Playwright's waiter reads left on.
|
|
14
|
+
*/
|
|
15
|
+
export declare function saveDownloadsTo(page: Page, dir: string): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Copies a finished download off the browser's disk to `file` through the
|
|
18
|
+
* provider: it lies under `dir`, named by its download id, as
|
|
19
|
+
* `saveDownloadsTo` had the browser name it. A download that failed or was
|
|
20
|
+
* canceled fails with the browser's reason.
|
|
21
|
+
*/
|
|
22
|
+
export declare function saveFromBrowser(download: Download, downloads: LeaseDownloads, file: string, signal: AbortSignal): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Saves a download Playwright received for the runner to `file`. When the
|
|
25
|
+
* file may have stayed on another machine, `unserved` says why, and a failed
|
|
26
|
+
* save names it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function saveLocally(download: Download, file: string, unserved: string | undefined): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=downloads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloads.d.ts","sourceRoot":"","sources":["../src/downloads.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAuB,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAMpD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB5E;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrI;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/G"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downloads from a browser on another machine. Playwright asks a CDP-attached
|
|
3
|
+
* browser to save each file under a directory of the runner's, which a
|
|
4
|
+
* remote browser does not have, so the download is canceled. A provider
|
|
5
|
+
* that serves downloads names a directory on the browser's own disk; the
|
|
6
|
+
* browser saves there, and the provider reads each finished file back.
|
|
7
|
+
*/
|
|
8
|
+
import { writeFile } from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { EngineError } from 'e2e/engine';
|
|
11
|
+
import { invalidState, message } from './support.js';
|
|
12
|
+
/** One browser-level CDP session per connection: a download behavior lives as long as the session that set it. */
|
|
13
|
+
const browserSessions = new WeakMap();
|
|
14
|
+
/**
|
|
15
|
+
* Has the browser behind `page` save the downloads of the page's context
|
|
16
|
+
* under `dir` on its own disk, each file named by its download id, with the
|
|
17
|
+
* download events Playwright's waiter reads left on.
|
|
18
|
+
*/
|
|
19
|
+
export async function saveDownloadsTo(page, dir) {
|
|
20
|
+
const context = page.context();
|
|
21
|
+
const browser = context.browser();
|
|
22
|
+
if (browser === null)
|
|
23
|
+
throw invalidState('the page has no browser to set a download directory on');
|
|
24
|
+
const pageSession = await context.newCDPSession(page);
|
|
25
|
+
let browserContextId;
|
|
26
|
+
try {
|
|
27
|
+
({ targetInfo: { browserContextId } } = await pageSession.send('Target.getTargetInfo'));
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await pageSession.detach().catch(() => undefined);
|
|
31
|
+
}
|
|
32
|
+
let session = browserSessions.get(browser);
|
|
33
|
+
if (session === undefined) {
|
|
34
|
+
session = browser.newBrowserCDPSession();
|
|
35
|
+
browserSessions.set(browser, session);
|
|
36
|
+
session.catch(() => browserSessions.delete(browser));
|
|
37
|
+
}
|
|
38
|
+
await (await session).send('Browser.setDownloadBehavior', {
|
|
39
|
+
behavior: 'allowAndName',
|
|
40
|
+
downloadPath: dir,
|
|
41
|
+
eventsEnabled: true,
|
|
42
|
+
...(browserContextId === undefined ? {} : { browserContextId }),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Copies a finished download off the browser's disk to `file` through the
|
|
47
|
+
* provider: it lies under `dir`, named by its download id, as
|
|
48
|
+
* `saveDownloadsTo` had the browser name it. A download that failed or was
|
|
49
|
+
* canceled fails with the browser's reason.
|
|
50
|
+
*/
|
|
51
|
+
export async function saveFromBrowser(download, downloads, file, signal) {
|
|
52
|
+
const failure = await download.failure();
|
|
53
|
+
if (failure !== null)
|
|
54
|
+
throw new EngineError('ENGINE_FAILURE', `download failed: ${failure}`, { retryable: false });
|
|
55
|
+
// Playwright names its own record of the file by the same download id.
|
|
56
|
+
const saved = path.posix.join(downloads.dir, path.basename(await download.path()));
|
|
57
|
+
await writeFile(file, await downloads.read(saved, signal));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Saves a download Playwright received for the runner to `file`. When the
|
|
61
|
+
* file may have stayed on another machine, `unserved` says why, and a failed
|
|
62
|
+
* save names it.
|
|
63
|
+
*/
|
|
64
|
+
export async function saveLocally(download, file, unserved) {
|
|
65
|
+
try {
|
|
66
|
+
await download.saveAs(file);
|
|
67
|
+
}
|
|
68
|
+
catch (cause) {
|
|
69
|
+
if (unserved === undefined)
|
|
70
|
+
throw cause;
|
|
71
|
+
throw new EngineError('ENGINE_FAILURE', `download failed: ${message(cause)}; ${unserved}`, { retryable: false, cause });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=downloads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloads.js","sourceRoot":"","sources":["../src/downloads.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The Playwright engine for e2e: a browser body built with the
|
|
3
3
|
* public `defineEngine`, validated by the same rules and graded by the same
|
|
4
4
|
* capabilities as any other engine. Core imports nothing from here; this
|
|
5
|
-
* package imports the contract from `e2e/engine` and contributes the `
|
|
5
|
+
* package imports the contract from `e2e/engine` and contributes the `browser`
|
|
6
6
|
* fixture the way a device engine contributes `device`.
|
|
7
7
|
*/
|
|
8
8
|
import type { BrowserContext, Page } from 'playwright';
|
|
@@ -13,7 +13,7 @@ import { type WebOptions } from './surface.ts';
|
|
|
13
13
|
* that replaces the toolset wholesale (spec chapter 16) and drives the page with
|
|
14
14
|
* its own Playwright tooling. Both accessors read the current attempt: the
|
|
15
15
|
* context exists from `startAttempt`, the page from the first `app.open()` or
|
|
16
|
-
* `
|
|
16
|
+
* `browser.goto()`, and either throws `INVALID_STATE` before that. The harness
|
|
17
17
|
* remains the notary for what it witnesses; a caller here acts out of band.
|
|
18
18
|
*/
|
|
19
19
|
export interface PlaywrightLiveSurface {
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EASL,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AASlE;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,cAAc,CAAC;CACxC;AAED,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,qBAAqB,GAAG,SAAS,CAIjF;AAED,wBAAgB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,YAAY,CAsG1D"}
|
package/dist/engine.js
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
* The Playwright engine for e2e: a browser body built with the
|
|
3
3
|
* public `defineEngine`, validated by the same rules and graded by the same
|
|
4
4
|
* capabilities as any other engine. Core imports nothing from here; this
|
|
5
|
-
* package imports the contract from `e2e/engine` and contributes the `
|
|
5
|
+
* package imports the contract from `e2e/engine` and contributes the `browser`
|
|
6
6
|
* fixture the way a device engine contributes `device`.
|
|
7
7
|
*/
|
|
8
|
-
import { ConfigurationError, defineEngine, isSecret, LOCATOR_ACTION_KINDS, POINTER_ACTION_KINDS,
|
|
8
|
+
import { ConfigurationError, defineEngine, isSecret, LOCATOR_ACTION_KINDS, POINTER_ACTION_KINDS, rejectUnknownKeys, } from 'e2e/engine';
|
|
9
9
|
import { createRequire } from 'node:module';
|
|
10
10
|
import { asBrowserProvider } from './provider.js';
|
|
11
11
|
import { PlaywrightSurface } from './surface.js';
|
|
12
|
-
import {
|
|
12
|
+
import { createBrowserFixture } from './browser.js';
|
|
13
|
+
/** App fields only a device target reads. */
|
|
14
|
+
const NATIVE_APP_KEYS = ['bundleId', 'appPath', 'launchArguments', 'permissions'];
|
|
13
15
|
/** Creates one Playwright engine: one browser per worker, one context per attempt. */
|
|
14
16
|
const surfaces = new WeakMap();
|
|
15
17
|
/** The live surface of a handle this module created, or undefined for any other engine. */
|
|
@@ -20,16 +22,22 @@ export function surfaceOf(engine) {
|
|
|
20
22
|
return { page: () => surface.requirePage(), context: () => surface.requireContext() };
|
|
21
23
|
}
|
|
22
24
|
export function web(options = {}) {
|
|
25
|
+
if ('allowedOrigins' in options) {
|
|
26
|
+
throw new ConfigurationError('INVALID_CONFIG', 'web({ allowedOrigins }) is gone: navigation and secret fills are not gated by origin; remove the option');
|
|
27
|
+
}
|
|
28
|
+
if ('video' in options) {
|
|
29
|
+
throw new ConfigurationError('INVALID_CONFIG', "web({ video }) was renamed web({ screencast }): it takes { size?, quality? } for the page screencast; which attempts record is the video mode on the config or a target");
|
|
30
|
+
}
|
|
31
|
+
rejectUnknownKeys('web()', options, WEB_OPTION_KEYS);
|
|
23
32
|
const provider = typeof options.browser === 'object' && options.browser !== null ? asBrowserProvider(options.browser) : undefined;
|
|
24
33
|
if (provider !== undefined && options.connect !== undefined) {
|
|
25
34
|
throw new ConfigurationError('INVALID_CONFIG', `web({ browser, connect }) names two browser sources; browser provider "${provider.name}" leases its own browsers, so remove connect`);
|
|
26
35
|
}
|
|
36
|
+
if (isRecord(options.connect))
|
|
37
|
+
rejectUnknownKeys('web({ connect })', options.connect, ['cdpEndpoint', 'reconnectEndpoint']);
|
|
27
38
|
if (options.connect !== undefined && typeof options.browser === 'string' && options.browser !== 'chromium') {
|
|
28
39
|
throw new ConfigurationError('INVALID_CONFIG', `web({ connect }) requires the chromium browser; CDP attach is chromium-only, got "${options.browser}"`);
|
|
29
40
|
}
|
|
30
|
-
if ('allowedOrigins' in options) {
|
|
31
|
-
throw new ConfigurationError('INVALID_CONFIG', 'web({ allowedOrigins }) is gone: navigation and secret fills are not gated by origin; remove the option');
|
|
32
|
-
}
|
|
33
41
|
if (options.headers !== undefined)
|
|
34
42
|
validateHeaders(options.headers);
|
|
35
43
|
if (options.basicAuth !== undefined)
|
|
@@ -38,9 +46,6 @@ export function web(options = {}) {
|
|
|
38
46
|
validateTestIdAttribute(options.testIdAttribute);
|
|
39
47
|
if (options.userAgent !== undefined)
|
|
40
48
|
validateUserAgent(options.userAgent, options.headers);
|
|
41
|
-
if ('video' in options) {
|
|
42
|
-
throw new ConfigurationError('INVALID_CONFIG', "web({ video }) was renamed web({ screencast }): it takes { size?, quality? } for the page screencast; which attempts record is the video mode on the config or a target");
|
|
43
|
-
}
|
|
44
49
|
if (options.screencast !== undefined)
|
|
45
50
|
validateScreencast(options.screencast);
|
|
46
51
|
const reconnecting = options.connect?.reconnectEndpoint !== undefined;
|
|
@@ -49,8 +54,8 @@ export function web(options = {}) {
|
|
|
49
54
|
}
|
|
50
55
|
// A per-attempt lease rides the same persistent context as `reconnectEndpoint`, with the same limits.
|
|
51
56
|
const recoverable = reconnecting || provider?.scope === 'attempt';
|
|
57
|
+
const mode = provider === undefined ? 'connect.reconnectEndpoint' : `browser provider "${provider.name}" with scope "attempt"`;
|
|
52
58
|
if (recoverable && (options.headers !== undefined || options.basicAuth !== undefined || options.userAgent !== undefined)) {
|
|
53
|
-
const mode = provider === undefined ? 'connect.reconnectEndpoint' : `browser provider "${provider.name}" with scope "attempt"`;
|
|
54
59
|
throw new ConfigurationError('INVALID_CONFIG', `${mode} uses a persistent context; headers, basicAuth, and userAgent require a newly created context`);
|
|
55
60
|
}
|
|
56
61
|
const surface = new PlaywrightSurface(options);
|
|
@@ -80,13 +85,13 @@ export function web(options = {}) {
|
|
|
80
85
|
type: (text, keyboardOptions, operation) => surface.typeText(text, keyboardOptions, operation),
|
|
81
86
|
press: (key, operation) => surface.pressKey(key, operation),
|
|
82
87
|
},
|
|
83
|
-
|
|
88
|
+
validateApp,
|
|
84
89
|
...(isSecret(options.basicAuth?.password) ? { secrets: [options.basicAuth.password] } : {}),
|
|
85
90
|
session: {
|
|
86
91
|
open: (url, operation) => surface.open(url, operation),
|
|
87
92
|
back: (operation) => surface.back(operation),
|
|
88
93
|
restart: (operation) => surface.restart(operation),
|
|
89
|
-
|
|
94
|
+
reset: recoverable ? () => Promise.reject(persistentContextLimit('app.clearState()', mode, provider !== undefined)) : (operation) => surface.reset(operation),
|
|
90
95
|
},
|
|
91
96
|
artifacts: {
|
|
92
97
|
screenshot: (label, operation) => surface.screenshot(label, operation),
|
|
@@ -104,12 +109,32 @@ export function web(options = {}) {
|
|
|
104
109
|
},
|
|
105
110
|
}),
|
|
106
111
|
fixtures: {
|
|
107
|
-
|
|
112
|
+
browser: (context) => createBrowserFixture(surface, context),
|
|
108
113
|
},
|
|
109
114
|
});
|
|
110
115
|
surfaces.set(handle, surface);
|
|
111
116
|
return handle;
|
|
112
117
|
}
|
|
118
|
+
/** Every option `web()` takes, kept equal to `WebOptions` by the compiler. */
|
|
119
|
+
const WEB_OPTION_KEYS = Object.keys({
|
|
120
|
+
browser: true,
|
|
121
|
+
viewport: true,
|
|
122
|
+
screencast: true,
|
|
123
|
+
connect: true,
|
|
124
|
+
headers: true,
|
|
125
|
+
basicAuth: true,
|
|
126
|
+
testIdAttribute: true,
|
|
127
|
+
userAgent: true,
|
|
128
|
+
});
|
|
129
|
+
/**
|
|
130
|
+
* What a persistent context rules out, named with its cause: `what` replaces
|
|
131
|
+
* the browser context, which `mode` never does. A per-attempt lease starts
|
|
132
|
+
* every attempt on a fresh browser already, and worker scope has the reset.
|
|
133
|
+
*/
|
|
134
|
+
function persistentContextLimit(what, mode, leased) {
|
|
135
|
+
const remedy = leased ? '; every attempt already starts on a fresh browser, and scope "worker" can clear one mid-test' : '';
|
|
136
|
+
return new ConfigurationError('UNSUPPORTED_CAPABILITY', `${what} is unavailable with ${mode}: it replaces the browser context, and the attempt rides one persistent context${remedy}`);
|
|
137
|
+
}
|
|
113
138
|
/** An HTTP header field name: one or more `token` characters (RFC 9110). */
|
|
114
139
|
const HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
115
140
|
/** A control character no HTTP field value may carry; a horizontal tab is the one the grammar allows. */
|
|
@@ -146,6 +171,7 @@ function validateBasicAuth(basicAuth) {
|
|
|
146
171
|
if (!isRecord(basicAuth)) {
|
|
147
172
|
throw new ConfigurationError('INVALID_CONFIG', 'web({ basicAuth }) must be an object with username and password');
|
|
148
173
|
}
|
|
174
|
+
rejectUnknownKeys('web({ basicAuth })', basicAuth, ['username', 'password']);
|
|
149
175
|
const { username, password } = basicAuth;
|
|
150
176
|
if (typeof username !== 'string' || username === '') {
|
|
151
177
|
throw new ConfigurationError('INVALID_CONFIG', 'web({ basicAuth }) requires a non-empty username string');
|
|
@@ -218,10 +244,20 @@ function validateTestIdAttribute(attribute) {
|
|
|
218
244
|
throw new ConfigurationError('INVALID_CONFIG', `web({ testIdAttribute }) must be an attribute name such as "data-testid", got ${JSON.stringify(attribute)}`);
|
|
219
245
|
}
|
|
220
246
|
}
|
|
221
|
-
/**
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
247
|
+
/**
|
|
248
|
+
* A browser target opens a URL: without `app.url` there is nothing for
|
|
249
|
+
* `app.open()` to open, and the fields that describe an installed device app
|
|
250
|
+
* have nothing to act on here.
|
|
251
|
+
*/
|
|
252
|
+
function validateApp(app, { targetName }) {
|
|
253
|
+
for (const key of NATIVE_APP_KEYS) {
|
|
254
|
+
if (app[key] !== undefined) {
|
|
255
|
+
throw new ConfigurationError('INVALID_CONFIG', `target "${targetName}" declares app.${key}, which describes an installed device app; a web() target opens app.url`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (app.url === undefined) {
|
|
259
|
+
throw new ConfigurationError('INVALID_CONFIG', `target "${targetName}" needs app.url: a web() target opens the app at a URL, targets: [{ engine: web(), app: { url: 'http://localhost:3000' } }]`);
|
|
260
|
+
}
|
|
225
261
|
}
|
|
226
262
|
/** This package's published version, read through require resolution. */
|
|
227
263
|
function ownVersion() {
|