import { describe, expect, it } from "vitest"; import { formatReport, runOcrEval } from "./ocrEvalHarness"; import { ocrEvalCorpus } from "./corpus"; // Regression gate: every case in the combined corpus is verified ground truth, // so the parser must read every labeled field correctly. A drop here means an // OCR/parser change regressed a previously-correct read - look at the printed // failures. If a change intentionally alters a correct output, update the corpus // label in the same commit (the label is the source of truth, not the code). describe("OCR eval harness", () => { const report = runOcrEval(ocrEvalCorpus); it("prints the accuracy report", () => { // Surfaced in test output for humans; not an assertion. // eslint-disable-next-line no-console console.log("\n" + formatReport(report) + "\n"); expect(report.totalCases).toBe(ocrEvalCorpus.length); }); it("reads every labeled field on the eval corpus correctly", () => { const failureSummary = report.failures .map((failure) => { const wrong = failure.fields .filter((entry) => !entry.correct) .map((entry) => `${entry.field}: expected "${entry.expected}" got "${entry.actual}"`) .join("; "); return `${failure.id} -> ${wrong}`; }) .join("\n"); expect(report.fieldAccuracy, `field regressions:\n${failureSummary}`).toBe(1); expect(report.criticalFieldAccuracy).toBe(1); expect(report.exactRate).toBe(1); }); it("labels every critical field at least once across the corpus", () => { const criticalCoverage = report.perField.filter( (entry) => ["name", "slot", "mainStat", "mainValue", "setName"].includes(entry.field) && entry.evaluated > 0, ); // name is derived indirectly on most cases; slot/mainStat/mainValue/setName must be exercised. expect(criticalCoverage.length).toBeGreaterThanOrEqual(4); }); });