Files
rea/tests/boundary/cli/httpCaptureComparison.test.ts
T

121 lines
4.2 KiB
TypeScript

import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect } from "vitest";
import { webPageInspectionSchema } from "../../../src/domain/browserObservationSchemas.js";
import { parseEvidence } from "../../../src/domain/evidence.js";
import { cliTest } from "../../support/cli/cliFixture.js";
import { startHttpComparisonBrowser } from "../../fixtures/httpComparisonBrowser.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
cliTest(
"CLI compares incomplete HTTP responses without inventing changes",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-http-comparison-");
const response = {
requestId: "request-1",
status: 200,
mimeType: "application/json",
};
const fixture = await startHttpComparisonBrowser([response]);
try {
const inspect = () =>
cli.run({
arguments: [
"inspect-web-page",
fixture.browser.endpoint,
"allowed-page",
"--observation-ms",
"0",
"--json",
],
environment: process.env,
});
const pendingInvocation = await inspect();
expect(pendingInvocation.exitCode, pendingInvocation.stderr).toBe(0);
expect(pendingInvocation.signal).toBeNull();
const pending = webPageInspectionSchema.parse(
parseEvidence(pendingInvocation.json).normalized_result,
);
fixture.setRequests([{ ...response, encodedDataLength: 100 }]);
const finishedInvocation = await inspect();
expect(finishedInvocation.exitCode, finishedInvocation.stderr).toBe(0);
expect(finishedInvocation.signal).toBeNull();
const finished = webPageInspectionSchema.parse(
parseEvidence(finishedInvocation.json).normalized_result,
);
fixture.setRequests([
{ ...response, status: 500, encodedDataLength: 100 },
]);
const changedInvocation = await inspect();
expect(changedInvocation.exitCode, changedInvocation.stderr).toBe(0);
expect(changedInvocation.signal).toBeNull();
const changed = webPageInspectionSchema.parse(
parseEvidence(changedInvocation.json).normalized_result,
);
expect(pending.network.requests).toMatchObject([
{
status: 200,
mime_type: "application/json",
encoded_data_length: null,
},
]);
expect(finished.network.requests).toMatchObject([
{
status: 200,
mime_type: "application/json",
encoded_data_length: 100,
},
]);
// Passive attachment cannot establish the complete same-URL request
// inventory. Closed imported captures can, and retain the positive oracle.
const closed = structuredClone(pending);
closed.completeness.attach_limited_sections =
closed.completeness.attach_limited_sections.filter(
(section) => section !== "network_requests",
);
const captures = [pending, finished, changed, closed];
const paths = captures.map((_, index) =>
join(root, `capture-${String(index)}.json`),
);
await Promise.all(
captures.map((inspection, index) =>
writeFile(paths[index]!, JSON.stringify({ inspection })),
),
);
for (const [left, right, status, count] of [
[0, 1, "unknown", 0],
[1, 0, "unknown", 0],
[0, 2, "unknown", 0],
[3, 2, "changed", 1],
] as const) {
const comparedInvocation = await cli.run({
arguments: [
"compare-web-captures",
paths[left]!,
paths[right]!,
"--json",
],
environment: process.env,
});
expect(comparedInvocation.exitCode, comparedInvocation.stderr).toBe(0);
expect(comparedInvocation.signal).toBeNull();
const compared = comparedInvocation.json;
expect(compared).toMatchObject({
operation: "compare_web_captures",
normalized_result: {
overall_status: status,
dimensions: {
network: { status, total_changes: count },
},
},
});
}
} finally {
await fixture.browser.close();
}
},
60_000,
);