Files
reverse-engineering-anything/tests/boundary/browser/browserComparisonEvidence.test.ts
T

99 lines
4.0 KiB
TypeScript

import { expect, it } from "vitest";
import {
compareWebCaptureEvidence,
compareWebScreenshotEvidence,
} from "../../../src/application/BrowserObservationService.js";
import { CdpBrowserProvider } from "../../../src/browser/CdpBrowserProvider.js";
import { compareWebCapturesInputSchema } from "../../../src/domain/webCaptureDiffSchemas.js";
import { EvidenceLedger } from "../../../src/application/investigation/EvidenceLedger.js";
import { scenarioCaptureFixture } from "../../fixtures/browserScenarioCapture.js";
import { passiveNetworkCapture } from "../../fixtures/passiveNetworkCapture.js";
import { browserCaptureComparisonInputSchema } from "../../../src/domain/browserCaptureComparison.js";
import { compareWebScreenshotsInputSchema } from "../../../src/domain/webScreenshot.js";
import { BROWSER_TOOL_CONTRACTS } from "../../../src/contracts/browserToolContracts.js";
import { digestCanonicalValue } from "../../../src/domain/canonicalDigest.js";
import { parseEvidence } from "../../../src/domain/evidence.js";
import { ok } from "../../../src/domain/result.js";
it("retains distinct offline comparison inputs even when their diff reports match", async () => {
const browser = new CdpBrowserProvider();
const compare = async (path: string) => {
const inspection = passiveNetworkCapture([path]);
const result = await compareWebCaptureEvidence(
browser,
compareWebCapturesInputSchema.parse({
before: { inspection },
after: { inspection },
}),
);
if (!result.ok) throw result.error;
return parseEvidence(result.value);
};
const first = await compare("/customer-a");
const second = await compare("/customer-b");
expect(first.normalized_result).toEqual(second.normalized_result);
expect(first.evidence_id).not.toBe(second.evidence_id);
expect(first.parameters.comparison_input_sha256).not.toBe(
second.parameters.comparison_input_sha256,
);
expect(first).toMatchObject({
confidence: "derived",
authority: "analyst-inference",
parameters: { before_target_id: "page", after_target_id: "page" },
});
expect((await compare("/customer-a")).evidence_id).toBe(first.evidence_id);
const ledger = new EvidenceLedger();
expect(ledger.record(first)).toEqual(ok("added"));
expect(ledger.record(second)).toEqual(ok("added"));
});
it("commits complete scenario comparison inputs beyond the diff projection", async () => {
const compare = async (duration: number) => {
const capture = { ...scenarioCaptureFixture(), duration_ms: duration };
const input = browserCaptureComparisonInputSchema.parse({
before_scenario: capture,
after_scenario: capture,
});
const result = await compareWebCaptureEvidence(
new CdpBrowserProvider(),
input,
);
if (!result.ok) throw result.error;
return result.value;
};
const first = await compare(1);
const second = await compare(2);
expect(first.normalized_result).toEqual(second.normalized_result);
expect(first.evidence_id).not.toBe(second.evidence_id);
expect(first).toMatchObject({
confidence: "derived",
authority: "analyst-inference",
parameters: { comparison_kind: "browser_scenario" },
});
});
it("commits complete screenshot comparison inputs and reports derived provenance", async () => {
const contract = BROWSER_TOOL_CONTRACTS.find(
({ name }) => name === "compare_web_screenshots",
);
const input = compareWebScreenshotsInputSchema.parse(
contract?.examples[0]?.input,
);
const result = await compareWebScreenshotEvidence(
new CdpBrowserProvider(),
input,
);
if (!result.ok) throw result.error;
expect(parseEvidence(result.value)).toMatchObject({
confidence: "derived",
authority: "analyst-inference",
parameters: {
comparison_input_sha256: digestCanonicalValue(input),
before_artifact_sha256: input.before.sha256,
after_artifact_sha256: input.after.sha256,
channel_threshold: input.channel_threshold,
},
normalized_result: { status: "identical", compared_pixels: 1 },
});
});