@e2e-dev/web 0.11.0-canary-20260928184528

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 (121) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +138 -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 +77 -0
  10. package/dist/attempt-session.d.ts.map +1 -0
  11. package/dist/attempt-session.js +293 -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 +86 -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 +15 -0
  26. package/dist/cdp-selectors.d.ts.map +1 -0
  27. package/dist/cdp-selectors.js +52 -0
  28. package/dist/cdp-selectors.js.map +1 -0
  29. package/dist/closed-shadow.d.ts +64 -0
  30. package/dist/closed-shadow.d.ts.map +1 -0
  31. package/dist/closed-shadow.js +142 -0
  32. package/dist/closed-shadow.js.map +1 -0
  33. package/dist/dialogs.d.ts +38 -0
  34. package/dist/dialogs.d.ts.map +1 -0
  35. package/dist/dialogs.js +87 -0
  36. package/dist/dialogs.js.map +1 -0
  37. package/dist/engine.d.ts +26 -0
  38. package/dist/engine.d.ts.map +1 -0
  39. package/dist/engine.js +176 -0
  40. package/dist/engine.js.map +1 -0
  41. package/dist/evaluation.d.ts +18 -0
  42. package/dist/evaluation.d.ts.map +1 -0
  43. package/dist/evaluation.js +35 -0
  44. package/dist/evaluation.js.map +1 -0
  45. package/dist/in-page/read-semantics.d.ts +28 -0
  46. package/dist/in-page/read-semantics.d.ts.map +1 -0
  47. package/dist/in-page/read-semantics.js +1178 -0
  48. package/dist/in-page/read-semantics.js.map +1 -0
  49. package/dist/index.d.ts +22 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +14 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/install.d.ts +40 -0
  54. package/dist/install.d.ts.map +1 -0
  55. package/dist/install.js +117 -0
  56. package/dist/install.js.map +1 -0
  57. package/dist/label-selector.d.ts +37 -0
  58. package/dist/label-selector.d.ts.map +1 -0
  59. package/dist/label-selector.js +53 -0
  60. package/dist/label-selector.js.map +1 -0
  61. package/dist/locators.d.ts +76 -0
  62. package/dist/locators.d.ts.map +1 -0
  63. package/dist/locators.js +289 -0
  64. package/dist/locators.js.map +1 -0
  65. package/dist/observation-capture.d.ts +12 -0
  66. package/dist/observation-capture.d.ts.map +1 -0
  67. package/dist/observation-capture.js +93 -0
  68. package/dist/observation-capture.js.map +1 -0
  69. package/dist/observation.d.ts +63 -0
  70. package/dist/observation.d.ts.map +1 -0
  71. package/dist/observation.js +280 -0
  72. package/dist/observation.js.map +1 -0
  73. package/dist/observe.d.ts +51 -0
  74. package/dist/observe.d.ts.map +1 -0
  75. package/dist/observe.js +105 -0
  76. package/dist/observe.js.map +1 -0
  77. package/dist/operation-budget.d.ts +11 -0
  78. package/dist/operation-budget.d.ts.map +1 -0
  79. package/dist/operation-budget.js +40 -0
  80. package/dist/operation-budget.js.map +1 -0
  81. package/dist/protected-app.d.ts +32 -0
  82. package/dist/protected-app.d.ts.map +1 -0
  83. package/dist/protected-app.js +39 -0
  84. package/dist/protected-app.js.map +1 -0
  85. package/dist/provider.d.ts +158 -0
  86. package/dist/provider.d.ts.map +1 -0
  87. package/dist/provider.js +311 -0
  88. package/dist/provider.js.map +1 -0
  89. package/dist/read-node.d.ts +152 -0
  90. package/dist/read-node.d.ts.map +1 -0
  91. package/dist/read-node.js +42 -0
  92. package/dist/read-node.js.map +1 -0
  93. package/dist/refs.d.ts +43 -0
  94. package/dist/refs.d.ts.map +1 -0
  95. package/dist/refs.js +85 -0
  96. package/dist/refs.js.map +1 -0
  97. package/dist/route-pattern.d.ts +13 -0
  98. package/dist/route-pattern.d.ts.map +1 -0
  99. package/dist/route-pattern.js +55 -0
  100. package/dist/route-pattern.js.map +1 -0
  101. package/dist/selector-engines.d.ts +6 -0
  102. package/dist/selector-engines.d.ts.map +1 -0
  103. package/dist/selector-engines.js +8 -0
  104. package/dist/selector-engines.js.map +1 -0
  105. package/dist/support.d.ts +147 -0
  106. package/dist/support.d.ts.map +1 -0
  107. package/dist/support.js +366 -0
  108. package/dist/support.js.map +1 -0
  109. package/dist/surface.d.ts +313 -0
  110. package/dist/surface.d.ts.map +1 -0
  111. package/dist/surface.js +691 -0
  112. package/dist/surface.js.map +1 -0
  113. package/dist/video.d.ts +59 -0
  114. package/dist/video.d.ts.map +1 -0
  115. package/dist/video.js +116 -0
  116. package/dist/video.js.map +1 -0
  117. package/dist/web.d.ts +191 -0
  118. package/dist/web.d.ts.map +1 -0
  119. package/dist/web.js +382 -0
  120. package/dist/web.js.map +1 -0
  121. package/package.json +67 -0
