fix(e2e): bound browser snapshot diagnostics

This commit is contained in:
Vincent Koc
2026-06-07 12:39:35 +02:00
parent afcbdd7416
commit 1703fbc2ad
2 changed files with 108 additions and 2 deletions

View File

@@ -1,8 +1,57 @@
// Assertions for browser CDP snapshot E2E fixtures.
import fs from "node:fs";
const DEFAULT_SNAPSHOT_MAX_BYTES = 512 * 1024;
const SNAPSHOT_DIAGNOSTIC_MAX_BYTES = 32 * 1024;
const snapshotPath = process.argv[2] ?? "/tmp/browser-cdp-snapshot.txt";
const snapshot = fs.readFileSync(snapshotPath, "utf8");
function readPositiveIntEnv(name, fallback) {
const raw = process.env[name];
if (raw === undefined || raw === "") {
return fallback;
}
const text = raw.trim();
if (!/^\d+$/u.test(text)) {
throw new Error(`${name} must be a positive integer; got: ${raw}`);
}
const parsed = Number(text);
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
throw new Error(`${name} must be a positive integer; got: ${raw}`);
}
return parsed;
}
function readBoundedSnapshot(file, maxBytes) {
const stats = fs.statSync(file);
if (!stats.isFile()) {
throw new Error(`${file} is not a file`);
}
if (stats.size > maxBytes) {
throw new Error(`browser CDP snapshot exceeded ${maxBytes} bytes: ${stats.size} bytes`);
}
const snapshot = fs.readFileSync(file, "utf8");
const bytes = Buffer.byteLength(snapshot, "utf8");
if (bytes > maxBytes) {
throw new Error(`browser CDP snapshot exceeded ${maxBytes} bytes: ${bytes} bytes`);
}
return snapshot;
}
function snapshotDiagnostic(snapshot) {
const buffer = Buffer.from(snapshot, "utf8");
if (buffer.byteLength <= SNAPSHOT_DIAGNOSTIC_MAX_BYTES) {
return snapshot;
}
return `[truncated snapshot diagnostic to ${SNAPSHOT_DIAGNOSTIC_MAX_BYTES} bytes]\n${buffer
.subarray(buffer.byteLength - SNAPSHOT_DIAGNOSTIC_MAX_BYTES)
.toString("utf8")}`;
}
const snapshotMaxBytes = readPositiveIntEnv(
"OPENCLAW_BROWSER_CDP_SNAPSHOT_MAX_BYTES",
DEFAULT_SNAPSHOT_MAX_BYTES,
);
const snapshot = readBoundedSnapshot(snapshotPath, snapshotMaxBytes);
for (const needle of [
'button "Save"',
@@ -14,7 +63,7 @@ for (const needle of [
'button "Inside"',
]) {
if (!snapshot.includes(needle)) {
console.error(snapshot);
console.error(snapshotDiagnostic(snapshot));
throw new Error(`missing snapshot needle: ${needle}`);
}
}

View File

@@ -0,0 +1,57 @@
// Browser CDP snapshot tests cover bounded snapshot assertions.
import { spawnSync } from "node:child_process";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
const SCRIPT_PATH = "scripts/e2e/lib/browser-cdp-snapshot/assert-snapshot.mjs";
const tempDirs: string[] = [];
function makeTempRoot(): string {
const root = mkdtempSync(path.join(tmpdir(), "openclaw-browser-cdp-snapshot-"));
tempDirs.push(root);
return root;
}
function runAssertSnapshot(snapshotPath: string, env: Record<string, string> = {}) {
return spawnSync(process.execPath, [SCRIPT_PATH, snapshotPath], {
encoding: "utf8",
env: { ...process.env, ...env },
});
}
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
rmSync(dir, { force: true, recursive: true });
}
});
describe("browser CDP snapshot assertions", () => {
it("rejects oversized snapshots before reading them into diagnostics", () => {
const root = makeTempRoot();
const snapshotPath = path.join(root, "snapshot.txt");
writeFileSync(snapshotPath, "x".repeat(33), "utf8");
const result = runAssertSnapshot(snapshotPath, {
OPENCLAW_BROWSER_CDP_SNAPSHOT_MAX_BYTES: "32",
});
expect(result.status).toBe(1);
expect(result.stderr).toContain("browser CDP snapshot exceeded 32 bytes");
expect(result.stderr).not.toContain("x".repeat(33));
});
it("bounds missing-needle snapshot diagnostics", () => {
const root = makeTempRoot();
const snapshotPath = path.join(root, "snapshot.txt");
writeFileSync(snapshotPath, `${"old snapshot line\n".repeat(6 * 1024)}recent tail`, "utf8");
const result = runAssertSnapshot(snapshotPath);
expect(result.status).toBe(1);
expect(result.stderr).toContain("recent tail");
expect(result.stderr).toContain("truncated snapshot diagnostic");
expect(result.stderr.length).toBeLessThan(80 * 1024);
});
});