"""Unit tests for fast-alpr result parsing — no model weights required (the objects are duck-typed stand-ins shaped like fast-alpr's ALPRResult).""" from __future__ import annotations from types import SimpleNamespace from vision_service.recognizer import _reduce_confidence, plate_from_alpr_result def test_reduce_confidence_takes_min_of_list() -> None: # The weakest character governs trust in the whole plate. assert _reduce_confidence([0.99, 0.80, 0.95]) == 0.80 def test_reduce_confidence_handles_scalar_and_junk() -> None: assert _reduce_confidence(0.7) == 0.7 assert _reduce_confidence(None) == 0.0 assert _reduce_confidence([]) == 0.0 assert _reduce_confidence("nope") == 0.0 def _fake_result(text: str, conf: list[float], region: str | None = None) -> SimpleNamespace: box = SimpleNamespace(x1=10, y1=20, x2=110, y2=60) return SimpleNamespace( ocr=SimpleNamespace(text=text, confidence=conf, region=region), detection=SimpleNamespace(bounding_box=box), ) def test_plate_from_result_maps_fields() -> None: plate = plate_from_alpr_result(_fake_result("5AU5341", [0.999, 0.9995, 0.97], "Czech Republic")) assert plate is not None assert plate.text == "5AU5341" assert plate.confidence == 0.97 # min of the per-character list assert plate.region == "Czech Republic" assert plate.bbox is not None assert (plate.bbox.x1, plate.bbox.y1, plate.bbox.x2, plate.bbox.y2) == (10, 20, 110, 60) def test_plate_from_result_skips_empty_text() -> None: assert plate_from_alpr_result(_fake_result("", [0.9])) is None assert plate_from_alpr_result(SimpleNamespace(ocr=None, detection=None)) is None