generated from john/python-template
Revamped the Documents, People, & Jobs too.
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
"""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.",
|
||||
}
|
||||
|
||||
response = client.post("/ui/people/new", data=payload, follow_redirects=True)
|
||||
|
||||
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",
|
||||
}
|
||||
|
||||
response = client.post("/ui/people/new", data=payload, follow_redirects=True)
|
||||
|
||||
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.",
|
||||
}
|
||||
|
||||
response = client.post(f"/ui/people/{person_id}/edit", data=update_payload, follow_redirects=True)
|
||||
|
||||
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)
|
||||
|
||||
response = client.post(f"/ui/people/{person_id}/delete", follow_redirects=True)
|
||||
|
||||
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)
|
||||
|
||||
response = client.post(f"/ui/people/{person_id}/delete", follow_redirects=True)
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user