import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; import test from "node:test"; import ts from "typescript"; const root = path.resolve(import.meta.dirname, "../../.."); const sourcePath = path.join(root, "web/protocol/render-image-comparison.ts"); const source = fs.readFileSync(sourcePath, "utf8").replace('import type { ErrorCode } from "./error";\n', ""); const transpiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 }, fileName: sourcePath, reportDiagnostics: true, }); assert.deepEqual(transpiled.diagnostics, []); const comparison = await import("data:text/javascript;base64," + Buffer.from(transpiled.outputText).toString("base64")); const thresholds = { maxMeanAbsoluteError: 8, maxRootMeanSquaredError: 16, maxP95ChannelError: 16, maxBadPixelRatio: 0.1, badPixelChannelError: 32, foregroundDeltaFromReferenceBackground: 32, minForegroundIntersectionOverUnion: 0.8, maxAlphaCoverageDeltaRatio: 0, }; function frame(width = 4, height = 4) { const pixels = new Uint8Array(width * height * 4); for (let index = 0; index < pixels.length; index += 4) pixels.set([64, 64, 64, 255], index); for (const pixel of [5, 6, 9, 10]) pixels.set([0, 0, 0, 255], pixel * 4); return pixels; } test("M11-04 reports every explainable metric for identical SRGB8 frames", () => { const reference = frame(); const report = comparison.compareRenderImages(reference, reference.slice(), 4, 4, thresholds); assert.equal(report.status, "READY"); assert.deepEqual( [report.meanAbsoluteError, report.rootMeanSquaredError, report.p95ChannelError, report.badPixelRatio], [0, 0, 0, 0], ); assert.equal(report.foregroundIntersectionOverUnion, 1); assert.equal(report.checks.length, 6); assert.equal(report.errorCode, null); }); test("M11-04 rejects a non-empty but compositionally wrong frame", () => { const reference = frame(); const wrong = frame(); for (let index = 0; index < wrong.length; index += 4) wrong.set([64, 64, 64, 255], index); wrong.set([255, 0, 0, 255], 0); const report = comparison.compareRenderImages(reference, wrong, 4, 4, thresholds); assert.equal(report.status, "BLOCKED"); assert.equal(report.errorCode, "RENDER_REFERENCE_MISMATCH"); assert.ok(report.foregroundIntersectionOverUnion < thresholds.minForegroundIntersectionOverUnion); assert.ok(report.checks.some((item) => !item.passed)); }); test("M11-04 rejects invalid dimensions, byte lengths and thresholds", () => { assert.throws(() => comparison.compareRenderImages(frame(), frame(), 0, 4, thresholds), /INVALID_ARGUMENT/); assert.throws(() => comparison.compareRenderImages(frame(), frame().subarray(1), 4, 4, thresholds), /INVALID_ARGUMENT/); assert.throws(() => comparison.compareRenderImages(frame(), frame(), 4, 4, { ...thresholds, maxBadPixelRatio: 2 }), /INVALID_ARGUMENT/); });