from __future__ import annotations import json from pathlib import Path from bl_ocr.domain.schema_validation import build_validator from bl_ocr.eval.harness import evaluate_annotation, evaluate_directory PROJECT_ROOT = Path(__file__).resolve().parents[1] SCHEMA_PATH = PROJECT_ROOT / "schema.json" def _validator(): return build_validator(json.loads(SCHEMA_PATH.read_text(encoding="utf-8"))) def _example() -> dict: return json.loads((PROJECT_ROOT / "example.json").read_text(encoding="utf-8")) def test_clean_example_passes_all_structural_checks(): result = evaluate_annotation("example", _example(), _validator()) assert result.parse_pass assert result.schema_pass assert result.schema_error_count == 0 assert result.row_count_pass assert result.arithmetic_pass assert not result.critical def test_row_count_mismatch_is_flagged(): annotation = _example() annotation["totals"]["line_count"]["value"] = 99 result = evaluate_annotation("mismatch", annotation, _validator()) assert not result.row_count_pass def test_empty_products_with_line_count_is_critical(): annotation = _example() annotation["products"] = [] result = evaluate_annotation("empty", annotation, _validator()) assert result.critical assert result.critical_reason is not None def test_none_annotation_fails_parse(): result = evaluate_annotation("broken", None, _validator(), parse_error="bad json") assert not result.parse_pass assert result.parse_error == "bad json" def test_evaluate_directory_aggregates(tmp_path: Path): # one clean file, one schema-invalid file (extra key) clean = _example() (tmp_path / "clean.json").write_text( json.dumps({"document_annotation": json.dumps(clean)}), encoding="utf-8" ) dirty = _example() dirty["products"][0]["_repaired"] = "leak" (tmp_path / "dirty.json").write_text( json.dumps({"document_annotation": json.dumps(dirty)}), encoding="utf-8" ) summary = evaluate_directory(tmp_path, SCHEMA_PATH) assert summary.total == 2 assert summary.parse_pass == 2 assert summary.schema_pass == 1 data = summary.as_dict() assert data["rates"]["schema_pass"] == 0.5 assert len(data["files"]) == 2