@flighthq/tool-capture 0.2.1-next.444.a313478 → 0.2.1-next.448.afbdd31
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/README.md +87 -0
- package/dist/baselineStore.d.ts.map +1 -1
- package/dist/baselineStore.js +7 -21
- package/dist/baselineStore.js.map +1 -1
- package/dist/bin.js +187 -27
- package/dist/bin.js.map +1 -1
- package/dist/captureBrowser.d.ts.map +1 -1
- package/dist/captureBrowser.js +8 -0
- package/dist/captureBrowser.js.map +1 -1
- package/dist/captureEntries.d.ts +1 -0
- package/dist/captureEntries.d.ts.map +1 -1
- package/dist/captureEntries.js +1 -1
- package/dist/captureEntries.js.map +1 -1
- package/dist/captureEntry.d.ts +4 -4
- package/dist/captureEntry.d.ts.map +1 -1
- package/dist/captureEntry.js +22 -8
- package/dist/captureEntry.js.map +1 -1
- package/dist/captureFormat.js +1 -1
- package/dist/captureFormat.js.map +1 -1
- package/dist/captureManifest.d.ts +12 -0
- package/dist/captureManifest.d.ts.map +1 -0
- package/dist/captureManifest.js +44 -0
- package/dist/captureManifest.js.map +1 -0
- package/dist/captureRenderTarget.d.ts +1 -2
- package/dist/captureRenderTarget.d.ts.map +1 -1
- package/dist/captureRenderTarget.js.map +1 -1
- package/dist/captureServer.d.ts +3 -1
- package/dist/captureServer.d.ts.map +1 -1
- package/dist/captureServer.js +11 -2
- package/dist/captureServer.js.map +1 -1
- package/dist/captureSuite.d.ts +32 -0
- package/dist/captureSuite.d.ts.map +1 -0
- package/dist/captureSuite.js +103 -0
- package/dist/captureSuite.js.map +1 -0
- package/dist/captureValidation.d.ts +35 -0
- package/dist/captureValidation.d.ts.map +1 -0
- package/dist/captureValidation.js +363 -0
- package/dist/captureValidation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/referenceCapture.d.ts.map +1 -1
- package/dist/referenceCapture.js +6 -7
- package/dist/referenceCapture.js.map +1 -1
- package/package.json +6 -5
- package/src/captureEntries.test.ts +7 -0
- package/src/captureManifest.test.ts +59 -0
- package/src/captureServer.test.ts +19 -1
- package/src/captureSuite.test.ts +11 -0
- package/src/captureValidation.test.ts +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# `@flighthq/tool-capture`
|
|
2
|
+
|
|
3
|
+
Deterministic browser capture and reporting for canvas, DOM, WebGL, and WebGPU pages.
|
|
4
|
+
|
|
5
|
+
## Capture a suite
|
|
6
|
+
|
|
7
|
+
Add a `tool-capture.json` manifest to a package:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"subject": "my-app",
|
|
12
|
+
"entries": [
|
|
13
|
+
{
|
|
14
|
+
"name": "home",
|
|
15
|
+
"renderers": ["canvas", "webgl"],
|
|
16
|
+
"routes": {
|
|
17
|
+
"canvas": "pages/home/canvas/",
|
|
18
|
+
"webgl": "pages/home/webgl/"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Then capture either an existing server or an already-built directory:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
tool-capture capture --url http://localhost:5173
|
|
29
|
+
tool-capture capture --dir dist
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Each target writes `screenshot.png`, `logs.jsonl`, and `status.json` beneath `.artifacts/<subject>/<entry>/<renderer>/`. Common reporting controls are built in:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
tool-capture capture --dir dist --frames 1 --fail-on-error
|
|
36
|
+
tool-capture capture --dir dist --update-baseline
|
|
37
|
+
tool-capture capture --dir dist --fail-on-changed
|
|
38
|
+
tool-capture capture --dir dist --renderer webgl,webgpu --parallel 4
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Use `runCaptureSuite` when entries or server lifecycle are generated programmatically. It owns browser setup and teardown, deterministic frame synchronization, parallel or sequential scheduling, baseline policy, interruption, summaries, and the final verdict.
|
|
42
|
+
|
|
43
|
+
## Validate fingerprints
|
|
44
|
+
|
|
45
|
+
The same manifest and server options drive the tolerant parity/regression pass when pages publish a render fingerprint:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
window.__ftVerification = {
|
|
49
|
+
render: 'webgl',
|
|
50
|
+
coverage: 1,
|
|
51
|
+
fingerprint: '1:25acc0',
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Fingerprints use the `<grid-size>:<rgb-hex>` format produced by `formatSurfaceFingerprint`. Once the page exposes a non-null fingerprint, validation is turn-key:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
tool-capture validate --dir dist --no-regression
|
|
59
|
+
tool-capture validate --dir dist --no-parity
|
|
60
|
+
tool-capture validate --dir dist --update-fingerprints
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Optional manifest policy keeps intentional exceptions beside the suite:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"subject": "my-app",
|
|
68
|
+
"entries": [],
|
|
69
|
+
"validation": {
|
|
70
|
+
"fingerprintSkip": ["audio-only"],
|
|
71
|
+
"paritySkip": {
|
|
72
|
+
"video": "all",
|
|
73
|
+
"approximate-effect": ["canvas"]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`runCaptureValidation` exposes the same validation lifecycle programmatically. Comparison tolerances and baseline formats come from `@flighthq/capture`; `tool-capture` owns browser execution and reporting.
|
|
80
|
+
|
|
81
|
+
## Observe one page
|
|
82
|
+
|
|
83
|
+
`observe` is the zero-integration eyes primitive. It always emits the best available screenshot and diagnostics rather than enforcing a suite gate:
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
tool-capture observe http://localhost:5173/example --out capture
|
|
87
|
+
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baselineStore.d.ts","sourceRoot":"","sources":["../src/baselineStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"baselineStore.d.ts","sourceRoot":"","sources":["../src/baselineStore.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,QAAQ,CAAC;AASrD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhF;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,GACnB,MAAM,GAAG,IAAI,CAEf;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,MAAM,GACZ,IAAI,CAKN"}
|
package/dist/baselineStore.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Per-test committed baseline store: one JSON file per test at <subject-root>/baselines/<name>.json,
|
|
2
2
|
// holding every column's values, e.g. { "canvas": { "fingerprint": "…", "sha256": "…" }, "flight:webgl": {…} }.
|
|
3
|
-
// captureEntry writes each column's `sha256` (screenshot hash);
|
|
3
|
+
// captureEntry writes each column's `sha256` (screenshot hash); captureValidation writes its `fingerprint`
|
|
4
4
|
// (coarse render fingerprint). Both read-merge-write so they preserve each other's fields and the other
|
|
5
5
|
// columns. Output is prettier-compatible (sorted keys, 2-space, trailing newline) so it never churns the
|
|
6
6
|
// format gate. Replaces the old tools/baselines/<subject>/<name>/<renderer>/{fingerprint.txt,baseline.sha256}.
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
8
8
|
import { dirname, join } from 'node:path';
|
|
9
|
+
import { createCaptureBaseline, formatCaptureBaseline, getCaptureBaselineField, parseCaptureBaseline, setCaptureBaselineField, } from '@flighthq/capture';
|
|
9
10
|
// Per-subject baseline root: baselines colocate with their suite (functional/examples are
|
|
10
11
|
// top-level). One JSON file per test under the root's baselines/ dir.
|
|
11
12
|
const BASELINE_ROOTS = {
|
|
@@ -17,38 +18,23 @@ export function baselinePath(root, subject, name) {
|
|
|
17
18
|
return join(root, base, 'baselines', `${name}.json`);
|
|
18
19
|
}
|
|
19
20
|
export function getBaselineField(root, subject, name, column, field) {
|
|
20
|
-
return readBaseline(baselinePath(root, subject, name))
|
|
21
|
+
return getCaptureBaselineField(readBaseline(baselinePath(root, subject, name)), column, field);
|
|
21
22
|
}
|
|
22
23
|
export function setBaselineField(root, subject, name, column, field, value) {
|
|
23
24
|
const path = baselinePath(root, subject, name);
|
|
24
25
|
const data = readBaseline(path);
|
|
25
|
-
(data
|
|
26
|
+
setCaptureBaselineField(data, column, field, value);
|
|
26
27
|
writeBaseline(path, data);
|
|
27
28
|
}
|
|
28
29
|
function readBaseline(path) {
|
|
29
30
|
if (!existsSync(path))
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
return JSON.parse(readFileSync(path, 'utf8'));
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return {};
|
|
36
|
-
}
|
|
31
|
+
return createCaptureBaseline();
|
|
32
|
+
return parseCaptureBaseline(readFileSync(path, 'utf8')) ?? createCaptureBaseline();
|
|
37
33
|
}
|
|
38
34
|
// Stable, prettier-compatible serialisation: columns and fields in sorted order so a re-baseline of one
|
|
39
35
|
// column produces a minimal diff and the format gate stays green.
|
|
40
36
|
function writeBaseline(path, data) {
|
|
41
37
|
mkdirSync(dirname(path), { recursive: true });
|
|
42
|
-
|
|
43
|
-
for (const column of Object.keys(data).sort()) {
|
|
44
|
-
const entry = data[column];
|
|
45
|
-
const out = {};
|
|
46
|
-
if (entry.fingerprint !== undefined)
|
|
47
|
-
out.fingerprint = entry.fingerprint;
|
|
48
|
-
if (entry.sha256 !== undefined)
|
|
49
|
-
out.sha256 = entry.sha256;
|
|
50
|
-
sorted[column] = out;
|
|
51
|
-
}
|
|
52
|
-
writeFileSync(path, JSON.stringify(sorted, null, 2) + '\n');
|
|
38
|
+
writeFileSync(path, formatCaptureBaseline(data));
|
|
53
39
|
}
|
|
54
40
|
//# sourceMappingURL=baselineStore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baselineStore.js","sourceRoot":"","sources":["../src/baselineStore.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,gHAAgH;AAChH,
|
|
1
|
+
{"version":3,"file":"baselineStore.js","sourceRoot":"","sources":["../src/baselineStore.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,gHAAgH;AAChH,2GAA2G;AAC3G,wGAAwG;AACxG,yGAAyG;AACzG,+GAA+G;AAC/G,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAK3B,0FAA0F;AAC1F,sEAAsE;AACtE,MAAM,cAAc,GAA2B;IAC7C,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY;IACtE,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC;IAChD,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAe,EACf,IAAY,EACZ,MAAc,EACd,KAAoB;IAEpB,OAAO,uBAAuB,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACjG,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAe,EACf,IAAY,EACZ,MAAc,EACd,KAAoB,EACpB,KAAa;IAEb,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACpD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,qBAAqB,EAAE,CAAC;IACtD,OAAO,oBAAoB,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,qBAAqB,EAAE,CAAC;AACrF,CAAC;AAED,wGAAwG;AACxG,kEAAkE;AAClE,SAAS,aAAa,CAAC,IAAY,EAAE,IAA+B;IAClE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC"}
|
package/dist/bin.js
CHANGED
|
@@ -1,38 +1,198 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
// in the consumer; a repo just adds `"capture:observe": "tool-capture observe"` and points it at a URL.
|
|
2
|
+
// Turn-key capture CLI:
|
|
3
|
+
// - observe <url>: one arbitrary page, zero integration, always emit eyes + diagnostics.
|
|
4
|
+
// - capture: a full entry × renderer report from a JSON manifest or Flight's built-in suites.
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
7
6
|
import { resolve } from 'node:path';
|
|
7
|
+
import { discoverEntries } from './captureEntries.js';
|
|
8
8
|
import { captureUrl } from './captureEntry.js';
|
|
9
|
-
|
|
9
|
+
import { isBrowserClosedError } from './captureInterrupt.js';
|
|
10
|
+
import { readCaptureManifest } from './captureManifest.js';
|
|
11
|
+
import { resolveCaptureDirectoryServer, resolveServer, resolveStaticServer } from './captureServer.js';
|
|
12
|
+
import { runCaptureSuite } from './captureSuite.js';
|
|
13
|
+
import { runCaptureValidation } from './captureValidation.js';
|
|
14
|
+
const USAGE = `usage:
|
|
15
|
+
tool-capture observe <url> [--out <dir>] [--wait <ms>] [--frames <n>]
|
|
16
|
+
tool-capture capture [--manifest <file>] (--url <url> | --dir <built-dir>) [options]
|
|
17
|
+
tool-capture capture --tool <examples|functional> [options]
|
|
18
|
+
tool-capture validate [--manifest <file>] (--url <url> | --dir <built-dir>) [options]
|
|
19
|
+
tool-capture validate --tool <examples|functional> [options]
|
|
20
|
+
|
|
21
|
+
capture options:
|
|
22
|
+
--filter <name> --renderer <ids> --out <dir> --wait <ms> --frames <n>
|
|
23
|
+
--parallel <n> --sequential --dev --build --update-baseline --fail-on-changed
|
|
24
|
+
--fail-on-error --verify --no-verify --observe
|
|
25
|
+
|
|
26
|
+
validation options:
|
|
27
|
+
--report --update-fingerprints --no-regression --no-parity
|
|
28
|
+
--stability-epsilon <n> --regression-tolerance <n> --parity-tolerance <n>
|
|
29
|
+
|
|
30
|
+
Manifest: { "subject": "app", "entries": [{ "name": "home", "renderers": ["webgl"],
|
|
31
|
+
"routes": { "webgl": "pages/home/" } }] }`;
|
|
10
32
|
function flag(argv, key) {
|
|
11
|
-
const
|
|
12
|
-
|
|
33
|
+
const equals = argv.find((arg) => arg.startsWith(`--${key}=`));
|
|
34
|
+
if (equals !== undefined)
|
|
35
|
+
return equals.slice(key.length + 3);
|
|
36
|
+
const index = argv.indexOf(`--${key}`);
|
|
37
|
+
return index >= 0 && argv[index + 1] !== undefined ? argv[index + 1] : undefined;
|
|
38
|
+
}
|
|
39
|
+
function hasFlag(argv, key) {
|
|
40
|
+
return argv.includes(`--${key}`);
|
|
41
|
+
}
|
|
42
|
+
async function resolveCaptureCliSuite(argv) {
|
|
43
|
+
const root = resolve(flag(argv, 'root') ?? process.cwd());
|
|
44
|
+
const manifestPath = flag(argv, 'manifest');
|
|
45
|
+
const toolName = flag(argv, 'tool');
|
|
46
|
+
let manifest = null;
|
|
47
|
+
let subject;
|
|
48
|
+
let entries;
|
|
49
|
+
if (manifestPath !== undefined) {
|
|
50
|
+
manifest = readCaptureManifest(resolve(root, manifestPath));
|
|
51
|
+
subject = flag(argv, 'subject') ?? manifest.subject;
|
|
52
|
+
entries = manifest.entries;
|
|
53
|
+
}
|
|
54
|
+
else if (toolName === 'examples' || toolName === 'functional') {
|
|
55
|
+
subject = flag(argv, 'subject') ?? toolName;
|
|
56
|
+
entries = discoverEntries(toolName, root);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const conventionalManifest = resolve(root, 'tool-capture.json');
|
|
60
|
+
if (!existsSync(conventionalManifest))
|
|
61
|
+
throw new Error(`capture/validate requires --manifest or --tool\n${USAGE}`);
|
|
62
|
+
manifest = readCaptureManifest(conventionalManifest);
|
|
63
|
+
subject = flag(argv, 'subject') ?? manifest.subject;
|
|
64
|
+
entries = manifest.entries;
|
|
65
|
+
}
|
|
66
|
+
const externalUrl = flag(argv, 'url');
|
|
67
|
+
const directory = flag(argv, 'dir');
|
|
68
|
+
let server;
|
|
69
|
+
if (externalUrl !== undefined) {
|
|
70
|
+
console.log(`Using server at ${externalUrl}\n`);
|
|
71
|
+
server = await resolveServer({ root, externalUrl });
|
|
72
|
+
}
|
|
73
|
+
else if (directory !== undefined) {
|
|
74
|
+
console.log(`Serving ${resolve(root, directory)}…`);
|
|
75
|
+
server = await resolveCaptureDirectoryServer(resolve(root, directory));
|
|
76
|
+
console.log(`Ready at ${server.url}\n`);
|
|
77
|
+
}
|
|
78
|
+
else if (toolName === 'examples' || toolName === 'functional') {
|
|
79
|
+
if (hasFlag(argv, 'dev'))
|
|
80
|
+
console.log(`Starting ${toolName} dev server…`);
|
|
81
|
+
else if (hasFlag(argv, 'build'))
|
|
82
|
+
console.log(`Building and serving ${toolName} dist…`);
|
|
83
|
+
else
|
|
84
|
+
console.log(`Serving ${toolName} dist (use --build to rebuild, --dev for Vite)…`);
|
|
85
|
+
server = hasFlag(argv, 'dev')
|
|
86
|
+
? await resolveServer({ tool: toolName, root })
|
|
87
|
+
: await resolveStaticServer({ tool: toolName, root, forceBuild: hasFlag(argv, 'build') });
|
|
88
|
+
console.log(`Ready at ${server.url}\n`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw new Error(`capture/validate requires --url or --dir for manifest suites\n${USAGE}`);
|
|
92
|
+
}
|
|
93
|
+
return { entries, manifest, root, server, subject };
|
|
94
|
+
}
|
|
95
|
+
async function capture(argv) {
|
|
96
|
+
const { subject, entries, server, root } = await resolveCaptureCliSuite(argv);
|
|
97
|
+
const frames = flag(argv, 'frames');
|
|
98
|
+
const parallel = flag(argv, 'parallel');
|
|
99
|
+
const result = await runCaptureSuite({
|
|
100
|
+
subject,
|
|
101
|
+
entries,
|
|
102
|
+
server,
|
|
103
|
+
root,
|
|
104
|
+
outBase: flag(argv, 'out') ?? '.artifacts',
|
|
105
|
+
filter: flag(argv, 'filter'),
|
|
106
|
+
rendererFilter: (flag(argv, 'renderer') ?? '').split(',').filter(Boolean),
|
|
107
|
+
extraWait: parseNonNegativeInteger(flag(argv, 'wait'), 0),
|
|
108
|
+
captureFrames: parseNonNegativeInteger(frames?.split(',')[0], 0),
|
|
109
|
+
workerCount: Math.max(1, parseNonNegativeInteger(parallel, 6)),
|
|
110
|
+
sequential: hasFlag(argv, 'sequential'),
|
|
111
|
+
updateBaseline: hasFlag(argv, 'update-baseline'),
|
|
112
|
+
failOnChanged: hasFlag(argv, 'fail-on-changed'),
|
|
113
|
+
failOnError: hasFlag(argv, 'fail-on-error'),
|
|
114
|
+
observe: hasFlag(argv, 'observe'),
|
|
115
|
+
verify: hasFlag(argv, 'verify') ? true : hasFlag(argv, 'no-verify') ? false : undefined,
|
|
116
|
+
});
|
|
117
|
+
if (result.aborted)
|
|
118
|
+
return 130;
|
|
119
|
+
return result.shouldFail ? 1 : 0;
|
|
120
|
+
}
|
|
121
|
+
async function validate(argv) {
|
|
122
|
+
const { subject, entries, server, root, manifest } = await resolveCaptureCliSuite(argv);
|
|
123
|
+
const result = await runCaptureValidation({
|
|
124
|
+
subject,
|
|
125
|
+
entries,
|
|
126
|
+
server,
|
|
127
|
+
root,
|
|
128
|
+
filter: flag(argv, 'filter'),
|
|
129
|
+
rendererFilter: (flag(argv, 'renderer') ?? '').split(',').filter(Boolean),
|
|
130
|
+
captureFrames: Math.max(1, parseNonNegativeInteger(flag(argv, 'frames'), 1)),
|
|
131
|
+
report: hasFlag(argv, 'report'),
|
|
132
|
+
updateFingerprints: hasFlag(argv, 'update-fingerprints'),
|
|
133
|
+
gateRegression: !hasFlag(argv, 'no-regression'),
|
|
134
|
+
gateParity: !hasFlag(argv, 'no-parity'),
|
|
135
|
+
stabilityEpsilon: parseNumber(flag(argv, 'stability-epsilon')),
|
|
136
|
+
regressionTolerance: parseNumber(flag(argv, 'regression-tolerance')),
|
|
137
|
+
parityTolerance: parseNumber(flag(argv, 'parity-tolerance')),
|
|
138
|
+
sequential: hasFlag(argv, 'sequential'),
|
|
139
|
+
workerCount: Math.max(1, parseNonNegativeInteger(flag(argv, 'parallel'), 6)),
|
|
140
|
+
fingerprintSkip: manifest?.validation?.fingerprintSkip ?? (manifest === null && subject === 'examples' ? ['playingsound'] : []),
|
|
141
|
+
paritySkip: manifest?.validation?.paritySkip ?? (manifest === null ? FLIGHT_PARITY_SKIP : {}),
|
|
142
|
+
});
|
|
143
|
+
if (result.aborted)
|
|
144
|
+
return 130;
|
|
145
|
+
return result.shouldFail ? 1 : 0;
|
|
13
146
|
}
|
|
14
147
|
async function main() {
|
|
15
|
-
const argv = process.argv.slice(2);
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
148
|
+
const [command, ...argv] = process.argv.slice(2);
|
|
149
|
+
if (command === 'observe') {
|
|
150
|
+
const url = argv[0];
|
|
151
|
+
if (url === undefined || url.startsWith('--'))
|
|
152
|
+
throw new Error(`observe requires a <url>\n${USAGE}`);
|
|
153
|
+
const outDir = resolve(flag(argv, 'out') ?? './capture');
|
|
154
|
+
const diagnostics = await captureUrl(url, {
|
|
155
|
+
outDir,
|
|
156
|
+
wait: parseNonNegativeInteger(flag(argv, 'wait'), 0),
|
|
157
|
+
captureFrames: parseNonNegativeInteger(flag(argv, 'frames'), 1) || 1,
|
|
158
|
+
});
|
|
159
|
+
console.log(`captured → ${resolve(outDir, 'screenshot.png')}`);
|
|
160
|
+
console.log(`observe ${JSON.stringify(diagnostics)}`);
|
|
161
|
+
process.exit(0);
|
|
162
|
+
}
|
|
163
|
+
if (command === 'capture')
|
|
164
|
+
process.exit(await capture(argv));
|
|
165
|
+
if (command === 'validate')
|
|
166
|
+
process.exit(await validate(argv));
|
|
167
|
+
console.error(USAGE);
|
|
168
|
+
process.exit(2);
|
|
169
|
+
}
|
|
170
|
+
function parseNonNegativeInteger(value, fallback) {
|
|
171
|
+
if (value === undefined)
|
|
172
|
+
return fallback;
|
|
173
|
+
const parsed = Number.parseInt(value, 10);
|
|
174
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
175
|
+
}
|
|
176
|
+
function parseNumber(value) {
|
|
177
|
+
if (value === undefined)
|
|
178
|
+
return undefined;
|
|
179
|
+
const parsed = Number.parseFloat(value);
|
|
180
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
34
181
|
}
|
|
182
|
+
const FLIGHT_PARITY_SKIP = {
|
|
183
|
+
playingvideo: 'all',
|
|
184
|
+
'effect-hue-saturation': ['canvas'],
|
|
185
|
+
'effect-lens-distortion': ['canvas'],
|
|
186
|
+
'effect-lens-flare': ['canvas'],
|
|
187
|
+
'effect-posterize': ['canvas'],
|
|
188
|
+
'effect-vignette': ['canvas'],
|
|
189
|
+
'effect-displacement': 'all',
|
|
190
|
+
'effect-god-rays': 'all',
|
|
191
|
+
'effect-screen-space-fog': 'all',
|
|
192
|
+
};
|
|
35
193
|
main().catch((err) => {
|
|
194
|
+
if (isBrowserClosedError(err))
|
|
195
|
+
process.exit(130);
|
|
36
196
|
console.error(err);
|
|
37
197
|
process.exit(1);
|
|
38
198
|
});
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureBrowser.d.ts","sourceRoot":"","sources":["../src/captureBrowser.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,wBAAsB,aAAa,CACjC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC5E,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"captureBrowser.d.ts","sourceRoot":"","sources":["../src/captureBrowser.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEhE,wBAAsB,aAAa,CACjC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC5E,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,CAgMxD"}
|
package/dist/captureBrowser.js
CHANGED
|
@@ -98,6 +98,14 @@ export async function launchBrowser(options = {}) {
|
|
|
98
98
|
window.requestAnimationFrame = (callback) => realRequestAnimationFrame((time) => {
|
|
99
99
|
if (flags.__captureFramesReached)
|
|
100
100
|
return; // halted: scene holds its last frame
|
|
101
|
+
// Harness/bootstrap scripts can request frames before the renderer has even created its
|
|
102
|
+
// canvas or registered a verification target. Those are not render frames: counting them can
|
|
103
|
+
// exhaust a small --frames value before an async application module starts, freezing its first
|
|
104
|
+
// real draw as a blank canvas. Let bootstrap callbacks run without advancing the capture count.
|
|
105
|
+
if (flags.__ftTarget === undefined && document.querySelector('canvas') === null) {
|
|
106
|
+
callback(time);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
101
109
|
if (count >= frames) {
|
|
102
110
|
const targetKind = flags.__ftTarget?.kind;
|
|
103
111
|
const gpuVerifying = verify && (targetKind === 'webgl' || targetKind === 'webgpu');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureBrowser.js","sourceRoot":"","sources":["../src/captureBrowser.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"captureBrowser.js","sourceRoot":"","sources":["../src/captureBrowser.ts"],"names":[],"mappings":"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"}
|
package/dist/captureEntries.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureEntries.d.ts","sourceRoot":"","sources":["../src/captureEntries.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,SAAS,+CAAgD,CAAC;AAIvE,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"captureEntries.d.ts","sourceRoot":"","sources":["../src/captureEntries.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,SAAS,+CAAgD,CAAC;AAIvE,MAAM,MAAM,IAAI,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAC;AAE3D,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IAGpB,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAI1C,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC;AASD,eAAO,MAAM,mBAAmB,QACgJ,CAAC;AAEjL,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAqBjE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI1F;AAID,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD"}
|
package/dist/captureEntries.js
CHANGED
|
@@ -9,7 +9,7 @@ export const RENDERERS = ['dom', 'canvas', 'webgl', 'webgpu'];
|
|
|
9
9
|
// null-fingerprint / page-error outcomes that may be skipped rather than failed — the gate verifies
|
|
10
10
|
// backends where they exist and stays green on machines without them. A real render bug still fails:
|
|
11
11
|
// a validation error (bad writeBuffer/copy) is logged before the device dies, and is matched first.
|
|
12
|
-
// Shared
|
|
12
|
+
// Shared by capture and validation so the smoke gate and the parity/regression gate agree on what counts
|
|
13
13
|
// as "unavailable".
|
|
14
14
|
export const BACKEND_UNAVAILABLE = /WebGPU adapter|WebGPU device|requestAdapter|requestDevice|GPUAdapter|WebGPU is not supported|external Instance reference no longer exists|device (was )?lost|device is lost/i;
|
|
15
15
|
export function discoverEntries(tool, root) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureEntries.js","sourceRoot":"","sources":["../src/captureEntries.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,uEAAuE;AAEvE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"captureEntries.js","sourceRoot":"","sources":["../src/captureEntries.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,uEAAuE;AAEvE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC;AAkBvE,oGAAoG;AACpG,+FAA+F;AAC/F,oGAAoG;AACpG,qGAAqG;AACrG,oGAAoG;AACpG,yGAAyG;AACzG,oBAAoB;AACpB,MAAM,CAAC,MAAM,mBAAmB,GAC9B,8KAA8K,CAAC;AAEjL,MAAM,UAAU,eAAe,CAAC,IAAU,EAAE,IAAY;IACtD,qGAAqG;IACrG,qDAAqD;IACrD,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IACpC,gGAAgG;IAChG,kEAAkE;IAClE,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,wBAAwB,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE/F,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAC7C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;SAC/E,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAC5C,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,eAAe,GAAI,SAA+B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACpE,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAChD,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;IAC9C,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAgB,EAAE,MAAyB;IAC/E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC9F,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,iFAAiF;AACjF,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/captureEntry.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BrowserContext } from '@playwright/test';
|
|
2
|
-
import type { Entry
|
|
2
|
+
import type { Entry } from './captureEntries.js';
|
|
3
3
|
export interface CaptureStatus {
|
|
4
4
|
state: 'ready' | 'error';
|
|
5
5
|
capturedAt: number;
|
|
@@ -45,7 +45,7 @@ export interface CaptureEntryOptions {
|
|
|
45
45
|
entry: Entry;
|
|
46
46
|
renderers: string[];
|
|
47
47
|
baseUrl: string;
|
|
48
|
-
tool:
|
|
48
|
+
tool: string;
|
|
49
49
|
outBase: string;
|
|
50
50
|
/** Repo root — committed baselines live at tests/<tool>/baselines/<name>.json. */
|
|
51
51
|
root: string;
|
|
@@ -96,7 +96,7 @@ export interface ParallelCaptureOptions {
|
|
|
96
96
|
entries: Entry[];
|
|
97
97
|
rendererFilter: string[];
|
|
98
98
|
baseUrl: string;
|
|
99
|
-
tool:
|
|
99
|
+
tool: string;
|
|
100
100
|
outBase: string;
|
|
101
101
|
root: string;
|
|
102
102
|
updateBaseline?: boolean;
|
|
@@ -143,5 +143,5 @@ export interface CaptureUrlOptions {
|
|
|
143
143
|
/** Frame-halt minimum (see launchBrowser); 1 is the robust default. */
|
|
144
144
|
captureFrames?: number;
|
|
145
145
|
}
|
|
146
|
-
export declare function getCaptureOutputPaths(outBase: string, tool:
|
|
146
|
+
export declare function getCaptureOutputPaths(outBase: string, tool: string, name: string, renderer: string): CaptureOutputPaths;
|
|
147
147
|
//# sourceMappingURL=captureEntry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"captureEntry.d.ts","sourceRoot":"","sources":["../src/captureEntry.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,kBAAkB,CAAC;AAK7D,OAAO,KAAK,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"captureEntry.d.ts","sourceRoot":"","sources":["../src/captureEntry.ts"],"names":[],"mappings":"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"}
|
package/dist/captureEntry.js
CHANGED
|
@@ -60,7 +60,7 @@ export async function captureEntry(opts) {
|
|
|
60
60
|
let anyFailed = false;
|
|
61
61
|
let anyChanged = false;
|
|
62
62
|
// Detail lines below the caller's [N/M] header drop the entry name (the header carries it) and
|
|
63
|
-
// column-align on the renderer label, matching
|
|
63
|
+
// column-align on the renderer label, matching the validation report. The renderer name carries the
|
|
64
64
|
// verdict color; routine confirmations dim (see formatStatusLine).
|
|
65
65
|
// displayLabel overrides the renderer name when set (used by captureParallel).
|
|
66
66
|
const labelWidth = displayLabel ? Math.max(6, displayLabel.length) : Math.max(6, ...renderers.map((r) => r.length));
|
|
@@ -70,13 +70,14 @@ export async function captureEntry(opts) {
|
|
|
70
70
|
// Stop launching pages once an interrupt has begun; the partial result is reported by the caller.
|
|
71
71
|
if (isAborted())
|
|
72
72
|
break;
|
|
73
|
-
const urlPath = entry.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
const urlPath = entry.routes?.[renderer] ??
|
|
74
|
+
(entry.route
|
|
75
|
+
? entry.route(renderer)
|
|
76
|
+
: tool === 'examples'
|
|
77
|
+
? `examples/${entry.name}/${routeSegment(renderer)}/`
|
|
78
|
+
: tool === 'functional'
|
|
79
|
+
? `tests/${entry.name}/${routeSegment(renderer)}/`
|
|
80
|
+
: ''); // landing: the single page is served at the server root
|
|
80
81
|
const url = `${baseUrl}/${urlPath}`;
|
|
81
82
|
const { outDir, tmpScreenshot, finalScreenshot, tmpLogs, finalLogs, statusPath } = getCaptureOutputPaths(outBase, tool, entry.name, renderer);
|
|
82
83
|
mkdirSync(outDir, { recursive: true });
|
|
@@ -221,6 +222,16 @@ export async function captureEntry(opts) {
|
|
|
221
222
|
.screenshot()
|
|
222
223
|
.catch(() => page.screenshot());
|
|
223
224
|
}
|
|
225
|
+
else if (backend === 'webgl' && captureFrames > 0) {
|
|
226
|
+
// launchBrowser forces preserveDrawingBuffer in deterministic frame mode, so read the canvas
|
|
227
|
+
// itself instead of Chromium's compositor. Headless SwiftShader can display a WebGL canvas in
|
|
228
|
+
// an interactive browser while returning an entirely blank locator screenshot; reference pages
|
|
229
|
+
// that do not register a verifier otherwise produce a false-green white capture here.
|
|
230
|
+
const canvasDataUrl = await getCanvasImageDataUrl(page);
|
|
231
|
+
if (canvasDataUrl === null)
|
|
232
|
+
throw new Error('WebGL canvas did not produce a capture image');
|
|
233
|
+
screenshotBuffer = Buffer.from(canvasDataUrl.split(',')[1], 'base64');
|
|
234
|
+
}
|
|
224
235
|
else {
|
|
225
236
|
screenshotBuffer = await page
|
|
226
237
|
.locator('canvas')
|
|
@@ -377,6 +388,9 @@ async function getRenderImageDataUrl(page) {
|
|
|
377
388
|
.evaluate(() => window.__ftRenderImage ?? null)
|
|
378
389
|
.catch(() => null);
|
|
379
390
|
}
|
|
391
|
+
async function getCanvasImageDataUrl(page) {
|
|
392
|
+
return page.evaluate(() => document.querySelector('canvas')?.toDataURL('image/png') ?? null).catch(() => null);
|
|
393
|
+
}
|
|
380
394
|
// The kind of functional target the page registered (webgl / webgpu / canvas / dom), or null if it
|
|
381
395
|
// registered none. A registered target is the page's claim that it verifies its own render; the
|
|
382
396
|
// screenshot selection uses it to tell "opted into verification but drew blank" (a failure) from
|