"""Tests for the documents page routes and action handlers.""" from datetime import date import pytest import pytest_asyncio from sqlmodel import select from transcription.db import session_scope from transcription.db.models import Document from transcription.db.models import DocumentPerson from transcription.db.models import DocumentType from transcription.db.models import Job from transcription.db.models import Person from transcription.db.models import PersonRole from transcription.db.models import Source # --- Helper Fixtures --- @pytest_asyncio.fixture async def seed_person_and_document(): """Seed a Person and Document linked by DocumentPerson role.""" async with session_scope() as session: letter_type = (await session.exec(select(DocumentType).where(DocumentType.label == "Letter"))).one() author_role = (await session.exec(select(PersonRole).where(PersonRole.semantic_key == "author"))).one() person = Person(full_name="Zenna Cochran") session.add(person) await session.flush() doc = Document( name="Letter from Hig", document_type_id=letter_type.id, archive_identifier="ZC-1924-001", ) session.add(doc) await session.flush() link = DocumentPerson( document_id=doc.id, person_id=person.id, role_id=author_role.id, ) session.add(link) await session.commit() return str(doc.id), str(person.id) # --- Integration Tests for Documents Route Handlers --- @pytest.mark.integration class TestDocumentsPageRendering: """Verify document list, detail, edit, and deletion route behaviors.""" def test_documents_page_renders_empty_state(self, app_client): _, client = app_client response = client.get("/ui/documents") assert response.status_code == 200 assert "Archival Documents" in response.text assert "No documents found in repository." in response.text @pytest.mark.asyncio async def test_documents_page_lists_seeded_documents(self, app_client): _, client = app_client async with session_scope() as session: postcard_type = (await session.exec(select(DocumentType).where(DocumentType.label == "Postcard"))).one() doc = Document( name="1924 Postcard", document_type_id=postcard_type.id, archive_identifier="PC-001", ) session.add(doc) await session.commit() response = client.get("/ui/documents") assert response.status_code == 200 assert "1924 Postcard" in response.text assert "Postcard" in response.text assert "PC-001" in response.text assert "Document Date" in response.text assert "Author" in response.text def test_document_create_page_renders_form(self, app_client): _, client = app_client response = client.get("/ui/documents/new") assert response.status_code == 200 assert "Create Document" in response.text assert "Document name" in response.text assert "Linked People" in response.text assert "Document type" in response.text @pytest.mark.asyncio async def test_document_create_page_preselects_person_with_disambiguating_label(self, app_client): _, client = app_client async with session_scope() as session: person = Person( full_name="Albert Edward Higgins", display_name="Hig", birth_date=date(1885, 1, 2), ) session.add(person) await session.commit() person_id = str(person.id) response = client.get(f"/ui/documents/new?person_id={person_id}") assert response.status_code == 200 assert "Hig - Albert Edward Higgins (1885)" in response.text @pytest.mark.asyncio async def test_document_detail_page_renders_bento_grid_and_metadata(self, app_client, seed_person_and_document): _, client = app_client doc_id, _ = seed_person_and_document response = client.get(f"/ui/documents/{doc_id}") assert response.status_code == 200 assert "Letter from Hig" in response.text assert "ZC-1924-001" in response.text assert "Zenna Cochran" in response.text assert "Document Type:" in response.text assert "Letter" in response.text assert "PIPELINE JOBS" in response.text.upper() assert "Edit Document" in response.text @pytest.mark.asyncio async def test_document_jobs_page_renders_job_links(self, app_client): _, client = app_client async with session_scope() as session: doc = Document(name="Doc With Job") session.add(doc) await session.flush() job = Job(document_id=doc.id) session.add(job) await session.commit() doc_id = str(doc.id) job_id = str(job.id) response = client.get(f"/ui/documents/{doc_id}/jobs") assert response.status_code == 200 assert "Jobs for Doc With Job" in response.text assert f"Job ID: {job_id}" in response.text @pytest.mark.asyncio async def test_document_edit_page_prefills_existing_values(self, app_client, seed_person_and_document): _, client = app_client doc_id, _ = seed_person_and_document response = client.get(f"/ui/documents/{doc_id}/edit") assert response.status_code == 200 assert "Edit Document Record" in response.text assert "Letter from Hig" in response.text assert "ZC-1924-001" in response.text @pytest.mark.asyncio async def test_document_delete_page_blocks_deletion_when_dependencies_exist(self, app_client): _, client = app_client async with session_scope() as session: doc = Document(name="Doc With Source") session.add(doc) await session.flush() source = Source( document_id=doc.id, page_number=1, upload_name="page_1.png", filename="page_1.png", file_path="/tmp/page_1.png", file_hash="0" * 64, file_size_bytes=1, ) session.add(source) await session.commit() doc_id = str(doc.id) response = client.get(f"/ui/documents/{doc_id}/delete") assert response.status_code == 200 assert "Delete Document" in response.text assert "Delete is blocked because related records exist." in response.text assert "Dependencies present: Sources" in response.text @pytest.mark.asyncio async def test_document_delete_page_allows_unlinked_document_deletion(self, app_client): _, client = app_client async with session_scope() as session: doc = Document(name="Orphan Document") session.add(doc) await session.commit() doc_id = str(doc.id) response = client.get(f"/ui/documents/{doc_id}/delete") assert response.status_code == 200 assert "Delete Document" in response.text assert "Delete document permanently" in response.text assert "Delete is blocked" not in response.text