@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.
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +138 -0
- package/dist/.build.json +1 -0
- package/dist/actions.d.ts +23 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +174 -0
- package/dist/actions.js.map +1 -0
- package/dist/attempt-session.d.ts +77 -0
- package/dist/attempt-session.d.ts.map +1 -0
- package/dist/attempt-session.js +293 -0
- package/dist/attempt-session.js.map +1 -0
- package/dist/browser-connection.d.ts +34 -0
- package/dist/browser-connection.d.ts.map +1 -0
- package/dist/browser-connection.js +86 -0
- package/dist/browser-connection.js.map +1 -0
- package/dist/capture-scope.d.ts +21 -0
- package/dist/capture-scope.d.ts.map +1 -0
- package/dist/capture-scope.js +61 -0
- package/dist/capture-scope.js.map +1 -0
- package/dist/cdp-recovery.d.ts +29 -0
- package/dist/cdp-recovery.d.ts.map +1 -0
- package/dist/cdp-recovery.js +84 -0
- package/dist/cdp-recovery.js.map +1 -0
- package/dist/cdp-selectors.d.ts +15 -0
- package/dist/cdp-selectors.d.ts.map +1 -0
- package/dist/cdp-selectors.js +52 -0
- package/dist/cdp-selectors.js.map +1 -0
- package/dist/closed-shadow.d.ts +64 -0
- package/dist/closed-shadow.d.ts.map +1 -0
- package/dist/closed-shadow.js +142 -0
- package/dist/closed-shadow.js.map +1 -0
- package/dist/dialogs.d.ts +38 -0
- package/dist/dialogs.d.ts.map +1 -0
- package/dist/dialogs.js +87 -0
- package/dist/dialogs.js.map +1 -0
- package/dist/engine.d.ts +26 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +176 -0
- package/dist/engine.js.map +1 -0
- package/dist/evaluation.d.ts +18 -0
- package/dist/evaluation.d.ts.map +1 -0
- package/dist/evaluation.js +35 -0
- package/dist/evaluation.js.map +1 -0
- package/dist/in-page/read-semantics.d.ts +28 -0
- package/dist/in-page/read-semantics.d.ts.map +1 -0
- package/dist/in-page/read-semantics.js +1178 -0
- package/dist/in-page/read-semantics.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +40 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +117 -0
- package/dist/install.js.map +1 -0
- package/dist/label-selector.d.ts +37 -0
- package/dist/label-selector.d.ts.map +1 -0
- package/dist/label-selector.js +53 -0
- package/dist/label-selector.js.map +1 -0
- package/dist/locators.d.ts +76 -0
- package/dist/locators.d.ts.map +1 -0
- package/dist/locators.js +289 -0
- package/dist/locators.js.map +1 -0
- package/dist/observation-capture.d.ts +12 -0
- package/dist/observation-capture.d.ts.map +1 -0
- package/dist/observation-capture.js +93 -0
- package/dist/observation-capture.js.map +1 -0
- package/dist/observation.d.ts +63 -0
- package/dist/observation.d.ts.map +1 -0
- package/dist/observation.js +280 -0
- package/dist/observation.js.map +1 -0
- package/dist/observe.d.ts +51 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +105 -0
- package/dist/observe.js.map +1 -0
- package/dist/operation-budget.d.ts +11 -0
- package/dist/operation-budget.d.ts.map +1 -0
- package/dist/operation-budget.js +40 -0
- package/dist/operation-budget.js.map +1 -0
- package/dist/protected-app.d.ts +32 -0
- package/dist/protected-app.d.ts.map +1 -0
- package/dist/protected-app.js +39 -0
- package/dist/protected-app.js.map +1 -0
- package/dist/provider.d.ts +158 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +311 -0
- package/dist/provider.js.map +1 -0
- package/dist/read-node.d.ts +152 -0
- package/dist/read-node.d.ts.map +1 -0
- package/dist/read-node.js +42 -0
- package/dist/read-node.js.map +1 -0
- package/dist/refs.d.ts +43 -0
- package/dist/refs.d.ts.map +1 -0
- package/dist/refs.js +85 -0
- package/dist/refs.js.map +1 -0
- package/dist/route-pattern.d.ts +13 -0
- package/dist/route-pattern.d.ts.map +1 -0
- package/dist/route-pattern.js +55 -0
- package/dist/route-pattern.js.map +1 -0
- package/dist/selector-engines.d.ts +6 -0
- package/dist/selector-engines.d.ts.map +1 -0
- package/dist/selector-engines.js +8 -0
- package/dist/selector-engines.js.map +1 -0
- package/dist/support.d.ts +147 -0
- package/dist/support.d.ts.map +1 -0
- package/dist/support.js +366 -0
- package/dist/support.js.map +1 -0
- package/dist/surface.d.ts +313 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +691 -0
- package/dist/surface.js.map +1 -0
- package/dist/video.d.ts +59 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +116 -0
- package/dist/video.js.map +1 -0
- package/dist/web.d.ts +191 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +382 -0
- package/dist/web.js.map +1 -0
- package/package.json +67 -0
package/dist/locators.js
ADDED
|
@@ -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"}
|