"""Action handler tests for Person CRUD mutations.""" from datetime import date from uuid import uuid4 import pytest from sqlmodel import select from transcription.db import session_scope from transcription.db.models import Document, DocumentPerson, DocumentPersonRole, Person @pytest.mark.integration class TestPeopleActionHandlers: """Verify POST/mutation routes for Person creation, updates, and deletions.""" @pytest.mark.asyncio async def test_create_person_success(self, app_client): _, client = app_client payload = { "full_name": "Mary-Jo Kline", "display_name": "Mary-Jo", "maiden_name": "", "birth_date": "1945-03-12", "birth_date_raw": "ca. 1945", "birth_place": "Boston, MA", "biography": "Editor and scholar in documentary editing.", } assert response.status_code == 200 assert "Mary-Jo Kline" in response.text async with session_scope() as session: person = ( await session.exec(select(Person).where(Person.full_name == "Mary-Jo Kline")) ).first() assert person is not None assert person.display_name == "Mary-Jo" assert person.birth_date == date(1945, 3, 12) assert person.biography == "Editor and scholar in documentary editing." @pytest.mark.asyncio async def test_create_person_validation_missing_full_name(self, app_client): _, client = app_client payload = { "full_name": "", "display_name": "Anonymous", } assert response.status_code == 200 assert "Full name is required." in response.text @pytest.mark.asyncio async def test_update_person_details_success(self, app_client): _, client = app_client async with session_scope() as session: person = Person(full_name="Original Name", display_name="Orig") session.add(person) await session.commit() person_id = str(person.id) update_payload = { "full_name": "Updated Person Name", "display_name": "Updated Display", "maiden_name": "Cochran", "birth_date": "1902-08-20", "biography": "Updated archival biographical information.", } assert response.status_code == 200 assert "Updated Person Name" in response.text async with session_scope() as session: updated_person = await session.get(Person, person_id) assert updated_person is not None assert updated_person.full_name == "Updated Person Name" assert updated_person.display_name == "Updated Display" assert updated_person.maiden_name == "Cochran" assert updated_person.birth_date == date(1902, 8, 20) @pytest.mark.asyncio async def test_delete_unlinked_person_success(self, app_client): _, client = app_client async with session_scope() as session: person = Person(full_name="Transient Record") session.add(person) await session.commit() person_id = str(person.id) assert response.status_code == 200 assert "Person deleted" in response.text or "Archival Entities: People" in response.text async with session_scope() as session: deleted_person = await session.get(Person, person_id) assert deleted_person is None @pytest.mark.asyncio async def test_delete_person_removes_linked_document_relationship(self, app_client): _, client = app_client async with session_scope() as session: person = Person(full_name="Linked Person to Delete") doc = Document(name="Historical Letter", document_type="letter") session.add_all([person, doc]) await session.flush() link = DocumentPerson( document_id=doc.id, person_id=person.id, role=DocumentPersonRole.AUTHOR, ) session.add(link) await session.commit() person_id = str(person.id) doc_id = str(doc.id) assert response.status_code == 200 async with session_scope() as session: # Person should be deleted deleted_person = await session.get(Person, person_id) assert deleted_person is None # Associated relationship link should also be removed remaining_links = ( await session.exec( select(DocumentPerson).where(DocumentPerson.person_id == person_id) ) ).all() assert len(remaining_links) == 0 # Document itself should remain intact document = await session.get(Document, doc_id) assert document is not None