"""Tests for the ViewerProjection model.""" from __future__ import annotations import pytest from pydantic import ValidationError from src.app.domain.models import ( EvidenceType, ExportEligibility, GeometryStatus, OverlayLevel, ReadinessLevel, ) from src.app.domain.models.viewer_projection import ( InspectionData, OverlayItem, ViewerProjection, ) class TestOverlayItem: def test_valid_word_overlay(self) -> None: o = OverlayItem( id="w1", level=OverlayLevel.WORD, bbox=(110, 220, 90, 40), text="Bonjour", confidence=0.96, provenance_type=EvidenceType.PROVIDER_NATIVE, geometry_status=GeometryStatus.EXACT, ) assert o.level == OverlayLevel.WORD assert o.text == "Bonjour" def test_valid_block_overlay(self) -> None: o = OverlayItem( id="tb1", level=OverlayLevel.BLOCK, bbox=(100, 200, 1200, 900), label="body", ) assert o.level == OverlayLevel.BLOCK def test_with_polygon(self) -> None: o = OverlayItem( id="w1", level=OverlayLevel.WORD, bbox=(100, 200, 50, 30), polygon=[(100, 200), (150, 200), (150, 230), (100, 230)], ) assert len(o.polygon) == 4 def test_empty_id_rejected(self) -> None: with pytest.raises(ValidationError): OverlayItem(id="", level=OverlayLevel.WORD, bbox=(0, 0, 10, 10)) def test_confidence_out_of_range(self) -> None: with pytest.raises(ValidationError): OverlayItem( id="w1", level=OverlayLevel.WORD, bbox=(0, 0, 10, 10), confidence=2.0, ) class TestInspectionData: def test_valid(self) -> None: insp = InspectionData( id="w1", level=OverlayLevel.WORD, text="Bonjour", bbox=(110, 220, 90, 40), confidence=0.96, lang="fra", provenance_type=EvidenceType.PROVIDER_NATIVE, provenance_provider="paddleocr", geometry_status=GeometryStatus.EXACT, readiness=ReadinessLevel.FULL, ) assert insp.lang == "fra" class TestViewerProjection: def test_valid_minimal(self) -> None: vp = ViewerProjection( image_ref="test.png", image_width=2480, image_height=3508, ) assert vp.block_overlays == [] assert vp.word_overlays == [] def test_valid_with_overlays(self) -> None: block = OverlayItem( id="tb1", level=OverlayLevel.BLOCK, bbox=(100, 200, 1200, 900), label="body", ) word = OverlayItem( id="w1", level=OverlayLevel.WORD, bbox=(110, 220, 90, 40), text="Bonjour", ) vp = ViewerProjection( image_ref="test.png", image_width=2480, image_height=3508, block_overlays=[block], word_overlays=[word], inspection_index={ "w1": InspectionData( id="w1", level=OverlayLevel.WORD, text="Bonjour", bbox=(110, 220, 90, 40), ) }, ) assert len(vp.block_overlays) == 1 assert len(vp.word_overlays) == 1 assert "w1" in vp.inspection_index def test_zero_dimensions_rejected(self) -> None: with pytest.raises(ValidationError): ViewerProjection( image_ref="test.png", image_width=0, image_height=100, ) def test_default_export_status(self) -> None: vp = ViewerProjection( image_ref="test.png", image_width=100, image_height=100, ) assert vp.export_status.alto_export == ReadinessLevel.NONE def test_json_roundtrip(self) -> None: vp = ViewerProjection( image_ref="test.png", image_width=2480, image_height=3508, export_status=ExportEligibility( alto_export=ReadinessLevel.FULL, page_export=ReadinessLevel.PARTIAL, viewer_render=ReadinessLevel.FULL, ), ) data = vp.model_dump(mode="json") vp2 = ViewerProjection.model_validate(data) assert vp2.export_status.alto_export == ReadinessLevel.FULL