fix(verifiers): own browser fixture setup and cleanup in one scope

This commit is contained in:
morluto committed 2026-10-14 09:55:09 +08:00
1 parent 278d7fb284
commit fd8a2e98ff
8 files changed
+184 -125

No files matched your search

+39 -27
View File
@@ -14,36 +14,42 @@ import { webModuleTraceResultSchema } from "../../dist/domain/webModuleTrace.js"
import { NativeModuleResolver } from "../../dist/browser/modules/NativeModuleResolver.js"; import { NativeModuleResolver } from "../../dist/browser/modules/NativeModuleResolver.js";
import { startBrowserModuleSite } from "../fixtures/browser-module-site.mjs"; import { startBrowserModuleSite } from "../fixtures/browser-module-site.mjs";
import { mcpTextValue } from "./mcp-verifier-results.mjs"; import { mcpTextValue } from "./mcp-verifier-results.mjs";
import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Check native URL resolution against an independently loaded module graph through CLI/MCP. */ /** Check native URL resolution against an independently loaded module graph through CLI/MCP. */
export async function verifyBrowserModules( export async function verifyBrowserModules(
executable, executable,
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)), entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
) { ) {
const site = await startBrowserModuleSite(); let site;
const root = await mkdtemp(join(tmpdir(), "rea-browser-modules-")); let root;
const env = { let transport;
...process.env, let client;
REA_LOG_LEVEL: "silent", let primaryError;
REA_BROWSER_EXECUTABLE: executable,
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
};
const cli = async (...args) => {
const { stdout } = await promisify(execFile)(
process.execPath,
[entrypoint, ...args, "--json"],
{ env, timeout: 45000, maxBuffer: 16 * 1024 * 1024 },
);
return parseEvidence(JSON.parse(stdout));
};
const transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
const client = new Client({ name: "module-real-e2e", version: "1" });
try { try {
site = await startBrowserModuleSite();
root = await mkdtemp(join(tmpdir(), "rea-browser-modules-"));
const env = {
...process.env,
REA_LOG_LEVEL: "silent",
REA_BROWSER_EXECUTABLE: executable,
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
};
const cli = async (...args) => {
const { stdout } = await promisify(execFile)(
process.execPath,
[entrypoint, ...args, "--json"],
{ env, timeout: 45000, maxBuffer: 16 * 1024 * 1024 },
);
return parseEvidence(JSON.parse(stdout));
};
transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
client = new Client({ name: "module-real-e2e", version: "1" });
const oracle = await loadingOracle(executable, site); const oracle = await loadingOracle(executable, site);
const scenario = { const scenario = {
browser: { mode: "launch", executable_path: executable }, browser: { mode: "launch", executable_path: executable },
@@ -298,11 +304,17 @@ export async function verifyBrowserModules(
map_identity_verified: true, map_identity_verified: true,
implicit_refetches: 0, implicit_refetches: 0,
}; };
} catch (cause) {
primaryError = cause;
throw cause;
} finally { } finally {
await client.close(); const cleanup = [];
await transport.close(); if (client !== undefined) cleanup.push(() => client.close());
await site.close(); if (transport !== undefined) cleanup.push(() => transport.close());
await rm(root, { recursive: true, force: true }); if (site !== undefined) cleanup.push(() => site.close());
if (root !== undefined)
cleanup.push(() => rm(root, { recursive: true, force: true }));
await closeRuntimeFixtureResources(cleanup, primaryError);
} }
} }
+51 -46
View File
@@ -14,6 +14,7 @@ import {
} from "../fixtures/browser-network-site.mjs"; } from "../fixtures/browser-network-site.mjs";
import { assertBrowserNetworkEvidence } from "./browser-network-assertions.mjs"; import { assertBrowserNetworkEvidence } from "./browser-network-assertions.mjs";
import { scenarioProfiles } from "./browser-scenario-verifier.mjs"; import { scenarioProfiles } from "./browser-scenario-verifier.mjs";
import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Exercise selected network content through real CLI and stdio MCP, one browser at a time. */ /** Exercise selected network content through real CLI and stdio MCP, one browser at a time. */
export async function verifyBrowserNetworkEvidence( export async function verifyBrowserNetworkEvidence(
@@ -21,9 +22,14 @@ export async function verifyBrowserNetworkEvidence(
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)), entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
attachment, attachment,
) { ) {
const site = await startBrowserNetworkSite(); let site;
const profilesBefore = await scenarioProfiles(); let profilesBefore;
let transport;
let client;
let primaryError;
try { try {
site = await startBrowserNetworkSite();
profilesBefore = await scenarioProfiles();
const scenario = browserScenarioSchema.parse({ const scenario = browserScenarioSchema.parse({
browser: { mode: "launch", executable_path: executable }, browser: { mode: "launch", executable_path: executable },
start_url: { url: site.origin }, start_url: { url: site.origin },
@@ -97,58 +103,50 @@ export async function verifyBrowserNetworkEvidence(
() => assertBrowserNetworkEvidence(swapped, site.origin), () => assertBrowserNetworkEvidence(swapped, site.origin),
/associated with a different same-URL request/, /associated with a different same-URL request/,
); );
const transport = new StdioClientTransport({ transport = new StdioClientTransport({
command: process.execPath, command: process.execPath,
args: [entrypoint, "mcp"], args: [entrypoint, "mcp"],
env, env,
stderr: "pipe", stderr: "pipe",
}); });
const client = new Client({ name: "network-real-e2e", version: "1" }); client = new Client({ name: "network-real-e2e", version: "1" });
let mcpProof; let mcpProof;
try { await client.connect(transport);
await client.connect(transport); const result = await client.callTool(
const result = await client.callTool( { name: "capture_browser_scenario", arguments: scenario },
{ name: "capture_browser_scenario", arguments: scenario }, { timeout: 60_000 },
);
assert.notEqual(result.isError, true, JSON.stringify(result));
const evidence = parseEvidence(result.structuredContent);
mcpProof = assertBrowserNetworkEvidence(
browserScenarioCaptureSchema.parse(evidence.normalized_result),
site.origin,
);
if (attachment !== undefined) {
const connectedScenario = browserScenarioSchema.parse({
...scenario,
browser: { mode: "connect", ...attachment },
});
const connected = await client.callTool(
{ name: "capture_browser_scenario", arguments: connectedScenario },
{ timeout: 60_000 }, { timeout: 60_000 },
); );
assert.notEqual(result.isError, true, JSON.stringify(result)); assert.notEqual(connected.isError, true, JSON.stringify(connected));
const evidence = parseEvidence(result.structuredContent); const connectedEvidence = parseEvidence(connected.structuredContent);
mcpProof = assertBrowserNetworkEvidence( assert.deepEqual(
browserScenarioCaptureSchema.parse(evidence.normalized_result), assertBrowserNetworkEvidence(
site.origin, browserScenarioCaptureSchema.parse(
); connectedEvidence.normalized_result,
if (attachment !== undefined) {
const connectedScenario = browserScenarioSchema.parse({
...scenario,
browser: { mode: "connect", ...attachment },
});
const connected = await client.callTool(
{ name: "capture_browser_scenario", arguments: connectedScenario },
{ timeout: 60_000 },
);
assert.notEqual(connected.isError, true, JSON.stringify(connected));
const connectedEvidence = parseEvidence(connected.structuredContent);
assert.deepEqual(
assertBrowserNetworkEvidence(
browserScenarioCaptureSchema.parse(
connectedEvidence.normalized_result,
),
site.origin,
"disconnected-external",
), ),
cliProof, site.origin,
); "disconnected-external",
assert.ok( ),
(await fetch(`${attachment.cdp_endpoint}/json/version`)).ok, cliProof,
"Network capture closed the external browser", );
); assert.ok(
} (await fetch(`${attachment.cdp_endpoint}/json/version`)).ok,
} finally { "Network capture closed the external browser",
try { );
await client.close();
} finally {
await transport.close();
}
} }
assert.deepEqual(mcpProof, cliProof); assert.deepEqual(mcpProof, cliProof);
for (const path of [ for (const path of [
@@ -180,7 +178,14 @@ export async function verifyBrowserNetworkEvidence(
profile_cleanup: true, profile_cleanup: true,
connected_network_verified: attachment !== undefined, connected_network_verified: attachment !== undefined,
}; };
} catch (cause) {
primaryError = cause;
throw cause;
} finally { } finally {
await site.close(); const cleanup = [];
if (client !== undefined) cleanup.push(() => client.close());
if (transport !== undefined) cleanup.push(() => transport.close());
if (site !== undefined) cleanup.push(() => site.close());
await closeRuntimeFixtureResources(cleanup, primaryError);
} }
} }
+33 -21
View File
@@ -15,6 +15,7 @@ import {
assertExportedScriptAnalysis, assertExportedScriptAnalysis,
} from "./browser-script-export-assertions.mjs"; } from "./browser-script-export-assertions.mjs";
import { mcpTextValue } from "./mcp-verifier-results.mjs"; import { mcpTextValue } from "./mcp-verifier-results.mjs";
import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Verify capture → export → existing analysis through real CLI and stdio MCP. */ /** Verify capture → export → existing analysis through real CLI and stdio MCP. */
export async function verifyBrowserScriptExport( export async function verifyBrowserScriptExport(
@@ -22,24 +23,29 @@ export async function verifyBrowserScriptExport(
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)), entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
attachment, attachment,
) { ) {
const site = await startBrowserScriptSite(); let site;
const root = await mkdtemp(join(tmpdir(), "rea-browser-script-export-")); let root;
const env = { let transport;
...process.env, let client;
REA_LOG_LEVEL: "silent", let primaryError;
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
};
const cli = exportCli(entrypoint, env);
const scenario = scriptCaptureScenario(executable, site.origin);
const save = (name, capture) => saveCapture(root, name, capture);
const transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
const client = new Client({ name: "web-script-real-e2e", version: "1" });
try { try {
site = await startBrowserScriptSite();
root = await mkdtemp(join(tmpdir(), "rea-browser-script-export-"));
const env = {
...process.env,
REA_LOG_LEVEL: "silent",
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
};
const cli = exportCli(entrypoint, env);
const scenario = scriptCaptureScenario(executable, site.origin);
const save = (name, capture) => saveCapture(root, name, capture);
transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
client = new Client({ name: "web-script-real-e2e", version: "1" });
const cliCapture = await cli( const cliCapture = await cli(
"capture-browser-scenario", "capture-browser-scenario",
JSON.stringify(scenario), JSON.stringify(scenario),
@@ -103,11 +109,17 @@ export async function verifyBrowserScriptExport(
query_variants_isolated: true, query_variants_isolated: true,
implicit_refetches: 0, implicit_refetches: 0,
}; };
} catch (cause) {
primaryError = cause;
throw cause;
} finally { } finally {
await client.close(); const cleanup = [];
await transport.close(); if (client !== undefined) cleanup.push(() => client.close());
await site.close(); if (transport !== undefined) cleanup.push(() => transport.close());
await rm(root, { recursive: true, force: true }); if (site !== undefined) cleanup.push(() => site.close());
if (root !== undefined)
cleanup.push(() => rm(root, { recursive: true, force: true }));
await closeRuntimeFixtureResources(cleanup, primaryError);
} }
} }
+38 -26
View File
@@ -12,35 +12,41 @@ import { parseEvidence } from "../../dist/domain/evidence.js";
import { webSourceLocationResultSchema } from "../../dist/domain/webSourceLocation.js"; import { webSourceLocationResultSchema } from "../../dist/domain/webSourceLocation.js";
import { startBrowserSourceMapSite } from "../fixtures/browser-source-map-site.mjs"; import { startBrowserSourceMapSite } from "../fixtures/browser-source-map-site.mjs";
import { mcpTextValue } from "./mcp-verifier-results.mjs"; import { mcpTextValue } from "./mcp-verifier-results.mjs";
import { closeRuntimeFixtureResources } from "./browser-runtime-fixture-lifecycle.mjs";
/** Verify real Chrome capture → export → original compiler point through packaged CLI/MCP. */ /** Verify real Chrome capture → export → original compiler point through packaged CLI/MCP. */
export async function verifyBrowserSourceMap( export async function verifyBrowserSourceMap(
executable, executable,
entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)), entrypoint = fileURLToPath(new URL("../rea.mjs", import.meta.url)),
) { ) {
const site = await startBrowserSourceMapSite(); let site;
const root = await mkdtemp(join(tmpdir(), "rea-browser-source-map-")); let root;
const env = { let transport;
...process.env, let client;
REA_LOG_LEVEL: "silent", let primaryError;
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
};
const cli = async (...args) => {
const { stdout } = await promisify(execFile)(
process.execPath,
[entrypoint, ...args, "--json"],
{ env, timeout: 45000, maxBuffer: 16 * 1024 * 1024 },
);
return parseEvidence(JSON.parse(stdout));
};
const transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
const client = new Client({ name: "source-map-real-e2e", version: "1" });
try { try {
site = await startBrowserSourceMapSite();
root = await mkdtemp(join(tmpdir(), "rea-browser-source-map-"));
const env = {
...process.env,
REA_LOG_LEVEL: "silent",
HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper",
};
const cli = async (...args) => {
const { stdout } = await promisify(execFile)(
process.execPath,
[entrypoint, ...args, "--json"],
{ env, timeout: 45000, maxBuffer: 16 * 1024 * 1024 },
);
return parseEvidence(JSON.parse(stdout));
};
transport = new StdioClientTransport({
command: process.execPath,
args: [entrypoint, "mcp"],
env,
stderr: "pipe",
});
client = new Client({ name: "source-map-real-e2e", version: "1" });
const capture = await cli( const capture = await cli(
"capture-browser-scenario", "capture-browser-scenario",
JSON.stringify({ JSON.stringify({
@@ -126,11 +132,17 @@ export async function verifyBrowserSourceMap(
selected_inert_userinfo_context_preserved: true, selected_inert_userinfo_context_preserved: true,
public_point_cases: 4, public_point_cases: 4,
}; };
} catch (cause) {
primaryError = cause;
throw cause;
} finally { } finally {
await client.close(); const cleanup = [];
await transport.close(); if (client !== undefined) cleanup.push(() => client.close());
await site.close(); if (transport !== undefined) cleanup.push(() => transport.close());
await rm(root, { recursive: true, force: true }); if (site !== undefined) cleanup.push(() => site.close());
if (root !== undefined)
cleanup.push(() => rm(root, { recursive: true, force: true }));
await closeRuntimeFixtureResources(cleanup, primaryError);
} }
} }
function assertPoint(evidence, { site, input, capture, identity }) { function assertPoint(evidence, { site, input, capture, identity }) {
+17 -5
View File
@@ -6,15 +6,21 @@ import { join } from "node:path";
import { chromium } from "playwright-core"; import { chromium } from "playwright-core";
import { startBrowserVerifierSite } from "./fixtures/browser-verifier-site.mjs"; import { startBrowserVerifierSite } from "./fixtures/browser-verifier-site.mjs";
import { verifyBrowserDomDestinations } from "./lib/browser-dom-destinations-e2e.mjs"; import { verifyBrowserDomDestinations } from "./lib/browser-dom-destinations-e2e.mjs";
import { closeRuntimeFixtureResources } from "./lib/browser-runtime-fixture-lifecycle.mjs";
import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE; const executable = process.env.REA_BROWSER_EXECUTABLE;
if (!executable) if (!executable)
throw new Error("verify:browser:dom requires REA_BROWSER_EXECUTABLE"); throw new Error("verify:browser:dom requires REA_BROWSER_EXECUTABLE");
const profile = await mkdtemp(join(tmpdir(), "rea-browser-dom-")); await requireOrdinaryWindowsVerifierCaller();
const site = await startBrowserVerifierSite(); let profile;
let site;
let context; let context;
let report; let report;
let primaryError;
try { try {
profile = await mkdtemp(join(tmpdir(), "rea-browser-dom-"));
site = await startBrowserVerifierSite();
context = await chromium.launchPersistentContext(profile, { context = await chromium.launchPersistentContext(profile, {
executablePath: executable, executablePath: executable,
headless: true, headless: true,
@@ -50,9 +56,15 @@ try {
native_oracle: true, native_oracle: true,
verified: true, verified: true,
}; };
} catch (cause) {
primaryError = cause;
throw cause;
} finally { } finally {
await context?.close(); const cleanup = [];
await site.close(); if (context !== undefined) cleanup.push(() => context.close());
await rm(profile, { recursive: true, force: true }); if (site !== undefined) cleanup.push(() => site.close());
if (profile !== undefined)
cleanup.push(() => rm(profile, { recursive: true, force: true }));
await closeRuntimeFixtureResources(cleanup, primaryError);
} }
process.stdout.write(`${JSON.stringify(report)}\n`); process.stdout.write(`${JSON.stringify(report)}\n`);
+2
View File
@@ -2,12 +2,14 @@
import { access } from "node:fs/promises"; import { access } from "node:fs/promises";
import { verifyBrowserModules } from "./lib/browser-module-e2e.mjs"; import { verifyBrowserModules } from "./lib/browser-module-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs"; import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE; const executable = process.env.REA_BROWSER_EXECUTABLE;
if (!executable) if (!executable)
throw new Error( throw new Error(
"verify:browser:modules requires REA_BROWSER_EXECUTABLE for caller-supplied Chromium", "verify:browser:modules requires REA_BROWSER_EXECUTABLE for caller-supplied Chromium",
); );
await requireOrdinaryWindowsVerifierCaller();
await access(executable); await access(executable);
const run = createVerifierRun(); const run = createVerifierRun();
const proof = await verifyBrowserModules(executable, process.argv[2]); const proof = await verifyBrowserModules(executable, process.argv[2]);
+2
View File
@@ -2,12 +2,14 @@
import { access } from "node:fs/promises"; import { access } from "node:fs/promises";
import { verifyBrowserNetworkEvidence } from "./lib/browser-network-e2e.mjs"; import { verifyBrowserNetworkEvidence } from "./lib/browser-network-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs"; import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE; const executable = process.env.REA_BROWSER_EXECUTABLE;
if (executable === undefined || executable === "") if (executable === undefined || executable === "")
throw new Error( throw new Error(
"verify:browser:network requires REA_BROWSER_EXECUTABLE pointing to an installed Chrome-family browser", "verify:browser:network requires REA_BROWSER_EXECUTABLE pointing to an installed Chrome-family browser",
); );
await requireOrdinaryWindowsVerifierCaller();
await access(executable); await access(executable);
const run = createVerifierRun(); const run = createVerifierRun();
const proof = await verifyBrowserNetworkEvidence(executable, process.argv[2]); const proof = await verifyBrowserNetworkEvidence(executable, process.argv[2]);
+2
View File
@@ -2,12 +2,14 @@
import { access } from "node:fs/promises"; import { access } from "node:fs/promises";
import { verifyBrowserScriptExport } from "./lib/browser-script-export-e2e.mjs"; import { verifyBrowserScriptExport } from "./lib/browser-script-export-e2e.mjs";
import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs"; import { createVerifierRun, completeVerifierRun } from "./lib/verifier-run.mjs";
import { requireOrdinaryWindowsVerifierCaller } from "./lib/windows-ordinary-user-verifier.mjs";
const executable = process.env.REA_BROWSER_EXECUTABLE; const executable = process.env.REA_BROWSER_EXECUTABLE;
if (executable === undefined || executable === "") if (executable === undefined || executable === "")
throw new Error( throw new Error(
"verify:browser:scripts requires REA_BROWSER_EXECUTABLE pointing to an installed Chrome-family browser", "verify:browser:scripts requires REA_BROWSER_EXECUTABLE pointing to an installed Chrome-family browser",
); );
await requireOrdinaryWindowsVerifierCaller();
await access(executable); await access(executable);
const run = createVerifierRun(); const run = createVerifierRun();
const proof = await verifyBrowserScriptExport(executable, process.argv[2]); const proof = await verifyBrowserScriptExport(executable, process.argv[2]);