@e2edev/web 0.11.0-canary-20260921180210

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 (101) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +112 -0
  4. package/dist/.build.json +1 -0
  5. package/dist/actions.d.ts +23 -0
  6. package/dist/actions.d.ts.map +1 -0
  7. package/dist/actions.js +174 -0
  8. package/dist/actions.js.map +1 -0
  9. package/dist/attempt-session.d.ts +76 -0
  10. package/dist/attempt-session.d.ts.map +1 -0
  11. package/dist/attempt-session.js +290 -0
  12. package/dist/attempt-session.js.map +1 -0
  13. package/dist/browser-connection.d.ts +34 -0
  14. package/dist/browser-connection.d.ts.map +1 -0
  15. package/dist/browser-connection.js +87 -0
  16. package/dist/browser-connection.js.map +1 -0
  17. package/dist/capture-scope.d.ts +21 -0
  18. package/dist/capture-scope.d.ts.map +1 -0
  19. package/dist/capture-scope.js +61 -0
  20. package/dist/capture-scope.js.map +1 -0
  21. package/dist/cdp-recovery.d.ts +29 -0
  22. package/dist/cdp-recovery.d.ts.map +1 -0
  23. package/dist/cdp-recovery.js +84 -0
  24. package/dist/cdp-recovery.js.map +1 -0
  25. package/dist/cdp-selectors.d.ts +14 -0
  26. package/dist/cdp-selectors.d.ts.map +1 -0
  27. package/dist/cdp-selectors.js +48 -0
  28. package/dist/cdp-selectors.js.map +1 -0
  29. package/dist/dialogs.d.ts +37 -0
  30. package/dist/dialogs.d.ts.map +1 -0
  31. package/dist/dialogs.js +78 -0
  32. package/dist/dialogs.js.map +1 -0
  33. package/dist/engine.d.ts +26 -0
  34. package/dist/engine.d.ts.map +1 -0
  35. package/dist/engine.js +166 -0
  36. package/dist/engine.js.map +1 -0
  37. package/dist/evaluation.d.ts +11 -0
  38. package/dist/evaluation.d.ts.map +1 -0
  39. package/dist/evaluation.js +27 -0
  40. package/dist/evaluation.js.map +1 -0
  41. package/dist/index.d.ts +21 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +14 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/install.d.ts +40 -0
  46. package/dist/install.d.ts.map +1 -0
  47. package/dist/install.js +117 -0
  48. package/dist/install.js.map +1 -0
  49. package/dist/locators.d.ts +74 -0
  50. package/dist/locators.d.ts.map +1 -0
  51. package/dist/locators.js +260 -0
  52. package/dist/locators.js.map +1 -0
  53. package/dist/observation-capture.d.ts +12 -0
  54. package/dist/observation-capture.d.ts.map +1 -0
  55. package/dist/observation-capture.js +93 -0
  56. package/dist/observation-capture.js.map +1 -0
  57. package/dist/observation.d.ts +63 -0
  58. package/dist/observation.d.ts.map +1 -0
  59. package/dist/observation.js +262 -0
  60. package/dist/observation.js.map +1 -0
  61. package/dist/observe.d.ts +51 -0
  62. package/dist/observe.d.ts.map +1 -0
  63. package/dist/observe.js +104 -0
  64. package/dist/observe.js.map +1 -0
  65. package/dist/operation-budget.d.ts +11 -0
  66. package/dist/operation-budget.d.ts.map +1 -0
  67. package/dist/operation-budget.js +40 -0
  68. package/dist/operation-budget.js.map +1 -0
  69. package/dist/protected-app.d.ts +32 -0
  70. package/dist/protected-app.d.ts.map +1 -0
  71. package/dist/protected-app.js +39 -0
  72. package/dist/protected-app.js.map +1 -0
  73. package/dist/read-node.d.ts +170 -0
  74. package/dist/read-node.d.ts.map +1 -0
  75. package/dist/read-node.js +823 -0
  76. package/dist/read-node.js.map +1 -0
  77. package/dist/refs.d.ts +43 -0
  78. package/dist/refs.d.ts.map +1 -0
  79. package/dist/refs.js +85 -0
  80. package/dist/refs.js.map +1 -0
  81. package/dist/route-pattern.d.ts +15 -0
  82. package/dist/route-pattern.d.ts.map +1 -0
  83. package/dist/route-pattern.js +68 -0
  84. package/dist/route-pattern.js.map +1 -0
  85. package/dist/support.d.ts +119 -0
  86. package/dist/support.d.ts.map +1 -0
  87. package/dist/support.js +299 -0
  88. package/dist/support.js.map +1 -0
  89. package/dist/surface.d.ts +257 -0
  90. package/dist/surface.d.ts.map +1 -0
  91. package/dist/surface.js +587 -0
  92. package/dist/surface.js.map +1 -0
  93. package/dist/video.d.ts +59 -0
  94. package/dist/video.d.ts.map +1 -0
  95. package/dist/video.js +115 -0
  96. package/dist/video.js.map +1 -0
  97. package/dist/web.d.ts +191 -0
  98. package/dist/web.d.ts.map +1 -0
  99. package/dist/web.js +354 -0
  100. package/dist/web.js.map +1 -0
  101. package/package.json +67 -0
