"""Tests for the people page routes.""" import asyncio from datetime import date from uuid import uuid4 import pytest from transcription.db import session_scope from transcription.db.models import Document from transcription.db.models import DocumentPerson from transcription.db.models import DocumentPersonRole from transcription.db.models import Person @pytest.mark.integration class TestPeoplePageRendering: """Verify people routes render expected CRUD read states.""" def test_people_page_renders_empty_state(self, app_client): _, client = app_client response = client.get("/ui/people") assert response.status_code == 200 assert "People" in response.text assert "Create new person" in response.text assert "No people yet." in response.text def test_people_page_lists_seeded_people(self, app_client): _, client = app_client async def _seed_person() -> None: async with session_scope() as session: session.add(Person(full_name="Ada Lovelace", display_name="Ada")) await session.commit() asyncio.run(_seed_person()) response = client.get("/ui/people") assert response.status_code == 200 assert "Ada Lovelace" in response.text assert "Display name: Ada" in response.text def test_person_create_page_renders_fields(self, app_client): _, client = app_client response = client.get("/ui/people/new") assert response.status_code == 200 assert "Create person" in response.text assert "Full name is required." in response.text assert "Birth date (YYYY-MM-DD)" in response.text assert "Death date (YYYY-MM-DD)" in response.text assert "Biography" in response.text assert "Save person" in response.text def test_person_detail_page_renders_metadata_and_empty_links(self, app_client): _, client = app_client async def _seed_person() -> str: async with session_scope() as session: person = Person( full_name="Grace Hopper", display_name="Grace", maiden_name="Murray", birth_date=date(1906, 12, 9), birth_date_raw="1906", birth_place="New York", death_date=date(1992, 1, 1), death_date_raw="1992", death_place="Arlington", biography="Computer pioneer", portrait_path="/images/grace.jpg", ) session.add(person) await session.commit() await session.refresh(person) return str(person.id) person_id = asyncio.run(_seed_person()) response = client.get(f"/ui/people/{person_id}") assert response.status_code == 200 assert "Grace Hopper" in response.text assert "Full name: Grace Hopper" in response.text assert "Display name: Grace" in response.text assert "Maiden name: Murray" in response.text assert "Birth date: 1906-12-09" in response.text assert "Death date: 1992-01-01" in response.text assert "Biography: Computer pioneer" in response.text assert "Portrait path: /images/grace.jpg" in response.text assert "Created at (read-only):" in response.text assert "Updated at (read-only):" in response.text assert "No linked documents yet." in response.text assert "Link this person from a Document workflow." in response.text def test_person_detail_page_renders_linked_documents(self, app_client): _, client = app_client async def _seed_links() -> str: async with session_scope() as session: person = Person(full_name="Linked Person") document = Document(name="Linked Document", document_type="letter") session.add(person) session.add(document) await session.flush() session.add( DocumentPerson( document_id=document.id, person_id=person.id, role=DocumentPersonRole.AUTHOR, ) ) await session.commit() await session.refresh(person) return str(person.id) person_id = asyncio.run(_seed_links()) response = client.get(f"/ui/people/{person_id}") assert response.status_code == 200 assert "Linked Document (author)" in response.text def test_person_detail_page_handles_invalid_id(self, app_client): _, client = app_client response = client.get("/ui/people/not-a-uuid") assert response.status_code == 200 assert "Invalid person id" in response.text def test_person_detail_page_handles_missing_person(self, app_client): _, client = app_client response = client.get(f"/ui/people/{uuid4()}") assert response.status_code == 200 assert "Person not found" in response.text def test_person_edit_page_renders_expected_fields(self, app_client): _, client = app_client async def _seed_person() -> str: async with session_scope() as session: person = Person(full_name="Editable Person", display_name="EP") session.add(person) await session.commit() await session.refresh(person) return str(person.id) person_id = asyncio.run(_seed_person()) response = client.get(f"/ui/people/{person_id}/edit") assert response.status_code == 200 assert "Edit person" in response.text assert "Full name is required." in response.text assert "Full name" in response.text assert "Save changes" in response.text def test_person_delete_page_shows_confirmation_when_unlinked(self, app_client): _, client = app_client async def _seed_person() -> str: async with session_scope() as session: person = Person(full_name="Safe Delete") session.add(person) await session.commit() await session.refresh(person) return str(person.id) person_id = asyncio.run(_seed_person()) response = client.get(f"/ui/people/{person_id}/delete") assert response.status_code == 200 assert "Delete person" in response.text assert "This action permanently deletes the person." in response.text assert "Delete person permanently" in response.text def test_person_delete_page_shows_blocked_state_when_linked_documents_exist(self, app_client): _, client = app_client async def _seed_links() -> str: async with session_scope() as session: person = Person(full_name="Blocked Delete") document = Document(name="Linked Document", document_type="record") session.add(person) session.add(document) await session.flush() session.add( DocumentPerson( document_id=document.id, person_id=person.id, role=DocumentPersonRole.AUTHOR, ) ) await session.commit() await session.refresh(person) return str(person.id) person_id = asyncio.run(_seed_links()) response = client.get(f"/ui/people/{person_id}/delete") assert response.status_code == 200 assert "Delete is blocked because linked documents exist." in response.text assert "Linked documents: 1" in response.text assert "Go to Documents" in response.text