@@ -0,0 +1,289 @@
1
+ /** LocatorExpression -> Playwright locator projection. */
2
+ import { EngineError } from 'e2e/engine';
3
+ import { SEARCH_ROOTS_SELECTOR_ENGINE } from './closed-shadow.js';
4
+ import { exactLabelSelector } from './label-selector.js';
5
+ import { SECURE_FIELD_SELECTOR } from './read-node.js';
6
+ function patternToPw(pattern) {
7
+ if (pattern.kind === 'regexp')
8
+ return new RegExp(pattern.source, pattern.flags);
9
+ return pattern.value;
10
+ }
11
+ function patternExact(pattern) {
12
+ return pattern.kind === 'string' ? pattern.exact : false;
13
+ }
14
+ /**
15
+ * The selector `getByTestId` compiles to, with the project's attribute in
16
+ * place of Playwright's process-global one (`selectors.setTestIdAttribute`
17
+ * would leak one engine's attribute into every other engine of the process).
18
+ * The value is encoded as Playwright's `escapeForAttributeSelector` encodes it:
19
+ * a string is an exact, case-sensitive match; a RegExp is passed as written.
20
+ */
21
+ function testIdSelector(attribute, pattern) {
22
+ const name = attribute.includes(',') ? JSON.stringify(attribute) : attribute;
23
+ const value = pattern.kind === 'regexp'
24
+ ? escapeRegexForSelector(new RegExp(pattern.source, pattern.flags))
25
+ : `"${pattern.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"s`;
26
+ return `internal:testid=[${name}=${value}]`;
27
+ }
28
+ /** A RegExp written into a Playwright selector: quotes and `>>` escaped unless the flags forbid it. */
29
+ function escapeRegexForSelector(re) {
30
+ if (/[uv]/.test(re.flags))
31
+ return String(re);
32
+ return String(re)
33
+ .replace(/(^|[^\\])(\\\\)*(["'`])/g, '$1$2\\$3')
34
+ .replace(/>>/g, '\\>\\>');
35
+ }
36
+ /**
37
+ * The contract's role vocabulary spelled as the ARIA role the role selector
38
+ * knows, where the two differ: the tree reports an `img` as `image`, so an
39
+ * `image` query has to go back to `img` to match it.
40
+ */
41
+ const ARIA_ROLE_BY_CONTRACT_ROLE = { image: 'img' };
42
+ /** Every control that carries a current value: the candidates of a display-value query. */
43
+ const VALUED_SELECTOR = 'input, textarea, select';
44
+ /**
45
+ * The one table of query kinds: each declares its Playwright getter or its
46
+ * CSS candidate set. An exact label query is the one kind whose candidates
47
+ * depend on the pattern: exact goes to the `e2e-label` engine, substring
48
+ * stays with Playwright's `getByLabel`.
49
+ */
50
+ function candidatesOf(query, testIdAttribute) {
51
+ switch (query.kind) {
52
+ case 'role': {
53
+ if (query.value.kind !== 'string') {
54
+ throw new EngineError('ENGINE_FAILURE', 'role query value must be a string', {
55
+ retryable: false,
56
+ });
57
+ }
58
+ const options = {};
59
+ if (query.name !== undefined) {
60
+ options.name = patternToPw(query.name);
61
+ if (query.name.kind === 'string')
62
+ options.exact = query.name.exact;
63
+ }
64
+ const states = query.states ?? {};
65
+ if (states.checked !== undefined)
66
+ options.checked = states.checked;
67
+ if (states.disabled !== undefined)
68
+ options.disabled = states.disabled;
69
+ if (states.selected !== undefined)
70
+ options.selected = states.selected;
71
+ if (states.expanded !== undefined)
72
+ options.expanded = states.expanded;
73
+ if (states.pressed !== undefined)
74
+ options.pressed = states.pressed;
75
+ if (query.level !== undefined)
76
+ options.level = query.level;
77
+ const role = ARIA_ROLE_BY_CONTRACT_ROLE[query.value.value] ?? query.value.value;
78
+ return { kind: 'playwright', locate: (roots) => roots.getByRole(role, options) };
79
+ }
80
+ case 'label':
81
+ return query.value.kind === 'string' && query.value.exact
82
+ ? {
83
+ kind: 'engine',
84
+ selector: exactLabelSelector({ value: query.value.value, testIdAttribute, secureFieldSelector: SECURE_FIELD_SELECTOR }),
85
+ }
86
+ : { kind: 'playwright', locate: (roots) => roots.getByLabel(patternToPw(query.value), { exact: false }) };
87
+ case 'placeholder':
88
+ return { kind: 'playwright', locate: (roots) => roots.getByPlaceholder(patternToPw(query.value), { exact: patternExact(query.value) }) };
89
+ case 'text':
90
+ return { kind: 'playwright', locate: (roots) => roots.getByText(patternToPw(query.value), { exact: patternExact(query.value) }) };
91
+ case 'displayValue':
92
+ return { kind: 'css', selector: VALUED_SELECTOR };
93
+ case 'testId':
94
+ return { kind: 'playwright', locate: (roots) => roots.locator(testIdSelector(testIdAttribute, query.value)) };
95
+ }
96
+ }
97
+ /** Composes the candidates of one query onto `scope` and the closed shadow roots under it. */
98
+ function queryToPw(scope, query, testIdAttribute) {
99
+ const candidates = candidatesOf(query, testIdAttribute);
100
+ switch (candidates.kind) {
101
+ case 'css':
102
+ return scope.locator(`${SEARCH_ROOTS_SELECTOR_ENGINE}=${candidates.selector}`);
103
+ case 'engine':
104
+ return scope.locator(candidates.selector);
105
+ case 'playwright':
106
+ return candidates.locate(scope.locator(`${SEARCH_ROOTS_SELECTOR_ENGINE}=`));
107
+ }
108
+ }
109
+ /**
110
+ * Self-selector for the part of the semantic `hidden` state Playwright's own
111
+ * visibility filter does not read: `aria-hidden` on the element itself.
112
+ */
113
+ const NOT_ARIA_HIDDEN = ':scope:not([aria-hidden="true"])';
114
+ /**
115
+ * A `visible` query narrows its candidates inside the selector, before any
116
+ * enclosing scope, filter, or index runs: Playwright's visibility predicate
117
+ * (layout box, `display`, `visibility`) plus the `aria-hidden` check the
118
+ * semantic `hidden` state also makes. An indexed, filtered, or scoping visible
119
+ * query therefore never selects or retains a node that state calls hidden.
120
+ * The surface additionally holds a terminal query to the batch-read `hidden`
121
+ * state, which reads the same box, style, and `details` facts Playwright's
122
+ * predicate does, so a direct query agrees with `toBeVisible()`.
123
+ */
124
+ function visibleQueryToPw(scope, query, testIdAttribute) {
125
+ return narrowedToVisible(queryToPw(scope, query, testIdAttribute), query);
126
+ }
127
+ /** The visibility narrowing above, on a locator already built for `query`; identity unless the query is `visible`. */
128
+ function narrowedToVisible(located, query) {
129
+ if (query.visible !== true)
130
+ return located;
131
+ return located.filter({ visible: true }).locator(NOT_ARIA_HIDDEN);
132
+ }
133
+ function positioned(locator, index) {
134
+ return index === 'first' ? locator.first() : index === 'last' ? locator.last() : locator.nth(index);
135
+ }
136
+ const DISPLAY_VALUE_COMPOSITION_MESSAGE = 'displayValue queries cannot scope child queries or serve as a has-filter in this engine';
137
+ /**
138
+ * Projects a complete immutable expression onto a Playwright locator within
139
+ * one scope. Frame cardinality is validated separately by the surface.
140
+ *
141
+ * Every semantic query searches its scope and the closed shadow roots under
142
+ * it (see `Candidates`), so a scope, a `has` filter, and an index reach
143
+ * across a closed boundary. Two compositions stay Playwright's own and stop
144
+ * at one: a `selector` expression is the platform's CSS or XPath, and
145
+ * `filter({ hasText })` reads an element's text as Playwright does, light DOM
146
+ * and open roots, so text inside a closed root does not count toward an
147
+ * element outside it.
148
+ *
149
+ * A display-value query resolves to a candidate locator plus a value predicate
150
+ * the surface applies once the candidates are read. Per-element filters
151
+ * (`filter({ hasText, has })`) commute with that predicate, so they compose
152
+ * onto the candidate locator as for any other query. Positional selection does
153
+ * not commute (positions are relative to the value-filtered matches), so it is
154
+ * recorded as a step and applied after filtering; a filter that follows a
155
+ * position is recorded the same way and checked on the selected element. Two
156
+ * compositions need the predicate inside Playwright's own chain and stay
157
+ * unsupported: a display-value query as the scope of a child query, and as a
158
+ * `has` filter.
159
+ */
160
+ function project(scope, expression, testIdAttribute) {
161
+ switch (expression.kind) {
162
+ case 'query': {
163
+ const inner = expression.scope === undefined
164
+ ? scope
165
+ : requireComposable(project(scope, expression.scope, testIdAttribute));
166
+ const { query } = expression;
167
+ const exactLabel = query.kind === 'label' && query.value.kind === 'string' && query.value.exact ? query.value : null;
168
+ const locator = visibleQueryToPw(inner, query, testIdAttribute);
169
+ return {
170
+ locator,
171
+ displayValue: query.kind === 'displayValue' ? query.value : null,
172
+ name: exactLabel,
173
+ composable: exactLabel === null ? null : locator,
174
+ steps: [],
175
+ visible: query.visible === true,
176
+ };
177
+ }
178
+ case 'filter': {
179
+ const source = project(scope, expression.source, testIdAttribute);
180
+ const options = {};
181
+ if (expression.hasText !== undefined)
182
+ options.hasText = patternToPw(expression.hasText);
183
+ if (expression.has !== undefined) {
184
+ options.has = requireComposable(project(scope, expression.has, testIdAttribute));
185
+ }
186
+ if (source.steps.length > 0) {
187
+ return { ...source, steps: [...source.steps, { kind: 'filter', options }] };
188
+ }
189
+ return {
190
+ ...source,
191
+ locator: source.locator.filter(options),
192
+ composable: source.composable === null ? null : source.composable.filter(options),
193
+ steps: [],
194
+ };
195
+ }
196
+ case 'index': {
197
+ const source = project(scope, expression.source, testIdAttribute);
198
+ if (source.displayValue !== null || source.name !== null) {
199
+ return {
200
+ ...source,
201
+ composable: source.composable === null ? null : positioned(source.composable, expression.index),
202
+ steps: [...source.steps, { kind: 'index', index: expression.index }],
203
+ };
204
+ }
205
+ return {
206
+ locator: positioned(source.locator, expression.index),
207
+ displayValue: null,
208
+ name: null,
209
+ composable: null,
210
+ steps: [],
211
+ visible: false,
212
+ };
213
+ }
214
+ case 'selector':
215
+ return {
216
+ locator: scope.locator(expression.selector),
217
+ displayValue: null,
218
+ name: null,
219
+ composable: null,
220
+ steps: [],
221
+ visible: false,
222
+ };
223
+ case 'frame':
224
+ return project(scope.frameLocator(expression.selector), expression.source, testIdAttribute);
225
+ }
226
+ }
227
+ /** Projects an expression onto the page; `testIdAttribute` is what a `testId` query reads. */
228
+ export function projectExpression(page, expression, testIdAttribute) {
229
+ return project(page, expression, testIdAttribute);
230
+ }
231
+ /**
232
+ * Returns the locator of a projection that must participate in Playwright's
233
+ * own locator chain: a scope for child queries or a `has` target. A
234
+ * display-value projection cannot, because its value predicate lives outside
235
+ * that chain.
236
+ */
237
+ function requireComposable(projected) {
238
+ if (projected.composable !== null)
239
+ return projected.composable;
240
+ if (projected.displayValue !== null) {
241
+ throw new EngineError('UNSUPPORTED_CAPABILITY', DISPLAY_VALUE_COMPOSITION_MESSAGE, {
242
+ retryable: false,
243
+ });
244
+ }
245
+ return projected.locator;
246
+ }
247
+ /**
248
+ * Applies post steps, innermost first, to an ordered list of matches. `nth`
249
+ * past the end selects nothing, matching Playwright's `nth` on a locator with
250
+ * too few matches. A filter step keeps the matches `passesFilter` accepts;
251
+ * it runs only on the matches that survived the steps before it.
252
+ */
253
+ export async function applyPostSteps(matches, steps, passesFilter) {
254
+ let selected = matches;
255
+ for (const step of steps) {
256
+ if (step.kind === 'index') {
257
+ const { index } = step;
258
+ if (index === 'first')
259
+ selected = selected.slice(0, 1);
260
+ else if (index === 'last')
261
+ selected = selected.slice(-1);
262
+ else
263
+ selected = index < selected.length ? [selected[index]] : [];
264
+ continue;
265
+ }
266
+ const kept = [];
267
+ for (const match of selected) {
268
+ if (await passesFilter(match, step.options))
269
+ kept.push(match);
270
+ }
271
+ selected = kept;
272
+ }
273
+ return selected;
274
+ }
275
+ /** Returns every frame selector along an expression, outermost first. */
276
+ export function frameSelectors(expression) {
277
+ switch (expression.kind) {
278
+ case 'query':
279
+ return expression.scope === undefined ? [] : frameSelectors(expression.scope);
280
+ case 'filter':
281
+ case 'index':
282
+ return frameSelectors(expression.source);
283
+ case 'selector':
284
+ return [];
285
+ case 'frame':
286
+ return [expression.selector, ...frameSelectors(expression.source)];
287
+ }
288
+ }
289
+ //# sourceMappingURL=locators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locators.js","sourceRoot":"","sources":["../src/locators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** One observation transaction: settling, semantic capture, masked pixels, and staged refs. */
2
+ import type { Page } from 'playwright';
3
+ import { type EngineObserveOptions, type OperationContext } from 'e2e/engine';
4
+ import { RefRegistry, type CapturedObservation } from './refs.ts';
5
+ interface CaptureSettings {
6
+ readonly testIdAttribute: string;
7
+ readonly site: string | undefined;
8
+ }
9
+ /** Captures under one deadline, retaining no refs from a failed or abandoned document. */
10
+ export declare function captureObservation(page: Page, refs: RefRegistry, settings: CaptureSettings, operation: OperationContext, options: EngineObserveOptions | undefined): Promise<CapturedObservation>;
11
+ export {};
12
+ //# sourceMappingURL=observation-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation-capture.d.ts","sourceRoot":"","sources":["../src/observation-capture.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAE/F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAe,KAAK,oBAAoB,EAAuB,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAIhH,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAUlE,UAAU,eAAe;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,0FAA0F;AAC1F,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,oBAAoB,GAAG,SAAS,GACxC,OAAO,CAAC,mBAAmB,CAAC,CAqE9B"}
@@ -0,0 +1,93 @@
1
+ /** One observation transaction: settling, semantic capture, masked pixels, and staged refs. */
2
+ import { EngineError } from 'e2e/engine';
3
+ import { CaptureScope } from './capture-scope.js';
4
+ import { captureDocument, ROOT_NODE_ID } from './observation.js';
5
+ import { capturePixels } from './observe.js';
6
+ import { RefRegistry } from './refs.js';
7
+ import { cancelled, currentViewport } from './support.js';
8
+ /** Shared node budget across the main document and its frames. */
9
+ const MAX_OBSERVED_NODES = 3_000;
10
+ /** Settling is best-effort and spends from the observation's total budget. */
11
+ const SETTLE_TIMEOUT_MS = 5_000;
12
+ /** Leave time for a fresh masked screenshot after semantic capture expires. */
13
+ const PIXEL_FALLBACK_RESERVE_MS = 2_000;
14
+ /** Captures under one deadline, retaining no refs from a failed or abandoned document. */
15
+ export async function captureObservation(page, refs, settings, operation, options) {
16
+ const deadline = Date.now() + operation.timeoutMs;
17
+ let accepting = true;
18
+ const generation = new Map();
19
+ try {
20
+ const settleDeadline = Math.min(deadline, Date.now() + SETTLE_TIMEOUT_MS);
21
+ await new CaptureScope(settleDeadline, operation.signal).run(() => page.waitForLoadState('domcontentloaded', {
22
+ timeout: Math.max(1, settleDeadline - Date.now()),
23
+ })).catch(() => undefined);
24
+ if (operation.signal.aborted)
25
+ throw cancelled('observe cancelled');
26
+ const viewport = await currentViewport(page);
27
+ const semanticDeadline = options?.pixelFallback === true
28
+ ? deadline - Math.min(PIXEL_FALLBACK_RESERVE_MS, (deadline - Date.now()) / 4)
29
+ : deadline;
30
+ // The initial image is independent of the reader. A fallback always takes a fresh one.
31
+ const pixelCapture = options?.pixels === true
32
+ ? capturePixels(page, { ...operation, timeoutMs: semanticDeadline - Date.now() }, viewport).catch(() => undefined)
33
+ : Promise.resolve(undefined);
34
+ let snapshot;
35
+ try {
36
+ const [captured, pixels] = await Promise.all([
37
+ captureDocument({
38
+ ...settings,
39
+ reserveIds: (count) => refs.reserveIds(count),
40
+ commit: (id, element) => {
41
+ if (accepting && !operation.signal.aborted)
42
+ generation.set(id, { kind: 'element', element });
43
+ else
44
+ void element.dispose().catch(() => undefined);
45
+ },
46
+ }, page, {
47
+ framePath: [], budget: MAX_OBSERVED_NODES,
48
+ deadline: semanticDeadline, signal: operation.signal,
49
+ }),
50
+ pixelCapture,
51
+ ]);
52
+ snapshot = {
53
+ location: page.url(),
54
+ root: captured.tree,
55
+ viewport: { width: viewport.width, height: viewport.height },
56
+ ...(captured.truncated ? { truncated: true } : {}),
57
+ ...(pixels === undefined ? {} : { pixels: pixels.pixels, maskedRegionCount: pixels.maskedRegionCount }),
58
+ };
59
+ }
60
+ catch (cause) {
61
+ RefRegistry.dispose(generation);
62
+ generation.clear();
63
+ if (options?.pixelFallback !== true || !(cause instanceof EngineError) || cause.code !== 'OPERATION_TIMEOUT')
64
+ throw cause;
65
+ await pixelCapture;
66
+ const fallbackViewport = await currentViewport(page);
67
+ const pixels = await capturePixels(page, {
68
+ ...operation, timeoutMs: deadline - Date.now(),
69
+ }, fallbackViewport);
70
+ if (!pixels.maskingProven)
71
+ throw cause;
72
+ snapshot = {
73
+ location: page.url(),
74
+ root: { ref: { id: ROOT_NODE_ID, revision: '' } },
75
+ viewport: { width: fallbackViewport.width, height: fallbackViewport.height },
76
+ truncated: true,
77
+ treeUnavailable: true,
78
+ pixels: pixels.pixels,
79
+ maskedRegionCount: pixels.maskedRegionCount,
80
+ };
81
+ }
82
+ return { snapshot, generation };
83
+ }
84
+ catch (cause) {
85
+ RefRegistry.dispose(generation);
86
+ generation.clear();
87
+ throw cause;
88
+ }
89
+ finally {
90
+ accepting = false;
91
+ }
92
+ }
93
+ //# sourceMappingURL=observation-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation-capture.js","sourceRoot":"","sources":["../src/observation-capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Semantic tree capture for one observation: the in-page walk, nested-document
3
+ * stitching, and element-handle bookkeeping the surface keeps per generation.
4
+ */
5
+ import type { ElementHandle, Frame } from 'playwright';
6
+ import { type NodeRef, type SemanticNode } from 'e2e/engine';
7
+ import { type RawNodeData } from './read-node.ts';
8
+ /**
9
+ * The id of every observation's root: the main document's element under one
10
+ * id the engine mints, stable across observations and navigations, so the
11
+ * harness can address the viewport (`perform(root, swipe)`) from an earlier
12
+ * observation. Outside the `n<number>` space stamped ids and located ids share.
13
+ */
14
+ export declare const ROOT_NODE_ID = "root";
15
+ /** A page or frame: anything one document's reader can be evaluated on. */
16
+ export type DocumentHost = Pick<Frame, 'evaluateHandle'>;
17
+ /** What one capture needs from the surface that owns the generation. */
18
+ export interface CaptureDeps {
19
+ readonly testIdAttribute: string;
20
+ /** The app's site; a child frame off it stays a boundary node. Undefined admits no child frame. */
21
+ readonly site: string | undefined;
22
+ /** Reserves a disjoint range before the reader can stamp any element, including on timeout. */
23
+ reserveIds(count: number): number;
24
+ /** Publishes one element handle under its id in the generation being built. */
25
+ commit(id: string, element: ElementHandle<Element>): void;
26
+ }
27
+ export interface CaptureOptions {
28
+ /** Enclosing frame selectors, outermost first; empty for the main document. */
29
+ readonly framePath: readonly string[];
30
+ /** Remaining node budget shared across every document of the observation. */
31
+ readonly budget: number;
32
+ /**
33
+ * Absolute time (epoch ms) by which the whole observation must be done.
34
+ * Every document's budget is derived from what remains of it, so the
35
+ * documents of one observation can never sum past the operation's budget.
36
+ */
37
+ readonly deadline: number;
38
+ readonly signal: AbortSignal;
39
+ }
40
+ /** One document's tree with what the capture knows about its completeness. */
41
+ export interface CapturedDocument {
42
+ readonly tree: SemanticNode;
43
+ /** Nodes captured across this document and every child document stitched in. */
44
+ readonly nodeCount: number;
45
+ /**
46
+ * True when nodes on screen are missing from `tree`: the node budget cut
47
+ * the walk short in this document or a child, or an on-site child frame's
48
+ * document was not read (no budget or time left, past the depth limit, or
49
+ * its capture failed). Off-site frames are left out by design and never
50
+ * count.
51
+ */
52
+ readonly truncated: boolean;
53
+ }
54
+ /**
55
+ * Captures one document's semantic tree, then descends into each observed
56
+ * iframe boundary node via its content frame and stitches the child
57
+ * document under it. Frame capture is best-effort: a detached or unloaded
58
+ * frame leaves its boundary node childless rather than failing the
59
+ * observation. The node budget is shared across all documents.
60
+ */
61
+ export declare function captureDocument(deps: CaptureDeps, host: DocumentHost, options: CaptureOptions): Promise<CapturedDocument>;
62
+ export declare function toSemanticNode(ref: NodeRef, raw: RawNodeData, children?: readonly SemanticNode[], framePath?: readonly string[]): SemanticNode;
63
+ //# sourceMappingURL=observation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAY,MAAM,YAAY,CAAC;AACjE,OAAO,EAKL,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAGL,KAAK,WAAW,EAEjB,MAAM,gBAAgB,CAAC;AAGxB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,SAAS,CAAC;AAcnC,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;AAEzD,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,mGAAmG;IACnG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,+FAA+F;IAC/F,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAKD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AAmND,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,WAAW,EAChB,QAAQ,GAAE,SAAS,YAAY,EAAO,EACtC,SAAS,GAAE,SAAS,MAAM,EAAO,GAChC,YAAY,CA0Bd"}