@@ -0,0 +1,299 @@
1
+ /** Shared error translation, filename, and swipe helpers for the Playwright engine. */
2
+ import { EngineError } from 'e2e/engine';
3
+ import { ConfigurationError, InfrastructureError, TestError } from 'e2e/engine';
4
+ export const DEFAULT_VIEWPORT = { width: 1280, height: 720 };
5
+ function centreOf(rect) {
6
+ return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
7
+ }
8
+ function withinViewport(point, viewport) {
9
+ return point.x >= 0 && point.y >= 0 && point.x <= viewport.width && point.y <= viewport.height;
10
+ }
11
+ /** Narrows one action target to the shared Playwright action surface. */
12
+ export function asActionable(target) {
13
+ return target.kind === 'locator' ? target.locator : target.element;
14
+ }
15
+ /** Owning page of one action target. */
16
+ async function targetPage(target) {
17
+ if (target.kind === 'locator')
18
+ return target.locator.page();
19
+ const frame = await target.element.ownerFrame();
20
+ if (frame === null)
21
+ throw invalidState('element is detached from every frame');
22
+ return frame.page();
23
+ }
24
+ /**
25
+ * Bounding box of one action target. A locator waits up to `timeout` for its
26
+ * element to resolve; an element handle is already resolved, so its box is
27
+ * read immediately.
28
+ */
29
+ function targetBoundingBox(target, timeout) {
30
+ return target.kind === 'locator'
31
+ ? target.locator.boundingBox({ timeout })
32
+ : target.element.boundingBox();
33
+ }
34
+ /** Minimal scroll that brings one target into view, without centring it. */
35
+ async function scrollIntoViewNearest(target) {
36
+ const scroll = (el) => {
37
+ el.scrollIntoView({ block: 'nearest', inline: 'nearest' });
38
+ };
39
+ if (target.kind === 'locator')
40
+ await target.locator.evaluate(scroll);
41
+ else
42
+ await target.element.evaluate(scroll);
43
+ }
44
+ /**
45
+ * Drags one target onto another with the pointer.
46
+ *
47
+ * `Locator.dragTo` exists but takes a locator on both sides, and a node the
48
+ * agent reached through its observed reference is an element handle — which used
49
+ * to make the whole verb unavailable for exactly the elements that have no
50
+ * locator: an unlabelled thumbnail, an empty drop zone. Driving the pointer
51
+ * works for both kinds because a handle has a bounding box like anything else.
52
+ *
53
+ */
54
+ export async function performPointerDrag(source, destination, timeout) {
55
+ // Hover the source first: it auto-waits for actionability and scrolls the
56
+ // source into view, and the gesture starts there, so its position is the one
57
+ // that has to hold.
58
+ await asActionable(source).hover({ timeout });
59
+ const page = await targetPage(source);
60
+ const viewport = page.viewportSize() ?? DEFAULT_VIEWPORT;
61
+ let from = await targetBoundingBox(source, timeout);
62
+ let to = await targetBoundingBox(destination, timeout);
63
+ // A pointer can only be put at a viewport coordinate, so a destination below
64
+ // the fold has to be brought into view — `Locator.dragTo` scrolls both sides,
65
+ // and a pointer sequence that skips it aims where no element is and drops
66
+ // nothing.
67
+ //
68
+ // Neither obvious tool fits. `scrollIntoViewIfNeeded` centres the destination,
69
+ // which pushes the source out and costs the position hovering just
70
+ // established. `mouse.wheel` does not wait for the scroll it causes, so the
71
+ // boxes read after it are a race. `scrollIntoView({ block: 'nearest' })`
72
+ // scrolls the smallest amount that reveals the element, synchronously, which
73
+ // keeps both endpoints on screen whenever they can be.
74
+ if (to !== null && !withinViewport(centreOf(to), viewport)) {
75
+ await scrollIntoViewNearest(destination);
76
+ from = await targetBoundingBox(source, timeout);
77
+ to = await targetBoundingBox(destination, timeout);
78
+ }
79
+ if (from === null || to === null) {
80
+ throw new EngineError('NOT_ACTIONABLE', 'a drag endpoint has no visible bounding box', {
81
+ retryable: false,
82
+ });
83
+ }
84
+ const start = centreOf(from);
85
+ const end = centreOf(to);
86
+ // Endpoints that cannot be on screen together are reported rather than dragged
87
+ // between: a pointer sequence aimed off-screen looks like a drag that ran and
88
+ // leaves the page untouched, which surfaces later as a confusing assertion
89
+ // instead of the drag failure it is.
90
+ for (const [label, point] of [
91
+ ['source', start],
92
+ ['destination', end],
93
+ ]) {
94
+ if (!withinViewport(point, viewport)) {
95
+ throw new EngineError('NOT_ACTIONABLE', `the drag ${label} is outside the viewport at (${Math.round(point.x)}, ${Math.round(point.y)}) ` +
96
+ `of ${viewport.width}x${viewport.height}: the two endpoints cannot be reached in one gesture`, { retryable: false });
97
+ }
98
+ }
99
+ await page.mouse.move(start.x, start.y);
100
+ await page.mouse.down();
101
+ // Two moves: HTML5 drag-and-drop commits on `dragover`, and one move into the
102
+ // destination does not always produce one.
103
+ await page.mouse.move(end.x, end.y, { steps: 2 });
104
+ await page.mouse.move(end.x, end.y);
105
+ await page.mouse.up();
106
+ }
107
+ /** Playwright colorizes call logs; escape codes are noise in reports. */
108
+ // oxlint-disable-next-line no-control-regex -- intentionally matches the ESC control character
109
+ const ANSI_PATTERN = /\u001b\[\d+(?:;\d+)*m/g;
110
+ /** A failure's message with terminal control sequences removed. */
111
+ export function message(cause) {
112
+ const text = cause instanceof Error ? cause.message : String(cause);
113
+ return text.replace(ANSI_PATTERN, '');
114
+ }
115
+ /** Constrains a caller-supplied artifact label to a safe filename. */
116
+ export function sanitizeFilename(name) {
117
+ return name.replaceAll(/[^A-Za-z0-9._-]/g, '_').slice(0, 64) || 'artifact';
118
+ }
119
+ export function isPwTimeout(cause) {
120
+ return cause instanceof Error && cause.name === 'TimeoutError';
121
+ }
122
+ export function invalidState(text) {
123
+ return new EngineError('INVALID_STATE', text, { retryable: false });
124
+ }
125
+ export function cancelled(text) {
126
+ return new EngineError('CANCELLED', text, { retryable: false });
127
+ }
128
+ /**
129
+ * Holds one error raised on a path nobody awaits - a native dialog nobody
130
+ * handled, a route handler that broke its contract - until the next step
131
+ * enters the surface, which then fails with the real cause. Rethrows once:
132
+ * the failure belongs to the step that observes it, not to every later one.
133
+ */
134
+ export class ErrorLatch {
135
+ pending = null;
136
+ /** Latches an error; the first one wins until it is thrown. */
137
+ latch(error) {
138
+ this.pending ??= error;
139
+ }
140
+ /** Rethrows the latched error once, if any. */
141
+ throwPending() {
142
+ if (this.pending !== null) {
143
+ const error = this.pending;
144
+ this.pending = null;
145
+ throw error;
146
+ }
147
+ }
148
+ }
149
+ /**
150
+ * True for an error that already carries its classification: an `EngineError`
151
+ * from any module copy, or a runner error (policy, validation, timeout). Those
152
+ * must cross the boundary untouched; re-wrapping one would turn a
153
+ * `POLICY_DENIED` into an infrastructure failure.
154
+ */
155
+ export function isClassified(cause) {
156
+ if (cause instanceof EngineError || cause instanceof TestError)
157
+ return true;
158
+ if (cause instanceof ConfigurationError || cause instanceof InfrastructureError)
159
+ return true;
160
+ return cause instanceof Error && cause.name === 'EngineError';
161
+ }
162
+ /**
163
+ * How a Playwright failure maps onto the error contract. Every translator in
164
+ * this package and in `actions.ts` follows this table:
165
+ *
166
+ * | Playwright failure | Code |
167
+ * | --------------------------------------------------------------- | ------------------------- |
168
+ * | already an EngineError / runner error | passed through untouched |
169
+ * | `TimeoutError` on a read, navigation, or artifact call | OPERATION_TIMEOUT |
170
+ * | `TimeoutError` on an action, log ends before the input dispatch | NOT_ACTIONABLE |
171
+ * | `TimeoutError` on an action, log shows the dispatch started | ACTION_MAY_HAVE_COMMITTED |
172
+ * | element detached / not attached / no element / resolved hidden | NODE_STALE (retryable) |
173
+ * | execution context destroyed / frame detached by a navigation | NODE_STALE (retryable) |
174
+ * | not an input / not editable / not checkable | NOT_ACTIONABLE |
175
+ * | strict mode violation, anything else | ENGINE_FAILURE |
176
+ *
177
+ * The action split is read from the call log Playwright appends to a timeout
178
+ * message: `performing <x> action`, `<x> action done`, and `waiting for
179
+ * scheduled navigations to finish` are only logged once the input is being (or
180
+ * has been) dispatched, so a timeout whose log reaches them is uncertain and
181
+ * the harness must not blindly repeat it. Every earlier line (`waiting for
182
+ * element to be visible, enabled and stable`, `scrolling into view if
183
+ * needed`, `retrying <x> action`) precedes dispatch and is a plain
184
+ * actionability miss.
185
+ */
186
+ export const POST_DISPATCH_PATTERN = /performing \w+ action|\w+ action done|waiting for scheduled navigations to finish/i;
187
+ /** Translates an unexpected Playwright error at the contract boundary. */
188
+ export function translatePwError(cause, operation) {
189
+ if (isClassified(cause))
190
+ return cause;
191
+ if (isPwTimeout(cause)) {
192
+ return new EngineError('OPERATION_TIMEOUT', `${operation} timed out: ${message(cause)}`, {
193
+ retryable: false,
194
+ cause,
195
+ });
196
+ }
197
+ return new EngineError('ENGINE_FAILURE', `${operation} failed: ${message(cause)}`, {
198
+ retryable: false,
199
+ cause,
200
+ });
201
+ }
202
+ const STALE_PATTERN = /detached|not attached|resolved to hidden|no element|not found/i;
203
+ /**
204
+ * A read that raced a navigation: the document it was reading was replaced
205
+ * mid-flight. Nothing was dispatched, so the read is repeatable against the
206
+ * new document — the same condition as a stale node, reported as one.
207
+ */
208
+ const NAVIGATION_RACE_PATTERN = /execution context was destroyed|because of a navigation|navigating and changing the content|frame was detached|frame got detached|node is detached from document/i;
209
+ /** Whether a Playwright failure describes a read that lost its document to a navigation. */
210
+ function isNavigationRace(cause) {
211
+ return NAVIGATION_RACE_PATTERN.test(message(cause));
212
+ }
213
+ /**
214
+ * Like translatePwError, but a read that lost its document to a navigation
215
+ * becomes retryable NODE_STALE so the runner re-reads the new document instead
216
+ * of failing the call. Timeouts keep their meaning: an observation that cannot
217
+ * be captured in time is not a race.
218
+ */
219
+ export function navigationStaleOr(cause, operation) {
220
+ if (!isClassified(cause) && isNavigationRace(cause)) {
221
+ return new EngineError('NODE_STALE', `${operation}: ${message(cause)}`, {
222
+ retryable: true,
223
+ cause,
224
+ });
225
+ }
226
+ return translatePwError(cause, operation);
227
+ }
228
+ /**
229
+ * Like translatePwError, but detachment/miss failures become retryable
230
+ * NODE_STALE. A timeout stays a timeout: `locate` resolves once and never
231
+ * waits, so a `TimeoutError` there is a budget that ran out, not a miss.
232
+ */
233
+ export function staleOr(cause, operation) {
234
+ if (isClassified(cause))
235
+ return cause;
236
+ const text = message(cause);
237
+ if (STALE_PATTERN.test(text) || isNavigationRace(cause)) {
238
+ return new EngineError('NODE_STALE', `${operation}: ${text}`, { retryable: true, cause });
239
+ }
240
+ return translatePwError(cause, operation);
241
+ }
242
+ export function performViewportSwipe(page, direction, momentum) {
243
+ const viewport = page.viewportSize() ?? DEFAULT_VIEWPORT;
244
+ const distance = swipeDistance(direction === 'up' || direction === 'down' ? viewport.height : viewport.width, momentum);
245
+ const [deltaX, deltaY] = wheelDelta(direction, distance);
246
+ return page.mouse.wheel(deltaX, deltaY);
247
+ }
248
+ /**
249
+ * The browser truncates a fractional pointer coordinate, so a point composed
250
+ * from a fractional box (`tap({ position })` on a node at y 148.875) would
251
+ * land on the pixel before the one asked for; it is rounded to the nearest
252
+ * CSS pixel instead.
253
+ */
254
+ export function nearestPixel(point) {
255
+ return { x: Math.round(point.x), y: Math.round(point.y) };
256
+ }
257
+ /** A pointer drag from one viewport point to another, on whole pixels, with an intermediate move so drag handlers see motion. */
258
+ export async function performPointDrag(mouse, start, end) {
259
+ const from = nearestPixel(start);
260
+ const to = nearestPixel(end);
261
+ const middle = nearestPixel({ x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 });
262
+ await mouse.move(from.x, from.y);
263
+ await mouse.down();
264
+ await mouse.move(middle.x, middle.y);
265
+ await mouse.move(to.x, to.y);
266
+ await mouse.up();
267
+ }
268
+ export async function performElementSwipe(target, direction, momentum, timeout) {
269
+ // Hover first: it auto-waits for visibility on both target kinds, so the
270
+ // immediate box read below observes a settled element.
271
+ await asActionable(target).hover({ timeout });
272
+ const box = await targetBoundingBox(target, timeout);
273
+ if (box === null) {
274
+ throw new EngineError('NOT_ACTIONABLE', 'element has no visible bounding box', {
275
+ retryable: false,
276
+ });
277
+ }
278
+ const distance = swipeDistance(direction === 'up' || direction === 'down' ? box.height : box.width, momentum);
279
+ const [deltaX, deltaY] = wheelDelta(direction, distance);
280
+ const page = await targetPage(target);
281
+ await page.mouse.wheel(deltaX, deltaY);
282
+ }
283
+ function swipeDistance(extent, momentum) {
284
+ const ratio = momentum === 'fast' ? 1.5 : momentum === 'slow' ? 0.75 : 0.5;
285
+ return Math.round(extent * ratio);
286
+ }
287
+ function wheelDelta(direction, distance) {
288
+ switch (direction) {
289
+ case 'down':
290
+ return [0, distance];
291
+ case 'up':
292
+ return [0, -distance];
293
+ case 'right':
294
+ return [distance, 0];
295
+ case 'left':
296
+ return [-distance, 0];
297
+ }
298
+ }
299
+ //# sourceMappingURL=support.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support.js","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * The Playwright surface: one browser per worker, one browser context per
3
+ * attempt, and the page every engine member delegates to. This is the closure
4
+ * state behind `web()`; the engine hooks in `engine.ts` and the `web`
5
+ * fixture in `web.ts` are thin delegates onto it. Action dispatch lives in
6
+ * `actions.ts` and tree capture in `observation.ts`. `AttemptSession` owns
7
+ * the attempt's live binding, recovery, references, and recordings.
8
+ */
9
+ import type { BrowserContext, Page, Route } from 'playwright';
10
+ import { type EngineAppDeclaration, type EngineAttemptContext, type EngineCleanupContext, type EngineInitInfo, type EngineObserveOptions, type EnginePrepareInfo, type EngineSnapshot, type EngineState, type LocatorAction, type LocatorExpression, type NodeRef, type OperationContext, type PointerAction, type SemanticNode, type VideoSegment, type ViewportPoint, type ViewportSize } from 'e2e/engine';
11
+ import { type BrowserName } from './browser-connection.ts';
12
+ import { DialogRouter } from './dialogs.ts';
13
+ import { ErrorLatch } from './support.ts';
14
+ type RoutePredicate = (url: URL) => boolean;
15
+ type RouteHandler = (route: Route) => Promise<void>;
16
+ /**
17
+ * Attach to a remote browser over CDP instead of launching a local one. The
18
+ * seam a hosted-browser engine plugs into: a per-run cloud session (its
19
+ * endpoint provisioned only once the run starts) resolves through
20
+ * `cdpEndpoint` at `init`, and again at an attempt start after a disconnect.
21
+ * Supplying `reconnectEndpoint` opts into a persistent context instead.
22
+ * CDP attach is chromium-only.
23
+ */
24
+ export interface WebConnectOptions {
25
+ /**
26
+ * Resolves the CDP endpoint (a `ws://`/`wss://` or `http://` DevTools URL)
27
+ * to attach to. Async because a hosted endpoint is not known at config load;
28
+ * called once per worker in `init`, and again at the start of any attempt
29
+ * that finds the session dropped, so a fresh per-run URL reconnects cleanly.
30
+ * With `reconnectEndpoint`, init defers provisioning and every attempt
31
+ * calls this resolver for a fresh, dedicated browser instead.
32
+ * `signal` aborts when the init or attempt that needs the browser is
33
+ * cancelled or exceeds its budget: a resolver that provisions a session
34
+ * should stop and release it, since a browser that arrives late is detached.
35
+ */
36
+ readonly cdpEndpoint: (signal: AbortSignal) => string | Promise<string>;
37
+ /**
38
+ * Opts into a dedicated persistent remote context. `cdpEndpoint` provisions
39
+ * a fresh browser at each attempt start; this resolver reconnects to that
40
+ * same browser after a transport drop. Called once before the next
41
+ * operation, within its budget. The original browser and page must survive.
42
+ * Dispatched operations are never retried. The host owns browser cleanup.
43
+ * Context replacement, headers, and basicAuth are unavailable in this mode.
44
+ */
45
+ readonly reconnectEndpoint?: (signal: AbortSignal) => string | Promise<string>;
46
+ }
47
+ /** HTTP basic authentication the browser answers a `401` challenge with. */
48
+ export interface WebBasicAuth {
49
+ /** The user name; `:` is not allowed in one (RFC 7617). */
50
+ readonly username: string;
51
+ readonly password: string;
52
+ }
53
+ /**
54
+ * Options of the browser engine: the app it drives (`url`, `command`,
55
+ * `services`, `environment`, `identity`, `readyUrl` - the
56
+ * engine contract's app declaration) plus the browser itself.
57
+ */
58
+ export interface WebOptions extends EngineAppDeclaration {
59
+ /** Browser to launch; defaults to chromium. */
60
+ readonly browser?: BrowserName;
61
+ /** Initial viewport of every attempt's page; default 1280 by 720. */
62
+ readonly viewport?: ViewportSize;
63
+ /**
64
+ * Attach to a remote browser over CDP instead of launching locally. Requires
65
+ * the chromium browser (the default). Wired by a hosted-browser engine.
66
+ */
67
+ readonly connect?: WebConnectOptions;
68
+ /**
69
+ * HTTP headers added to every request the browser sends to an allowed
70
+ * origin: a preview-protection bypass token, a tunnel's interstitial skip.
71
+ * Requests to any other origin (a CDN, an analytics endpoint, an identity
72
+ * provider) never carry them, so a header that is a secret stays with the
73
+ * app it unlocks. Names are case-insensitive; a header the page already
74
+ * sends under the same name is replaced. Applies to every path onto the
75
+ * page, deterministic and agent-driven alike. Injecting headers routes
76
+ * every request of the attempt, which turns the browser's HTTP cache off
77
+ * and blocks service workers (a worker's requests bypass routing, so a
78
+ * page it controlled would reach the gate bare), and a Playwright trace
79
+ * records request headers.
80
+ */
81
+ readonly headers?: Readonly<Record<string, string>>;
82
+ /**
83
+ * HTTP basic authentication for a staging app behind a browser challenge.
84
+ * The browser answers a `401` with these credentials wherever one is
85
+ * issued, as Playwright's own `httpCredentials` does. Applies to every path
86
+ * onto the page.
87
+ */
88
+ readonly basicAuth?: WebBasicAuth;
89
+ /**
90
+ * The attribute that carries an element's test id: what the `testId` query
91
+ * (`screen.getByTestId`) resolves and what `SemanticNode.testId` reports.
92
+ * Defaults to `data-testid`.
93
+ */
94
+ readonly testIdAttribute?: string;
95
+ }
96
+ export declare class PlaywrightSurface {
97
+ /**
98
+ * Errors raised where nobody awaits them (dialog routing, route handlers)
99
+ * wait here and fail the next step that enters the surface.
100
+ */
101
+ latch: ErrorLatch;
102
+ dialogs: DialogRouter;
103
+ private readonly browserName;
104
+ private readonly connection;
105
+ private readonly connect;
106
+ private session;
107
+ private readonly usedContexts;
108
+ private readonly viewport;
109
+ /** Injected request headers, names lowercased so they replace the browser's own of the same name. */
110
+ private readonly headers;
111
+ private readonly basicAuth;
112
+ private readonly testIdAttribute;
113
+ private app;
114
+ private headed;
115
+ private artifactsDir;
116
+ private artifactCounter;
117
+ /**
118
+ * Attempt-scoped network routes. Registered on the
119
+ * context, not a page, so they cover every page the attempt opens - the
120
+ * first navigation included - and re-applied to each context the attempt
121
+ * replaces on `reset` or session restore.
122
+ */
123
+ private routes;
124
+ constructor(options: WebOptions);
125
+ /**
126
+ * Installs the browser on first run, once per run before any worker.
127
+ * A CDP attach uses the remote's browser, so only a local launch needs the
128
+ * browser here. The download narrates through `info.log` and is bounded by
129
+ * the run's interrupt alone, never by a launch budget.
130
+ */
131
+ prepare(info: EnginePrepareInfo): Promise<void>;
132
+ /** Provisions the shared browser once per worker: a local launch, or a CDP attach. */
133
+ init(info: EngineInitInfo): Promise<void>;
134
+ /**
135
+ * Provisions the shared browser through the shared connection — a launch, or a CDP attach
136
+ * via the connector — bounded by `signal`. Checked before the endpoint is
137
+ * resolved: a cancelled caller must never provision a remote session it will
138
+ * not use.
139
+ */
140
+ private acquireBrowser;
141
+ /**
142
+ * Builds the connection's connector when attaching over CDP; undefined for a local
143
+ * launch. The connector honours `signal` at every await: the resolver
144
+ * receives it, the endpoint is not used once aborted, and a browser that
145
+ * connects after cancellation is detached at once rather than cached — the
146
+ * host's session is never held by an init or attempt that already gave up.
147
+ */
148
+ private connector;
149
+ /** Opens one attempt owner before setup starts, so cleanup can cancel pending attachment. */
150
+ startAttempt(context: EngineAttemptContext): Promise<void>;
151
+ /** Retires the owner before awaiting cleanup; late work cannot reach the next attempt. */
152
+ endAttempt(context: EngineCleanupContext): Promise<void>;
153
+ /** Releases attempt resources and the worker's shared browser process. */
154
+ dispose(context: EngineCleanupContext): Promise<void>;
155
+ /** Returns the active attempt, including its connection generation and references. */
156
+ private requireSession;
157
+ /** Registers one attempt-scoped route on the current context. */
158
+ route(predicate: RoutePredicate, handler: RouteHandler): Promise<void>;
159
+ /** Removes one registered route from the attempt and the current context. */
160
+ unroute(predicate: RoutePredicate, handler: RouteHandler): Promise<void>;
161
+ requirePage(): Page;
162
+ requireContext(): BrowserContext;
163
+ /** Creates the active page through the attempt's sole binding owner. */
164
+ ensurePage(): Promise<Page>;
165
+ /**
166
+ * The single entry of every operation: rethrows an error latched on an
167
+ * unawaited path, refuses a cancelled operation, races `fn` against the
168
+ * operation signal so an abort mid-call surfaces as `CANCELLED` instead of
169
+ * waiting out Playwright, and translates raw errors at the contract
170
+ * boundary. `translate` overrides the default translation for operations
171
+ * with a documented retryable failure mode.
172
+ */
173
+ guard<T>(operation: OperationContext, label: string, fn: (operation: OperationContext) => Promise<T>, translate?: (cause: unknown, label: string) => Error): Promise<T>;
174
+ /** Opens one URL the harness resolved; the attempt's page is created on first use. */
175
+ open(url: string, operation: OperationContext): Promise<void>;
176
+ back(operation: OperationContext): Promise<void>;
177
+ /** Restarts the document while retaining this attempt's context and storage. */
178
+ restart(operation: OperationContext): Promise<void>;
179
+ /** Replaces the context with a clean one and opens its blank page. */
180
+ reset(operation: OperationContext): Promise<void>;
181
+ /**
182
+ * Resolves one expression to every node it currently matches, fully read,
183
+ * in one in-page round trip. A `displayValue` query is filtered here by the
184
+ * value each element reported, so no per-node calls are needed; any
185
+ * `first`/`last`/`nth` on such a query then selects among those matches, and
186
+ * a filter placed after a position is checked on the selected element. A
187
+ * `visible` query drops the candidates whose hidden state the same read
188
+ * reported before either of those, so a position is among shown matches.
189
+ */
190
+ locate(expression: LocatorExpression, operation: OperationContext): Promise<readonly SemanticNode[]>;
191
+ /**
192
+ * One action on a located or observed node. A `swipe` on the observation
193
+ * root is the viewport swipe: a wheel gesture sized by the viewport, with no
194
+ * element resolved behind it, so it needs only the page. Every other action
195
+ * on the root acts on the document element the root stands for.
196
+ */
197
+ perform(ref: NodeRef, action: LocatorAction, operation: OperationContext): Promise<void>;
198
+ /** One pointer action at a viewport point in CSS pixels, with nothing resolved behind it; see `dispatchPointerAction`. */
199
+ performAt(point: ViewportPoint, action: PointerAction, operation: OperationContext): Promise<void>;
200
+ /**
201
+ * Types into whatever holds focus. Keystrokes into a document body are
202
+ * accepted by the browser and lost, so the focused element is checked for
203
+ * editability first and the call refuses rather than "typing" into nothing.
204
+ * `replace` clears with select-all and delete: the only locator-free clear,
205
+ * scoped by the browser to the whole editing host, so it is opt-in.
206
+ */
207
+ typeText(text: string, options: {
208
+ readonly replace: boolean;
209
+ }, operation: OperationContext): Promise<void>;
210
+ /** Sends one key to whatever holds focus, in the contract's key grammar Playwright shares. */
211
+ pressKey(key: string, operation: OperationContext): Promise<void>;
212
+ /**
213
+ * Refuses focused typing when nothing that takes keystrokes has focus, in
214
+ * any frame of the page. Text fields and contenteditable hosts take them;
215
+ * so does any other focusable element the app made focusable (a canvas, a
216
+ * widget with a tabindex and its own key handling), because focusing it is
217
+ * how the app opted into keys. Focus on the body, a button, a link, a
218
+ * select, or a non-text input means the keystrokes would be discarded.
219
+ */
220
+ private requireEditableFocus;
221
+ private validateFrames;
222
+ /**
223
+ * Reserves one artifact path under the attempt directory: a per-attempt
224
+ * counter keeps names unique, the label keeps them readable.
225
+ */
226
+ artifactPath(folder: string, label: string | undefined, extension: string): {
227
+ relative: string;
228
+ absolute: string;
229
+ };
230
+ /** Redacted at the source: secure fields in every frame are masked, as in observation pixels. */
231
+ screenshot(label: string | undefined, operation: OperationContext): Promise<string>;
232
+ /** Starts tracing the current attempt. */
233
+ startTrace(operation: OperationContext): Promise<void>;
234
+ /** Returns every trace segment finalized by the current attempt. */
235
+ stopTrace(operation: OperationContext): Promise<string | readonly string[]>;
236
+ /** Starts the attempt's video before a trace chooses its screencast dimensions. */
237
+ startVideo(operation: OperationContext): Promise<void>;
238
+ /** Finishes the attempt's recording and returns its finalized segments. */
239
+ stopVideo(operation: OperationContext): Promise<readonly VideoSegment[]>;
240
+ captureState(operation: OperationContext): Promise<EngineState>;
241
+ /** Replaces the attempt's context with one seeded from the snapshot. */
242
+ restoreState(state: EngineState, operation: OperationContext): Promise<void>;
243
+ /**
244
+ * Captures one atomic semantic observation. Secure fields are masked in the
245
+ * page before the tree leaves the engine, and every node keeps a live
246
+ * element handle valid until the next observation replaces the generation.
247
+ *
248
+ * With `options.pixels`, masked viewport pixels are captured alongside the
249
+ * tree rather than after it, so the image and the node geometry describe the
250
+ * page as closely in time as two engine calls can.
251
+ */
252
+ observe(operation: OperationContext, options?: EngineObserveOptions): Promise<EngineSnapshot>;
253
+ /** Captures privately, then publishes only into the page and ref generation that requested it. */
254
+ private captureObservation;
255
+ }
256
+ export {};
257
+ //# sourceMappingURL=surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../src/surface.ts"],"names":[],"mappings":"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"}