""" Tests for Phase 8: normalized intermediate schema and mapping service. """ import json from pathlib import Path import pytest from src.models.normalized_template import ( ActionType, NormalizedDocument, NormalizedField, NormalizedRole, NormalizedTemplate, ) from src.services.mapping_service import adobe_folder_to_normalized DOWNLOADS = Path(__file__).parent.parent / "downloads" DAVID_DIR = DOWNLOADS / "David Tag Demo Form__CBJCHBCA" NDA_DIR = DOWNLOADS / "_DEMO USE ONLY_ NDA__CBJCHBCA" ROB_DIR = DOWNLOADS / "Rob Test__CBJCHBCA" # --------------------------------------------------------------------------- # Model construction # --------------------------------------------------------------------------- class TestNormalizedModels: def test_normalized_role_defaults(self): r = NormalizedRole(name="Customer", order=1) assert r.action_type == ActionType.SIGN assert r.order == 1 def test_normalized_field_defaults(self): f = NormalizedField(type="text", label="Name", page=1, x=10, y=20, width=120, height=24) assert f.required is False assert f.read_only is False assert f.options == [] assert f.conditional_parent_label is None def test_normalized_template_construction(self): t = NormalizedTemplate( name="My Template", roles=[NormalizedRole(name="Signer 1", order=1)], fields=[ NormalizedField(type="signature", label="sig1", page=1, x=0, y=0, width=140, height=28) ], ) assert t.name == "My Template" assert len(t.roles) == 1 assert len(t.fields) == 1 def test_role_names(self): t = NormalizedTemplate( name="T", roles=[ NormalizedRole(name="Customer", order=1), NormalizedRole(name="Company", order=2), ], ) assert t.role_names() == ["Customer", "Company"] def test_fields_for_role(self): t = NormalizedTemplate( name="T", roles=[NormalizedRole(name="Signer 1", order=1)], fields=[ NormalizedField(type="signature", label="s1", page=1, x=0, y=0, width=140, height=28, role_name="Signer 1"), NormalizedField(type="text", label="name", page=1, x=0, y=50, width=120, height=24, role_name="Signer 2"), ], ) assert len(t.fields_for_role("Signer 1")) == 1 assert len(t.fields_for_role("Signer 2")) == 1 assert len(t.fields_for_role("Nobody")) == 0 def test_normalized_document_checksum(self): doc = NormalizedDocument( name="test.pdf", content_base64="dGVzdA==", checksum_sha256="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", ) assert doc.checksum_sha256 != "" def test_serialization_roundtrip(self): t = NormalizedTemplate( name="Round Trip", roles=[NormalizedRole(name="Signer 1", order=1)], ) dumped = t.model_dump() restored = NormalizedTemplate(**dumped) assert restored.name == t.name assert len(restored.roles) == 1 # --------------------------------------------------------------------------- # Mapping service — requires real download fixtures # --------------------------------------------------------------------------- @pytest.mark.skipif(not DAVID_DIR.exists(), reason="Downloads fixtures not present") class TestMappingService: def test_david_template_normalizes(self): norm, warnings = adobe_folder_to_normalized(str(DAVID_DIR)) assert isinstance(norm, NormalizedTemplate) assert norm.name != "" assert len(norm.roles) >= 1 assert len(norm.fields) > 0 def test_david_fields_have_roles(self): norm, _ = adobe_folder_to_normalized(str(DAVID_DIR)) role_names = norm.role_names() for f in norm.fields: assert f.role_name in role_names, f"Field '{f.label}' has unresolved role '{f.role_name}'" def test_david_documents_have_checksum(self): norm, _ = adobe_folder_to_normalized(str(DAVID_DIR)) assert len(norm.documents) >= 1 for doc in norm.documents: assert doc.checksum_sha256 != "", f"Document '{doc.name}' missing checksum" assert len(doc.checksum_sha256) == 64 # SHA-256 hex def test_exclude_documents_option(self): norm, _ = adobe_folder_to_normalized(str(DAVID_DIR), include_documents=False) for doc in norm.documents: assert doc.content_base64 == "" # checksum still computed even when content excluded assert doc.checksum_sha256 != "" @pytest.mark.skipif(not NDA_DIR.exists(), reason="NDA fixture not present") def test_nda_template_normalizes(self): norm, _ = adobe_folder_to_normalized(str(NDA_DIR)) assert norm.name != "" assert len(norm.fields) > 0 @pytest.mark.skipif(not ROB_DIR.exists(), reason="Rob fixture not present") def test_rob_template_normalizes(self): norm, _ = adobe_folder_to_normalized(str(ROB_DIR)) assert norm.name != ""