@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.
Files changed (44) hide show
  1. package/README.md +14 -12
  2. package/dist/.build.json +1 -1
  3. package/dist/browser-connection.d.ts.map +1 -1
  4. package/dist/browser-connection.js +12 -1
  5. package/dist/browser-connection.js.map +1 -1
  6. package/dist/{web.d.ts → browser.d.ts} +18 -9
  7. package/dist/browser.d.ts.map +1 -0
  8. package/dist/{web.js → browser.js} +23 -16
  9. package/dist/browser.js.map +1 -0
  10. package/dist/downloads.d.ts +29 -0
  11. package/dist/downloads.d.ts.map +1 -0
  12. package/dist/downloads.js +74 -0
  13. package/dist/downloads.js.map +1 -0
  14. package/dist/engine.d.ts +2 -2
  15. package/dist/engine.d.ts.map +1 -1
  16. package/dist/engine.js +53 -17
  17. package/dist/engine.js.map +1 -1
  18. package/dist/in-page/read-semantics.d.ts.map +1 -1
  19. package/dist/in-page/read-semantics.js +101 -15
  20. package/dist/in-page/read-semantics.js.map +1 -1
  21. package/dist/index.d.ts +18 -9
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +7 -5
  24. package/dist/index.js.map +1 -1
  25. package/dist/locators.d.ts.map +1 -1
  26. package/dist/locators.js +26 -7
  27. package/dist/locators.js.map +1 -1
  28. package/dist/protected-app.d.ts +5 -3
  29. package/dist/protected-app.d.ts.map +1 -1
  30. package/dist/protected-app.js +16 -2
  31. package/dist/protected-app.js.map +1 -1
  32. package/dist/provider.d.ts +74 -4
  33. package/dist/provider.d.ts.map +1 -1
  34. package/dist/provider.js +110 -14
  35. package/dist/provider.js.map +1 -1
  36. package/dist/surface.d.ts +17 -9
  37. package/dist/surface.d.ts.map +1 -1
  38. package/dist/surface.js +19 -5
  39. package/dist/surface.js.map +1 -1
  40. package/dist/video.d.ts +1 -1
  41. package/dist/video.js +1 -1
  42. package/package.json +10 -8
  43. package/dist/web.d.ts.map +0 -1
  44. 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 engine declares the app it drives. App options: `url` (the base URL
33
- `app.open()` opens; required once a test navigates), `command` (a process the
34
- runner starts before the run and stops after it, with `readyUrl` to poll,
35
- default `url`), `environment`
36
- (`test`, `staging`, `production`; inferred from the host), and `identity` (a
37
- stable cache and session key when the origin is ephemeral). Browser options:
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 `web` fixture
105
+ ## The `browser` fixture
104
106
 
105
- The engine contributes `web`: navigation, routes, cookies, dialogs, frames,
106
- downloads, keyboard and mouse, plus `expect(web).toHaveURL()` and
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, web }) => {
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(web).toHaveURL('/dashboard');
119
+ await expect(browser).toHaveURL('/dashboard');
118
120
  });
119
121
  ```
120
122
 
package/dist/.build.json CHANGED
@@ -1 +1 @@
1
- {"version":"0.11.0-canary-20260929180659"}
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;AAE5D;;;;;;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
+ {"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;QAC1G,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
+ {"version":3,"file":"browser-connection.js","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  /**
2
- * The `web` fixture: the browser-shaped deterministic surface this engine
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 `web.<method>` step; `expect(web)` reaches the
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 WebExpectation {
83
+ export interface BrowserExpectation {
84
84
  /** Inverts the matcher. */
85
- readonly not: WebExpectation;
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 `web.frameLocator` returns. Every `Screen` query answers
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
- export interface Web extends Expectable<WebExpectation> {
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 `web` fixture for one attempt over the shared surface. */
190
- export declare function createWebFixture(surface: PlaywrightSurface, context: EngineFixtureContext): Web;
191
- //# sourceMappingURL=web.d.ts.map
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 `web` fixture: the browser-shaped deterministic surface this engine
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 `web.<method>` step; `expect(web)` reaches the
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 `web` fixture for one attempt over the shared surface. */
41
- export function createWebFixture(surface, context) {
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 = createWebExpectation({ currentUrl, currentTitle, baseHref, deadlineFor, context });
64
- const web = {
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(web).toHaveURL`, exposed as a wait.
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('web.locator', selector) }),
89
- frameLocator: (selector) => frameScreen(context, [requireSelector('web.frameLocator', selector)]),
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 `web.onDialog` step.
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
- await download.saveAs(absolute);
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('web', context.expectable(web, () => context.fixture('expect', expectation, matchers)), {
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(web)` matchers: URL, title, and class polling against the assertion budget. */
319
- function createWebExpectation(deps, negated = false) {
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 createWebExpectation(deps, !negated);
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=web.js.map
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 `web`
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
- * `web.goto()`, and either throws `INVALID_STATE` before that. The harness
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 {
@@ -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,EAQL,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAMlE;;;;;;;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,CAoG1D"}
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 `web`
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, obj, } from 'e2e/engine';
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 { createWebFixture } from './web.js';
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
- app: declaredApp(options),
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
- ...(recoverable ? {} : { reset: (operation) => surface.reset(operation) }),
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
- web: (context) => createWebFixture(surface, context),
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
- /** The app-declaration half of the options, so browser knobs never reach the manifest. */
222
- function declaredApp(options) {
223
- const { url, environment, identity, command, readyUrl, services } = options;
224
- return obj({ url, environment, identity, command, readyUrl, services });
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() {