generated from john/python-template
V5.1 Modify Person table: split full name into first & last, added tags support
Quality Gate / gate (push) Failing after 11s
Quality Gate / gate (push) Failing after 11s
This commit is contained in:
@@ -37,7 +37,10 @@ def _seed_document_and_person(
|
||||
async def _seed() -> tuple[UUID, UUID]:
|
||||
async with session_scope(database_url=db_url) as session:
|
||||
document = Document(name=document_name)
|
||||
person = Person(full_name=person_name)
|
||||
tokens = [token for token in person_name.split() if token]
|
||||
given_names = " ".join(tokens[:-1]) if len(tokens) >= 2 else person_name
|
||||
last_name = tokens[-1] if len(tokens) >= 2 else person_name
|
||||
person = Person(given_names=given_names, last_name=last_name)
|
||||
session.add(document)
|
||||
session.add(person)
|
||||
await session.commit()
|
||||
|
||||
@@ -13,6 +13,7 @@ from transcription.db.models import DocumentPerson
|
||||
from transcription.db.models import DocumentTag
|
||||
from transcription.db.models import Job
|
||||
from transcription.db.models import Person
|
||||
from transcription.db.models import PersonTag
|
||||
from transcription.db.models import Source
|
||||
from transcription.db.models import Tag
|
||||
from transcription.db.models import Photo
|
||||
@@ -132,7 +133,7 @@ async def test_delete_document_removes_person_links(default_session_factory, tmp
|
||||
name="person-linked-delete",
|
||||
)
|
||||
)
|
||||
person = await people_service.create_person(Person(full_name="Linked Person"))
|
||||
person = await people_service.create_person(Person(given_names="Linked", last_name="Person"))
|
||||
author_role = await people_service.create_person_role(label="Author")
|
||||
await people_service.create_document_person(
|
||||
DocumentPerson(
|
||||
@@ -197,7 +198,7 @@ async def test_read_person_detail_loads_document_links(default_session_factory):
|
||||
name="linked-doc",
|
||||
)
|
||||
)
|
||||
person = await people_service.create_person(Person(full_name="Linked Person"))
|
||||
person = await people_service.create_person(Person(given_names="Linked", last_name="Person"))
|
||||
author_role = await people_service.create_person_role(label="Author")
|
||||
await people_service.create_document_person(
|
||||
DocumentPerson(
|
||||
@@ -221,16 +222,17 @@ async def test_update_person_refreshes_updated_timestamp(default_session_factory
|
||||
|
||||
created = await service.create_person(
|
||||
Person(
|
||||
full_name="timestamp-person",
|
||||
given_names="timestamp",
|
||||
last_name="person",
|
||||
updated_at=datetime(2000, 1, 1, tzinfo=UTC),
|
||||
)
|
||||
)
|
||||
original_updated_at = created.updated_at
|
||||
created.display_name = "updated"
|
||||
created.given_names = "updated"
|
||||
|
||||
updated = await service.update_person(created)
|
||||
|
||||
assert updated.display_name == "updated"
|
||||
assert updated.given_names == "updated"
|
||||
assert updated.updated_at >= original_updated_at
|
||||
|
||||
|
||||
@@ -245,7 +247,7 @@ async def test_delete_person_removes_links_when_linked_documents_exist(default_s
|
||||
name="block-person-delete-doc",
|
||||
)
|
||||
)
|
||||
person = await service.create_person(Person(full_name="Blocked Person"))
|
||||
person = await service.create_person(Person(given_names="Blocked", last_name="Person"))
|
||||
author_role = await service.create_person_role(label="Author")
|
||||
await service.create_document_person(
|
||||
DocumentPerson(
|
||||
@@ -268,7 +270,7 @@ async def test_delete_person_removes_links_when_linked_documents_exist(default_s
|
||||
async def test_delete_person_succeeds_when_unlinked(default_session_factory):
|
||||
service = PeopleService(session_factory=default_session_factory)
|
||||
|
||||
person = await service.create_person(Person(full_name="Free Person"))
|
||||
person = await service.create_person(Person(given_names="Free", last_name="Person"))
|
||||
|
||||
await service.delete_person(person)
|
||||
|
||||
@@ -280,7 +282,7 @@ async def test_delete_person_succeeds_when_unlinked(default_session_factory):
|
||||
async def test_delete_person_blocks_when_photos_exist(default_session_factory):
|
||||
service = PeopleService(session_factory=default_session_factory)
|
||||
|
||||
person = await service.create_person(Person(full_name="Photo Protected Person"))
|
||||
person = await service.create_person(Person(given_names="Photo Protected", last_name="Person"))
|
||||
async with service._session_scope() as session:
|
||||
session.add(
|
||||
Photo(
|
||||
@@ -313,7 +315,7 @@ async def test_update_document_person_changes_role_id(default_session_factory):
|
||||
service = PeopleService(session_factory=default_session_factory)
|
||||
|
||||
document = await documents_service.create_document(Document(id=uuid4(), name="role-sync-doc"))
|
||||
person = await service.create_person(Person(full_name="Role Sync Person"))
|
||||
person = await service.create_person(Person(given_names="Role Sync", last_name="Person"))
|
||||
author_role = await service.create_person_role(label="Author")
|
||||
recipient_role = await service.create_person_role(label="Recipient")
|
||||
link = await service.create_document_person(
|
||||
@@ -357,3 +359,25 @@ async def test_sync_document_tags_by_labels_creates_and_replaces_tags(default_se
|
||||
assert len(listed) == 1
|
||||
listed_labels = {link.tag_ref.label for link in listed[0].document_tags if link.tag_ref is not None}
|
||||
assert listed_labels == {"Census", "Research"}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_person_tags_by_labels_creates_and_replaces_tags(default_session_factory):
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
person = await people.create_person(Person(given_names="Tagged", last_name="Person"))
|
||||
|
||||
await people.sync_person_tags_by_labels(person_id=person.id, labels=["Family", "Census"])
|
||||
await people.sync_person_tags_by_labels(person_id=person.id, labels=["Census", "Research"])
|
||||
|
||||
async with people._session_scope() as session:
|
||||
links = (await session.exec(select(PersonTag).where(PersonTag.person_id == person.id))).all()
|
||||
tags = (await session.exec(select(Tag))).all()
|
||||
|
||||
assert len(links) == 2
|
||||
linked_ids = {link.tag_id for link in links}
|
||||
linked_labels = {tag.label for tag in tags if tag.id in linked_ids}
|
||||
assert linked_labels == {"Census", "Research"}
|
||||
|
||||
detail = await people.read_person_detail(person.id)
|
||||
listed_labels = {link.tag_ref.label for link in detail.person_tags if link.tag_ref is not None}
|
||||
assert listed_labels == {"Census", "Research"}
|
||||
|
||||
@@ -18,7 +18,7 @@ async def test_create_photo_persists_media_and_primary_state(default_session_fac
|
||||
settings = Settings(openrouter_api_key="test-key", upload_dir=tmp_path / "uploads")
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
photos = PhotosService(session_factory=default_session_factory, settings=settings)
|
||||
person = await people.create_person(Person(full_name="Photo Person"))
|
||||
person = await people.create_person(Person(given_names="Photo", last_name="Person"))
|
||||
|
||||
first = await photos.create_photo(person_id=person.id, filename="one.png", file_bytes=PNG_BYTES)
|
||||
second = await photos.create_photo(person_id=person.id, filename="two.png", file_bytes=PNG_BYTES)
|
||||
@@ -36,7 +36,7 @@ async def test_set_primary_and_delete_promotes_next_photo(default_session_factor
|
||||
settings = Settings(openrouter_api_key="test-key", upload_dir=tmp_path / "uploads")
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
photos = PhotosService(session_factory=default_session_factory, settings=settings)
|
||||
person = await people.create_person(Person(full_name="Primary Person"))
|
||||
person = await people.create_person(Person(given_names="Primary", last_name="Person"))
|
||||
|
||||
first = await photos.create_photo(person_id=person.id, filename="one.png", file_bytes=PNG_BYTES)
|
||||
second = await photos.create_photo(person_id=person.id, filename="two.png", file_bytes=PNG_BYTES)
|
||||
|
||||
@@ -95,7 +95,7 @@ async def test_person_role_delete_allows_unreferenced_and_blocks_referenced(defa
|
||||
unused = await people.create_person_role(label="Witness")
|
||||
referenced = await people.create_person_role(label="Creator")
|
||||
document = await documents.create_document(Document(name="Role document"))
|
||||
person = await people.create_person(Person(full_name="Role Person"))
|
||||
person = await people.create_person(Person(given_names="Role", last_name="Person"))
|
||||
await people.create_document_person(
|
||||
DocumentPerson(
|
||||
document_id=document.id,
|
||||
@@ -131,7 +131,7 @@ async def test_custom_person_role_can_be_used_for_document_link(default_session_
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
role = await people.create_person_role(label="Witness")
|
||||
document = await documents.create_document(Document(name="Witnessed document"))
|
||||
person = await people.create_person(Person(full_name="Archive Witness"))
|
||||
person = await people.create_person(Person(given_names="Archive", last_name="Witness"))
|
||||
|
||||
link = await people.add_document_person_link(
|
||||
document_id=document.id,
|
||||
|
||||
@@ -34,10 +34,11 @@ async def test_document_update_advances_updated_at(default_session_factory):
|
||||
@pytest.mark.asyncio
|
||||
async def test_person_update_advances_updated_at(default_session_factory):
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
person = await people.create_person(Person(full_name="Grace Hopper"))
|
||||
person = await people.create_person(Person(given_names="Grace", last_name="Hopper"))
|
||||
original = person.updated_at
|
||||
|
||||
person.full_name = "Rear Adm. Grace Hopper"
|
||||
person.given_names = "Rear Adm. Grace"
|
||||
person.last_name = "Hopper"
|
||||
updated = await people.update_person(person)
|
||||
|
||||
assert updated.updated_at > original
|
||||
|
||||
@@ -28,7 +28,7 @@ async def test_people_service_handles_person_and_document_person_crud(default_se
|
||||
people_service = PeopleService(session_factory=default_session_factory)
|
||||
|
||||
document = await documents.create_document(Document(id=uuid4(), name="person-doc"))
|
||||
person = await people_service.create_person(Person(full_name="Ada Lovelace"))
|
||||
person = await people_service.create_person(Person(given_names="Ada", last_name="Lovelace"))
|
||||
author_role = await people_service.create_person_role(label="Author")
|
||||
recipient_role = await people_service.create_person_role(label="Recipient")
|
||||
|
||||
@@ -61,15 +61,15 @@ async def test_people_service_handles_person_and_document_person_crud(default_se
|
||||
async def test_people_service_normalizes_and_rejects_duplicate_family_search_ids(default_session_factory):
|
||||
people_service = PeopleService(session_factory=default_session_factory)
|
||||
|
||||
created = await people_service.create_person(Person(full_name="Hig Higgins", family_search_id=" g8t4-mdq "))
|
||||
created = await people_service.create_person(Person(given_names="Hig", last_name="Higgins", family_search_id=" g8t4-mdq "))
|
||||
assert created.family_search_id == "G8T4-MDQ"
|
||||
|
||||
with pytest.raises(PeopleError) as duplicate:
|
||||
await people_service.create_person(Person(full_name="Duplicate Hig", family_search_id="G8T4-MDQ"))
|
||||
await people_service.create_person(Person(given_names="Duplicate", last_name="Hig", family_search_id="G8T4-MDQ"))
|
||||
assert duplicate.value.category == ErrorCategory.CONFLICT
|
||||
|
||||
with pytest.raises(PeopleError) as malformed:
|
||||
await people_service.create_person(Person(full_name="Malformed", family_search_id="not-an-id"))
|
||||
await people_service.create_person(Person(given_names="Malformed", last_name="Person", family_search_id="not-an-id"))
|
||||
assert malformed.value.category == ErrorCategory.VALIDATION
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ async def test_document_detail_loads_linked_person_relationship(default_session_
|
||||
people_service = PeopleService(session_factory=default_session_factory)
|
||||
|
||||
document = await documents.create_document(Document(id=uuid4(), name="detail-person-doc"))
|
||||
person = await people_service.create_person(Person(full_name="Grace Hopper"))
|
||||
person = await people_service.create_person(Person(given_names="Grace", last_name="Hopper"))
|
||||
author_role = await people_service.create_person_role(label="Author")
|
||||
await people_service.create_document_person(
|
||||
DocumentPerson(
|
||||
|
||||
@@ -45,7 +45,7 @@ async def test_update_document_with_people_rolls_back_document_and_links(default
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
role = await people.create_person_role(label="Witness")
|
||||
inactive = await people.create_person_role(label="Former Witness", is_active=False)
|
||||
person = await people.create_person(Person(full_name="Archive Witness"))
|
||||
person = await people.create_person(Person(given_names="Archive", last_name="Witness"))
|
||||
document = await create_document_with_people(
|
||||
document=Document(name="Original name"),
|
||||
links=[DocumentPersonInput(person_id=person.id, role_id=role.id)],
|
||||
@@ -83,7 +83,7 @@ async def test_direct_link_writes_reject_new_inactive_role_assignments(default_s
|
||||
people = PeopleService(session_factory=default_session_factory)
|
||||
active = await people.create_person_role(label="Witness")
|
||||
inactive = await people.create_person_role(label="Former Witness", is_active=False)
|
||||
person = await people.create_person(Person(full_name="Archive Witness"))
|
||||
person = await people.create_person(Person(given_names="Archive", last_name="Witness"))
|
||||
document = await documents.create_document(Document(name="Role rules"))
|
||||
link = await people.add_document_person_link(
|
||||
document_id=document.id,
|
||||
@@ -114,7 +114,7 @@ async def test_document_print_projection_uses_semantic_author_and_current_text(d
|
||||
document = await documents.create_document(
|
||||
Document(name="Print Me", notes="Archive note", document_type_id=document_type.id)
|
||||
)
|
||||
person = await people.create_person(Person(full_name="Historic Author"))
|
||||
person = await people.create_person(Person(given_names="Historic", last_name="Author"))
|
||||
|
||||
async with people._session_scope() as session:
|
||||
author = PersonRole(
|
||||
|
||||
+52
-6
@@ -20,6 +20,7 @@ from transcription.db import dispose_database_runtime
|
||||
from transcription.db import initialize_database_runtime
|
||||
from transcription.db import reconcile_canonical_media_paths
|
||||
from transcription.db import reconcile_legacy_job_source_columns
|
||||
from transcription.db import reconcile_person_name_columns
|
||||
from transcription.db import session_scope
|
||||
from transcription.db.models import DocumentType
|
||||
from transcription.db.models import PersonRole
|
||||
@@ -55,6 +56,7 @@ async def test_create_all_creates_expected_tables(tmp_path):
|
||||
assert "person_role" in table_names
|
||||
assert "document_person" in table_names
|
||||
assert "document_tag" in table_names
|
||||
assert "person_tag" in table_names
|
||||
assert "job" in table_names
|
||||
assert "source" in table_names
|
||||
assert "job_source" in table_names
|
||||
@@ -141,7 +143,7 @@ async def test_create_all_declares_hot_path_indexes(tmp_path):
|
||||
database = inspect(sync_connection)
|
||||
indexes = {
|
||||
table: [index["column_names"] for index in database.get_indexes(table)]
|
||||
for table in ("job", "source", "job_source", "document", "document_person", "document_tag")
|
||||
for table in ("job", "source", "job_source", "document", "document_person", "document_tag", "person_tag")
|
||||
}
|
||||
job_source_unique = [
|
||||
constraint["column_names"]
|
||||
@@ -151,9 +153,13 @@ async def test_create_all_declares_hot_path_indexes(tmp_path):
|
||||
constraint["column_names"]
|
||||
for constraint in database.get_unique_constraints("document_tag")
|
||||
]
|
||||
return indexes, job_source_unique, document_tag_unique
|
||||
person_tag_unique = [
|
||||
constraint["column_names"]
|
||||
for constraint in database.get_unique_constraints("person_tag")
|
||||
]
|
||||
return indexes, job_source_unique, document_tag_unique, person_tag_unique
|
||||
|
||||
indexes, job_source_unique, document_tag_unique = await connection.run_sync(collect)
|
||||
indexes, job_source_unique, document_tag_unique, person_tag_unique = await connection.run_sync(collect)
|
||||
|
||||
assert ["status", "date_created"] in indexes["job"]
|
||||
assert ["document_id"] in indexes["job"]
|
||||
@@ -168,6 +174,46 @@ async def test_create_all_declares_hot_path_indexes(tmp_path):
|
||||
assert ["document_id"] in indexes["document_tag"]
|
||||
assert ["tag_id"] in indexes["document_tag"]
|
||||
assert ["document_id", "tag_id"] in document_tag_unique
|
||||
assert ["person_id"] in indexes["person_tag"]
|
||||
assert ["tag_id"] in indexes["person_tag"]
|
||||
assert ["person_id", "tag_id"] in person_tag_unique
|
||||
finally:
|
||||
await dispose_database_runtime()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_reconcile_person_name_columns_backfills_split_names(tmp_path):
|
||||
settings = Settings(
|
||||
openrouter_api_key="test-key",
|
||||
database=SqliteSettings(path=str(tmp_path / "legacy-person-name.db")),
|
||||
environment="test",
|
||||
)
|
||||
runtime = initialize_database_runtime(settings=settings)
|
||||
|
||||
try:
|
||||
await create_all(engine=runtime.engine)
|
||||
async with runtime.engine.begin() as connection:
|
||||
await connection.execute(text('alter table "person" add column "full_name" varchar'))
|
||||
await connection.execute(
|
||||
text(
|
||||
'insert into "person" (id, full_name, given_names, last_name, created_at, updated_at) '
|
||||
"values (:id, :full_name, '', '', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
|
||||
),
|
||||
{"id": "55" * 16, "full_name": "Ada Lovelace"},
|
||||
)
|
||||
|
||||
changed = await reconcile_person_name_columns(engine=runtime.engine)
|
||||
assert changed >= 1
|
||||
|
||||
async with runtime.engine.connect() as connection:
|
||||
row = (
|
||||
await connection.execute(
|
||||
text('select given_names, last_name from "person" where id = :id'),
|
||||
{"id": "55" * 16},
|
||||
)
|
||||
).one()
|
||||
assert row[0] == "Ada"
|
||||
assert row[1] == "Lovelace"
|
||||
finally:
|
||||
await dispose_database_runtime()
|
||||
|
||||
@@ -227,10 +273,10 @@ async def test_reconcile_canonical_media_paths_normalizes_source_and_photo_paths
|
||||
async with runtime.engine.begin() as connection:
|
||||
await connection.execute(
|
||||
text(
|
||||
'insert into "person" (id, full_name, created_at, updated_at) '
|
||||
'values (:id, :full_name, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)'
|
||||
'insert into "person" (id, given_names, last_name, created_at, updated_at) '
|
||||
'values (:id, :given_names, :last_name, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)'
|
||||
),
|
||||
{"id": "11" * 16, "full_name": "Portrait"},
|
||||
{"id": "11" * 16, "given_names": "Portrait", "last_name": "Person"},
|
||||
)
|
||||
await connection.execute(
|
||||
text(
|
||||
|
||||
@@ -53,7 +53,7 @@ def _persist_document(session) -> Document:
|
||||
|
||||
|
||||
def _persist_person(session, **overrides: Any) -> Person:
|
||||
defaults: dict[str, Any] = {"full_name": "Ada Lovelace"}
|
||||
defaults: dict[str, Any] = {"given_names": "Ada", "last_name": "Lovelace"}
|
||||
defaults.update(overrides)
|
||||
person = Person(**defaults)
|
||||
session.add(person)
|
||||
@@ -195,10 +195,10 @@ class TestSourceModel:
|
||||
|
||||
class TestPersonAndDocumentPersonModel:
|
||||
def test_family_search_id_is_unique_when_present(self, session):
|
||||
session.add(Person(full_name="First Person", family_search_id="G8T4-MDQ"))
|
||||
session.add(Person(given_names="First", last_name="Person", family_search_id="G8T4-MDQ"))
|
||||
session.commit()
|
||||
|
||||
session.add(Person(full_name="Second Person", family_search_id="G8T4-MDQ"))
|
||||
session.add(Person(given_names="Second", last_name="Person", family_search_id="G8T4-MDQ"))
|
||||
with pytest.raises(IntegrityError):
|
||||
session.commit()
|
||||
|
||||
|
||||
@@ -168,9 +168,15 @@ def test_export_import_migration_backfills_legacy_portraits_and_homepage_images(
|
||||
target_engine = create_engine(target_db_url)
|
||||
try:
|
||||
with target_engine.connect() as connection:
|
||||
person_name = connection.execute(
|
||||
text('select given_names, last_name from "person" where id = :id'),
|
||||
{"id": person_id},
|
||||
).one()
|
||||
photos = connection.execute(
|
||||
text('select person_id, path, is_primary from "photo" order by person_id is not null desc, created_at asc')
|
||||
).all()
|
||||
assert person_name[0] == "Legacy"
|
||||
assert person_name[1] == "Portrait"
|
||||
assert len(photos) == 2
|
||||
person_photo = next(row for row in photos if row[0] is not None)
|
||||
homepage_photo = next(row for row in photos if row[0] is None)
|
||||
|
||||
@@ -28,7 +28,7 @@ async def seed_person_and_document():
|
||||
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")
|
||||
person = Person(given_names="Zenna", last_name="Cochran")
|
||||
session.add(person)
|
||||
await session.flush()
|
||||
|
||||
@@ -122,8 +122,8 @@ class TestDocumentsPageRendering:
|
||||
_, client = app_client
|
||||
async with session_scope() as session:
|
||||
person = Person(
|
||||
full_name="Albert Edward Higgins",
|
||||
display_name="Hig",
|
||||
given_names="Albert Edward",
|
||||
last_name="Higgins",
|
||||
birth_date=date(1885, 1, 2),
|
||||
)
|
||||
session.add(person)
|
||||
@@ -133,7 +133,7 @@ class TestDocumentsPageRendering:
|
||||
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
|
||||
assert "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):
|
||||
|
||||
@@ -15,18 +15,18 @@ def test_compact_date_prefers_exact_then_approximate_then_unknown():
|
||||
|
||||
def test_person_selector_label_disambiguates_without_changing_identity():
|
||||
person = Person(
|
||||
full_name="Albert Edward Higgins",
|
||||
display_name="Hig",
|
||||
given_names="Albert Edward",
|
||||
last_name="Higgins",
|
||||
birth_date=date(1885, 1, 2),
|
||||
)
|
||||
assert person_selector_label(person) == "Hig - Albert Edward Higgins (1885)"
|
||||
assert person_selector_label(person) == "Albert Edward Higgins (1885)"
|
||||
|
||||
approximate = Person(
|
||||
full_name="Albert Edward Higgins",
|
||||
display_name="Hig",
|
||||
given_names="Albert Edward",
|
||||
last_name="Higgins",
|
||||
birth_date_raw="about 1912",
|
||||
)
|
||||
assert person_selector_label(approximate) == "Hig - Albert Edward Higgins (1912)"
|
||||
assert person_selector_label(approximate) == "Albert Edward Higgins (1912)"
|
||||
|
||||
|
||||
def test_family_search_url_uses_fixed_person_details_route():
|
||||
|
||||
@@ -35,17 +35,18 @@ class TestPeoplePageRendering:
|
||||
_, client = app_client
|
||||
|
||||
async with session_scope() as session:
|
||||
session.add(Person(full_name="Ada Lovelace", display_name="Ada"))
|
||||
session.add(Person(given_names="Ada", last_name="Lovelace"))
|
||||
await session.commit()
|
||||
|
||||
response = client.get("/ui/people")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "Ada Lovelace" in response.text
|
||||
assert "Lovelace" in response.text
|
||||
assert "Ada" in response.text
|
||||
assert "Last Name" in response.text
|
||||
assert "First & Middle" in response.text or "First & Middle" in response.text
|
||||
assert "FamilySearch ID" in response.text
|
||||
assert "# Documents" in response.text
|
||||
assert "Display Name" not in response.text
|
||||
assert "Maiden Name" not in response.text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_people_page_shows_document_counts(self, app_client):
|
||||
@@ -53,7 +54,7 @@ class TestPeoplePageRendering:
|
||||
|
||||
async with session_scope() as session:
|
||||
role = (await session.exec(select(PersonRole).where(PersonRole.semantic_key == "author"))).one()
|
||||
person = Person(full_name="Counted Person")
|
||||
person = Person(given_names="Counted", last_name="Person")
|
||||
document = Document(name="Linked For Count")
|
||||
session.add_all([person, document])
|
||||
await session.flush()
|
||||
@@ -72,7 +73,7 @@ class TestPeoplePageRendering:
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "Create Person Record" in response.text
|
||||
assert "Full name is required." in response.text
|
||||
assert "Last name and first/middle names are required." in response.text
|
||||
assert "Birth date" in response.text
|
||||
assert "Death date" in response.text
|
||||
assert "Birth date (YYYY-MM-DD)" not in response.text
|
||||
@@ -90,9 +91,8 @@ class TestPeoplePageRendering:
|
||||
|
||||
async with session_scope() as session:
|
||||
person = Person(
|
||||
full_name="Grace Hopper",
|
||||
display_name="Grace",
|
||||
maiden_name="Murray",
|
||||
given_names="Grace",
|
||||
last_name="Hopper",
|
||||
birth_date=date(1906, 12, 9),
|
||||
birth_date_raw="1906",
|
||||
birth_place="New York",
|
||||
@@ -111,8 +111,8 @@ class TestPeoplePageRendering:
|
||||
assert response.status_code == 200
|
||||
assert "Grace Hopper" in response.text
|
||||
assert "Full Name:" in response.text
|
||||
assert "Display Name:" in response.text
|
||||
assert "Maiden Name:" in response.text
|
||||
assert "Last Name:" in response.text
|
||||
assert "First & Middle:" in response.text or "First & Middle:" in response.text
|
||||
assert "Birth Date:" in response.text
|
||||
assert "1906-12-09" in response.text
|
||||
assert "Death Date:" in response.text
|
||||
@@ -141,7 +141,7 @@ class TestPeoplePageRendering:
|
||||
photo_file.write_bytes(b"portrait")
|
||||
|
||||
async with session_scope() as session:
|
||||
person = Person(full_name="Portrait Person")
|
||||
person = Person(given_names="Portrait", last_name="Person")
|
||||
session.add(person)
|
||||
await session.flush()
|
||||
session.add(
|
||||
@@ -172,7 +172,7 @@ class TestPeoplePageRendering:
|
||||
photo_file.write_bytes(b"portrait")
|
||||
|
||||
async with session_scope() as session:
|
||||
person = Person(full_name="Gallery Person")
|
||||
person = Person(given_names="Gallery", last_name="Person")
|
||||
session.add(person)
|
||||
await session.flush()
|
||||
session.add(
|
||||
@@ -202,7 +202,7 @@ class TestPeoplePageRendering:
|
||||
|
||||
async with session_scope() as session:
|
||||
author_role = (await session.exec(select(PersonRole).where(PersonRole.semantic_key == "author"))).one()
|
||||
person = Person(full_name="Linked Person")
|
||||
person = Person(given_names="Linked", last_name="Person")
|
||||
document = Document(name="Linked Document")
|
||||
session.add_all([person, document])
|
||||
await session.flush()
|
||||
@@ -250,11 +250,11 @@ class TestPeoplePageRendering:
|
||||
assert "Open" not in response.text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_person_detail_page_hides_empty_maiden_name(self, app_client):
|
||||
async def test_person_detail_page_hides_removed_maiden_name_field(self, app_client):
|
||||
_, client = app_client
|
||||
|
||||
async with session_scope() as session:
|
||||
person = Person(full_name="No Maiden Name")
|
||||
person = Person(given_names="No Maiden", last_name="Name")
|
||||
session.add(person)
|
||||
await session.commit()
|
||||
person_id = str(person.id)
|
||||
@@ -285,7 +285,7 @@ class TestPeoplePageRendering:
|
||||
_, client = app_client
|
||||
|
||||
async with session_scope() as session:
|
||||
person = Person(full_name="Editable Person", display_name="EP")
|
||||
person = Person(given_names="Editable", last_name="Person")
|
||||
session.add(person)
|
||||
await session.commit()
|
||||
person_id = str(person.id)
|
||||
@@ -294,8 +294,9 @@ class TestPeoplePageRendering:
|
||||
|
||||
assert response.status_code == 200
|
||||
assert "Edit Person Record" in response.text
|
||||
assert "Full name is required." in response.text
|
||||
assert "Editable Person" in response.text
|
||||
assert "Last name and first/middle names are required." in response.text
|
||||
assert "Editable" in response.text
|
||||
assert "Person" in response.text
|
||||
assert "Save changes" in response.text
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -303,7 +304,7 @@ class TestPeoplePageRendering:
|
||||
_, client = app_client
|
||||
|
||||
async with session_scope() as session:
|
||||
person = Person(full_name="Safe Delete")
|
||||
person = Person(given_names="Safe", last_name="Delete")
|
||||
session.add(person)
|
||||
await session.commit()
|
||||
person_id = str(person.id)
|
||||
|
||||
Reference in New Issue
Block a user