@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,40 @@
1
+ /** First-run browser provisioning for the Playwright engine. */
2
+ import { type BrowserName } from './browser-connection.ts';
3
+ /** What an installer receives besides the browser names. */
4
+ export interface InstallContext {
5
+ /** Receives every line the installer prints: the download URL, progress, warnings. */
6
+ readonly log: (line: string) => void;
7
+ /** Aborts a download in progress. */
8
+ readonly signal?: AbortSignal | undefined;
9
+ /** Environment the installer runs with: the run's, so it fills the cache the workers will launch from. */
10
+ readonly env: NodeJS.ProcessEnv;
11
+ }
12
+ export interface EnsureBrowsersOptions {
13
+ /**
14
+ * Receives progress lines; defaults to stderr. The engine's `prepare` hands
15
+ * the harness's `info.log` here, so a first-run download narrates through
16
+ * the reporter rather than underneath it.
17
+ */
18
+ readonly log?: (line: string) => void;
19
+ /**
20
+ * Injected detection for tests; defaults to an executable existence check.
21
+ * Undefined means "cannot tell here": the installer runs and decides.
22
+ */
23
+ readonly isInstalled?: (name: BrowserName) => boolean | undefined;
24
+ /** Injected installer for tests; defaults to spawning the Playwright CLI. */
25
+ readonly install?: (names: readonly BrowserName[], context: InstallContext) => Promise<void>;
26
+ /** Aborts a download in progress; the run's interrupt owns it. */
27
+ readonly signal?: AbortSignal;
28
+ /** The run's environment; defaults to this process's. */
29
+ readonly env?: NodeJS.ProcessEnv;
30
+ }
31
+ /**
32
+ * Ensures the given Playwright browsers are installed, downloading any
33
+ * missing ones via `playwright install`. Called from the engine's `prepare`,
34
+ * once per run before any worker starts, so a download is never charged
35
+ * against a launch timeout and never runs once per worker. Concurrent
36
+ * installs (two runs at once) are still safe: the Playwright CLI serializes
37
+ * them with a registry lock.
38
+ */
39
+ export declare function ensureBrowsersInstalled(names: readonly BrowserName[], options?: EnsureBrowsersOptions): Promise<void>;
40
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAOhE,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAyBxE,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,qCAAqC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,0GAA0G;IAC1G,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,GAAG,SAAS,CAAC;IAClE,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAef"}
@@ -0,0 +1,117 @@
1
+ /** First-run browser provisioning for the Playwright engine. */
2
+ import { spawn } from 'node:child_process';
3
+ import { existsSync } from 'node:fs';
4
+ import { createRequire } from 'node:module';
5
+ import path from 'node:path';
6
+ import { EngineError, InfrastructureError } from 'e2e/engine';
7
+ import { browserType } from './browser-connection.js';
8
+ /**
9
+ * Whether the browser's executable exists on disk, or undefined when this
10
+ * process cannot tell. Playwright resolves its browser cache from
11
+ * `PLAYWRIGHT_BROWSERS_PATH` at module load, so the in-process check is only
12
+ * authoritative when the run's environment agrees with this process's. A run
13
+ * pointed at another cache is left to the CLI, which resolves against the
14
+ * environment it is spawned with and is a no-op when nothing is missing.
15
+ */
16
+ function isBrowserInstalled(name, env) {
17
+ if (env['PLAYWRIGHT_BROWSERS_PATH'] !== process.env['PLAYWRIGHT_BROWSERS_PATH'])
18
+ return undefined;
19
+ try {
20
+ return existsSync(browserType(name).executablePath());
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ /** Resolves the `playwright` CLI entry point relative to this package. */
27
+ function playwrightCliPath() {
28
+ const require = createRequire(import.meta.url);
29
+ return path.join(path.dirname(require.resolve('playwright/package.json')), 'cli.js');
30
+ }
31
+ /**
32
+ * Ensures the given Playwright browsers are installed, downloading any
33
+ * missing ones via `playwright install`. Called from the engine's `prepare`,
34
+ * once per run before any worker starts, so a download is never charged
35
+ * against a launch timeout and never runs once per worker. Concurrent
36
+ * installs (two runs at once) are still safe: the Playwright CLI serializes
37
+ * them with a registry lock.
38
+ */
39
+ export async function ensureBrowsersInstalled(names, options = {}) {
40
+ const env = options.env ?? process.env;
41
+ const isInstalled = options.isInstalled ?? ((name) => isBrowserInstalled(name, env));
42
+ const verdicts = new Map([...new Set(names)].map((name) => [name, isInstalled(name)]));
43
+ const missing = [...verdicts.keys()].filter((name) => verdicts.get(name) !== true);
44
+ if (missing.length === 0)
45
+ return;
46
+ // The headline is only honest when every listed browser is known to be
47
+ // absent; when the verdict is the CLI's, its own output tells the story
48
+ // and says nothing when there is nothing to fetch.
49
+ const knownMissing = missing.every((name) => verdicts.get(name) === false);
50
+ const log = options.log ?? ((line) => process.stderr.write(`${line}\n`));
51
+ if (knownMissing)
52
+ log(`Downloading missing Playwright browsers (first run): ${missing.join(', ')}...`);
53
+ const install = options.install ?? runPlaywrightInstall;
54
+ await install(missing, { log, signal: options.signal, env });
55
+ if (knownMissing)
56
+ log('Browser download complete.');
57
+ }
58
+ /**
59
+ * Forwards a child's stdout or stderr to `log` one complete line at a time.
60
+ * The Playwright CLI redraws its progress bar with carriage returns when it
61
+ * has a terminal; with a pipe it prints whole lines, but the splitter accepts
62
+ * both so no partial redraw ever reaches the reporter.
63
+ */
64
+ function forwardLines(stream, log) {
65
+ let pending = '';
66
+ const flush = (text) => {
67
+ for (const line of text.split(/\r\n|\n|\r/)) {
68
+ const trimmed = line.trimEnd();
69
+ if (trimmed !== '')
70
+ log(trimmed);
71
+ }
72
+ };
73
+ stream.setEncoding('utf8');
74
+ stream.on('data', (chunk) => {
75
+ pending += chunk;
76
+ const cut = Math.max(pending.lastIndexOf('\n'), pending.lastIndexOf('\r'));
77
+ if (cut === -1)
78
+ return;
79
+ flush(pending.slice(0, cut + 1));
80
+ pending = pending.slice(cut + 1);
81
+ });
82
+ stream.on('end', () => flush(pending));
83
+ }
84
+ /** Spawns `node <playwright>/cli.js install <names>`, narrating its output through `log`. */
85
+ function runPlaywrightInstall(names, { log, signal, env }) {
86
+ return new Promise((resolve, reject) => {
87
+ if (signal?.aborted === true) {
88
+ reject(new EngineError('CANCELLED', 'browser install cancelled', { retryable: false }));
89
+ return;
90
+ }
91
+ const child = spawn(process.execPath, [playwrightCliPath(), 'install', ...names], {
92
+ stdio: ['ignore', 'pipe', 'pipe'],
93
+ env,
94
+ });
95
+ forwardLines(child.stdout, log);
96
+ forwardLines(child.stderr, log);
97
+ const onAbort = () => {
98
+ child.kill();
99
+ reject(new EngineError('CANCELLED', 'browser install cancelled', { retryable: false }));
100
+ };
101
+ signal?.addEventListener('abort', onAbort, { once: true });
102
+ child.on('exit', () => signal?.removeEventListener('abort', onAbort));
103
+ child.on('error', (cause) => {
104
+ reject(new InfrastructureError('BROWSER_INSTALL_FAILED', `failed to run playwright install: ${cause.message}`, {
105
+ cause,
106
+ }));
107
+ });
108
+ child.on('exit', (code) => {
109
+ if (code === 0) {
110
+ resolve();
111
+ return;
112
+ }
113
+ reject(new InfrastructureError('BROWSER_INSTALL_FAILED', `playwright install ${names.join(' ')} exited with code ${String(code)}; run "npx playwright install ${names.join(' ')}" manually`));
114
+ });
115
+ });
116
+ }
117
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /** LocatorExpression -> Playwright locator projection. */
2
+ import type { Locator as PwLocator, Page } from 'playwright';
3
+ import { type LocatorExpression, type TextPattern } from 'e2e/engine';
4
+ /** One positional step applied after display-value filtering. */
5
+ export type PositionalStep = 'first' | 'last' | number;
6
+ type PwFilterOptions = NonNullable<Parameters<PwLocator['filter']>[0]>;
7
+ /**
8
+ * One step a display-value projection applies after its candidates are
9
+ * value-filtered, in expression order: a position among the matches, or a
10
+ * per-element filter that came after a position and so could not compose onto
11
+ * the candidate locator.
12
+ */
13
+ export type PostStep = {
14
+ readonly kind: 'index';
15
+ readonly index: PositionalStep;
16
+ } | {
17
+ readonly kind: 'filter';
18
+ readonly options: PwFilterOptions;
19
+ };
20
+ export interface ProjectedLocator {
21
+ /**
22
+ * The Playwright locator to resolve. For a display-value query this is the
23
+ * candidate set (every form control in scope), not the matches: Playwright
24
+ * has no selector for a control's current value, so the value predicate can
25
+ * only run after the candidates are read.
26
+ */
27
+ readonly locator: PwLocator;
28
+ /** Non-null when the terminal query filters by display value. */
29
+ readonly displayValue: TextPattern | null;
30
+ /**
31
+ * Non-null when the terminal query is an exact label query: `locator` holds
32
+ * every labelable control in scope and the surface keeps those with an
33
+ * associated label (an `aria-label`, an `aria-labelledby` target, or a
34
+ * `<label>`) whose accessible-name text equals the pattern. Playwright's own
35
+ * `getByLabel` reads a label's full text, aria-hidden included, so a
36
+ * required-field marker made `getByLabel('Display name')` miss
37
+ * `Display name*`; the engine's reader drops such text.
38
+ */
39
+ readonly name: TextPattern | null;
40
+ /**
41
+ * The Playwright locator to compose with as a scope or `has` filter, for a
42
+ * projection whose own predicate lives outside Playwright's chain. An exact
43
+ * label query composes through Playwright's substring label match, which
44
+ * accepts every control the predicate would and some it would not; that is
45
+ * the one place the predicate is approximated. Null for a display-value
46
+ * projection, which has no such equivalent and is rejected instead.
47
+ */
48
+ readonly composable: PwLocator | null;
49
+ /**
50
+ * Steps to apply to the value-filtered matches, innermost first. Always
51
+ * empty when `displayValue` is null, because the projection then composes
52
+ * positions and filters natively onto the locator.
53
+ */
54
+ readonly steps: readonly PostStep[];
55
+ /**
56
+ * True when the terminal query keeps only nodes whose `hidden` state is
57
+ * false. The surface applies it to the batch read before the display-value
58
+ * predicate and any post step, so a position is taken among shown matches.
59
+ */
60
+ readonly visible: boolean;
61
+ }
62
+ /** Projects an expression onto the page; `testIdAttribute` is what a `testId` query reads. */
63
+ export declare function projectExpression(page: Page, expression: LocatorExpression, testIdAttribute: string): ProjectedLocator;
64
+ /**
65
+ * Applies post steps, innermost first, to an ordered list of matches. `nth`
66
+ * past the end selects nothing, matching Playwright's `nth` on a locator with
67
+ * too few matches. A filter step keeps the matches `passesFilter` accepts;
68
+ * it runs only on the matches that survived the steps before it.
69
+ */
70
+ export declare function applyPostSteps<T>(matches: readonly T[], steps: readonly PostStep[], passesFilter: (match: T, options: PwFilterOptions) => Promise<boolean>): Promise<readonly T[]>;
71
+ /** Returns every frame selector along an expression, outermost first. */
72
+ export declare function frameSelectors(expression: LocatorExpression): string[];
73
+ export {};
74
+ //# sourceMappingURL=locators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locators.d.ts","sourceRoot":"","sources":["../src/locators.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,KAAK,EAAgB,OAAO,IAAI,SAAS,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAe,KAAK,iBAAiB,EAAsB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAiFvG,iEAAiE;AACjE,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvD,KAAK,eAAe,GAAG,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;CAAE,CAAC;AAyBnE,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1C;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,GAAG,IAAI,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAsGD,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,iBAAiB,EAC7B,eAAe,EAAE,MAAM,GACtB,gBAAgB,CAElB;AAkBD;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,YAAY,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,GACrE,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAiBvB;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,UAAU,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAYtE"}
@@ -0,0 +1,260 @@
1
+ /** LocatorExpression -> Playwright locator projection. */
2
+ import { EngineError } from 'e2e/engine';
3
+ function patternToPw(pattern) {
4
+ if (pattern.kind === 'regexp')
5
+ return new RegExp(pattern.source, pattern.flags);
6
+ return pattern.value;
7
+ }
8
+ function patternExact(pattern) {
9
+ return pattern.kind === 'string' ? pattern.exact : false;
10
+ }
11
+ /**
12
+ * The selector `getByTestId` compiles to, with the project's attribute in
13
+ * place of Playwright's process-global one (`selectors.setTestIdAttribute`
14
+ * would leak one engine's attribute into every other engine of the process).
15
+ * The value is encoded as Playwright's `escapeForAttributeSelector` encodes it:
16
+ * a string is an exact, case-sensitive match; a RegExp is passed as written.
17
+ */
18
+ function testIdSelector(attribute, pattern) {
19
+ const name = attribute.includes(',') ? JSON.stringify(attribute) : attribute;
20
+ const value = pattern.kind === 'regexp'
21
+ ? escapeRegexForSelector(new RegExp(pattern.source, pattern.flags))
22
+ : `"${pattern.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"s`;
23
+ return `internal:testid=[${name}=${value}]`;
24
+ }
25
+ /** A RegExp written into a Playwright selector: quotes and `>>` escaped unless the flags forbid it. */
26
+ function escapeRegexForSelector(re) {
27
+ if (/[uv]/.test(re.flags))
28
+ return String(re);
29
+ return String(re)
30
+ .replace(/(^|[^\\])(\\\\)*(["'`])/g, '$1$2\\$3')
31
+ .replace(/>>/g, '\\>\\>');
32
+ }
33
+ /**
34
+ * The contract's role vocabulary spelled as the ARIA role the role selector
35
+ * knows, where the two differ: the tree reports an `img` as `image`, so an
36
+ * `image` query has to go back to `img` to match it.
37
+ */
38
+ const ARIA_ROLE_BY_CONTRACT_ROLE = { image: 'img' };
39
+ function queryToPw(scope, query, testIdAttribute) {
40
+ switch (query.kind) {
41
+ case 'role': {
42
+ if (query.value.kind !== 'string') {
43
+ throw new EngineError('ENGINE_FAILURE', 'role query value must be a string', {
44
+ retryable: false,
45
+ });
46
+ }
47
+ const options = {};
48
+ if (query.name !== undefined) {
49
+ options.name = patternToPw(query.name);
50
+ if (query.name.kind === 'string')
51
+ options.exact = query.name.exact;
52
+ }
53
+ const states = query.states ?? {};
54
+ if (states.checked !== undefined)
55
+ options.checked = states.checked;
56
+ if (states.disabled !== undefined)
57
+ options.disabled = states.disabled;
58
+ if (states.selected !== undefined)
59
+ options.selected = states.selected;
60
+ if (states.expanded !== undefined)
61
+ options.expanded = states.expanded;
62
+ if (states.pressed !== undefined)
63
+ options.pressed = states.pressed;
64
+ if (query.level !== undefined)
65
+ options.level = query.level;
66
+ const role = ARIA_ROLE_BY_CONTRACT_ROLE[query.value.value] ?? query.value.value;
67
+ return scope.getByRole(role, options);
68
+ }
69
+ case 'label':
70
+ return scope.getByLabel(patternToPw(query.value), { exact: patternExact(query.value) });
71
+ case 'placeholder':
72
+ return scope.getByPlaceholder(patternToPw(query.value), { exact: patternExact(query.value) });
73
+ case 'text':
74
+ return scope.getByText(patternToPw(query.value), { exact: patternExact(query.value) });
75
+ case 'displayValue':
76
+ // Candidate set; the surface filters by current value at locate time.
77
+ return scope.locator('input, textarea, select');
78
+ case 'testId':
79
+ return scope.locator(testIdSelector(testIdAttribute, query.value));
80
+ }
81
+ }
82
+ /**
83
+ * Self-selector for the part of the semantic `hidden` state Playwright's own
84
+ * visibility filter does not read: `aria-hidden` on the element itself.
85
+ */
86
+ const NOT_ARIA_HIDDEN = ':scope:not([aria-hidden="true"])';
87
+ /**
88
+ * A `visible` query narrows its candidates inside the selector, before any
89
+ * enclosing scope, filter, or index runs: Playwright's visibility predicate
90
+ * (layout box, `display`, `visibility`) plus the `aria-hidden` check the
91
+ * semantic `hidden` state also makes. An indexed, filtered, or scoping visible
92
+ * query therefore never selects or retains a node that state calls hidden.
93
+ * The surface additionally holds a terminal query to the batch-read `hidden`
94
+ * state, so a direct query agrees with `toBeVisible()` even at the margin
95
+ * where the two predicates differ (a zero-size element with a layout rect is
96
+ * hidden to Playwright and shown to the semantic read).
97
+ */
98
+ function visibleQueryToPw(scope, query, testIdAttribute) {
99
+ const located = queryToPw(scope, query, testIdAttribute);
100
+ if (query.visible !== true)
101
+ return located;
102
+ return located.filter({ visible: true }).locator(NOT_ARIA_HIDDEN);
103
+ }
104
+ /**
105
+ * Every control `getByLabel` can name: labelable form controls plus anything
106
+ * carrying its own label attributes. The candidates of an exact label query;
107
+ * the surface keeps those whose labels match.
108
+ */
109
+ const LABELABLE_SELECTOR = 'button, input:not([type="hidden"]), textarea, select, meter, output, progress, [aria-label], [aria-labelledby]';
110
+ function positioned(locator, index) {
111
+ return index === 'first' ? locator.first() : index === 'last' ? locator.last() : locator.nth(index);
112
+ }
113
+ const DISPLAY_VALUE_COMPOSITION_MESSAGE = 'displayValue queries cannot scope child queries or serve as a has-filter in this engine';
114
+ /**
115
+ * Projects a complete immutable expression onto a Playwright locator within
116
+ * one scope. Frame cardinality is validated separately by the surface.
117
+ *
118
+ * A display-value query resolves to a candidate locator plus a value predicate
119
+ * the surface applies once the candidates are read. Per-element filters
120
+ * (`filter({ hasText, has })`) commute with that predicate, so they compose
121
+ * onto the candidate locator as for any other query. Positional selection does
122
+ * not commute (positions are relative to the value-filtered matches), so it is
123
+ * recorded as a step and applied after filtering; a filter that follows a
124
+ * position is recorded the same way and checked on the selected element. Two
125
+ * compositions need the predicate inside Playwright's own chain and stay
126
+ * unsupported: a display-value query as the scope of a child query, and as a
127
+ * `has` filter.
128
+ */
129
+ function project(scope, expression, testIdAttribute) {
130
+ switch (expression.kind) {
131
+ case 'query': {
132
+ const inner = expression.scope === undefined
133
+ ? scope
134
+ : requireComposable(project(scope, expression.scope, testIdAttribute));
135
+ const { query } = expression;
136
+ const exactLabel = query.kind === 'label' && patternExact(query.value);
137
+ const locator = exactLabel
138
+ ? inner.locator(LABELABLE_SELECTOR)
139
+ : visibleQueryToPw(inner, query, testIdAttribute);
140
+ return {
141
+ locator,
142
+ displayValue: query.kind === 'displayValue' ? query.value : null,
143
+ name: exactLabel ? query.value : null,
144
+ composable: exactLabel ? inner.getByLabel(patternToPw(query.value), { exact: false }) : null,
145
+ steps: [],
146
+ visible: query.visible === true,
147
+ };
148
+ }
149
+ case 'filter': {
150
+ const source = project(scope, expression.source, testIdAttribute);
151
+ const options = {};
152
+ if (expression.hasText !== undefined)
153
+ options.hasText = patternToPw(expression.hasText);
154
+ if (expression.has !== undefined) {
155
+ options.has = requireComposable(project(scope, expression.has, testIdAttribute));
156
+ }
157
+ if (source.steps.length > 0) {
158
+ return { ...source, steps: [...source.steps, { kind: 'filter', options }] };
159
+ }
160
+ return {
161
+ ...source,
162
+ locator: source.locator.filter(options),
163
+ composable: source.composable === null ? null : source.composable.filter(options),
164
+ steps: [],
165
+ };
166
+ }
167
+ case 'index': {
168
+ const source = project(scope, expression.source, testIdAttribute);
169
+ if (source.displayValue !== null || source.name !== null) {
170
+ return {
171
+ ...source,
172
+ composable: source.composable === null ? null : positioned(source.composable, expression.index),
173
+ steps: [...source.steps, { kind: 'index', index: expression.index }],
174
+ };
175
+ }
176
+ return {
177
+ locator: positioned(source.locator, expression.index),
178
+ displayValue: null,
179
+ name: null,
180
+ composable: null,
181
+ steps: [],
182
+ visible: false,
183
+ };
184
+ }
185
+ case 'selector':
186
+ return {
187
+ locator: scope.locator(expression.selector),
188
+ displayValue: null,
189
+ name: null,
190
+ composable: null,
191
+ steps: [],
192
+ visible: false,
193
+ };
194
+ case 'frame':
195
+ return project(scope.frameLocator(expression.selector), expression.source, testIdAttribute);
196
+ }
197
+ }
198
+ /** Projects an expression onto the page; `testIdAttribute` is what a `testId` query reads. */
199
+ export function projectExpression(page, expression, testIdAttribute) {
200
+ return project(page, expression, testIdAttribute);
201
+ }
202
+ /**
203
+ * Returns the locator of a projection that must participate in Playwright's
204
+ * own locator chain: a scope for child queries or a `has` target. A
205
+ * display-value projection cannot, because its value predicate lives outside
206
+ * that chain.
207
+ */
208
+ function requireComposable(projected) {
209
+ if (projected.composable !== null)
210
+ return projected.composable;
211
+ if (projected.displayValue !== null) {
212
+ throw new EngineError('UNSUPPORTED_CAPABILITY', DISPLAY_VALUE_COMPOSITION_MESSAGE, {
213
+ retryable: false,
214
+ });
215
+ }
216
+ return projected.locator;
217
+ }
218
+ /**
219
+ * Applies post steps, innermost first, to an ordered list of matches. `nth`
220
+ * past the end selects nothing, matching Playwright's `nth` on a locator with
221
+ * too few matches. A filter step keeps the matches `passesFilter` accepts;
222
+ * it runs only on the matches that survived the steps before it.
223
+ */
224
+ export async function applyPostSteps(matches, steps, passesFilter) {
225
+ let selected = matches;
226
+ for (const step of steps) {
227
+ if (step.kind === 'index') {
228
+ const { index } = step;
229
+ if (index === 'first')
230
+ selected = selected.slice(0, 1);
231
+ else if (index === 'last')
232
+ selected = selected.slice(-1);
233
+ else
234
+ selected = index < selected.length ? [selected[index]] : [];
235
+ continue;
236
+ }
237
+ const kept = [];
238
+ for (const match of selected) {
239
+ if (await passesFilter(match, step.options))
240
+ kept.push(match);
241
+ }
242
+ selected = kept;
243
+ }
244
+ return selected;
245
+ }
246
+ /** Returns every frame selector along an expression, outermost first. */
247
+ export function frameSelectors(expression) {
248
+ switch (expression.kind) {
249
+ case 'query':
250
+ return expression.scope === undefined ? [] : frameSelectors(expression.scope);
251
+ case 'filter':
252
+ case 'index':
253
+ return frameSelectors(expression.source);
254
+ case 'selector':
255
+ return [];
256
+ case 'frame':
257
+ return [expression.selector, ...frameSelectors(expression.source)];
258
+ }
259
+ }
260
+ //# 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, DEFAULT_VIEWPORT } 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 = page.viewportSize() ?? DEFAULT_VIEWPORT;
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 = page.viewportSize() ?? DEFAULT_VIEWPORT;
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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"}