generated from john/python-template
228 lines
6.9 KiB
Python
228 lines
6.9 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import UTC
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
|
|
from transcription.db.models import Document
|
|
from transcription.db.models import Job
|
|
from transcription.db.models import DocumentPerson
|
|
from transcription.db.models import DocumentPersonRole
|
|
from transcription.db.models import Person
|
|
from transcription.db.models import Source
|
|
from transcription.services.documents import DocumentDeleteBlockedError
|
|
from transcription.services.documents import DocumentError
|
|
from transcription.services.documents import DocumentService
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_document_detail_allows_missing_sources(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
created = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="detail-doc",
|
|
document_type="letter",
|
|
)
|
|
)
|
|
|
|
detail = await service.read_document_detail(created.id)
|
|
|
|
assert detail.id == created.id
|
|
assert detail.sources == []
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_document_refreshes_updated_timestamp(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
created = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="timestamp-doc",
|
|
document_type="letter",
|
|
updated_at=datetime(2000, 1, 1, tzinfo=UTC),
|
|
)
|
|
)
|
|
|
|
original_updated_at = created.updated_at
|
|
created.notes = "updated"
|
|
|
|
updated = await service.update_document(created)
|
|
|
|
assert updated.notes == "updated"
|
|
assert updated.updated_at >= original_updated_at
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_document_blocks_when_dependencies_exist(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
document = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="blocked-delete",
|
|
document_type="record",
|
|
)
|
|
)
|
|
|
|
async with service._session_scope() as session:
|
|
session.add(
|
|
Source(
|
|
document_id=document.id,
|
|
page_number=1,
|
|
upload_name="001_page.png",
|
|
filename="001_page.png",
|
|
file_path="uploads/001_page.png",
|
|
)
|
|
)
|
|
session.add(Job(document_id=document.id))
|
|
await session.commit()
|
|
|
|
with pytest.raises(DocumentDeleteBlockedError):
|
|
await service.delete_document(document)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_document_succeeds_when_unlinked(default_session_factory, tmp_path):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
service.settings.upload_dir = tmp_path
|
|
|
|
document = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="free-delete",
|
|
document_type="memo",
|
|
)
|
|
)
|
|
|
|
document_dir = service.settings.upload_dir / "documents" / str(document.id)
|
|
document_dir.mkdir(parents=True, exist_ok=True)
|
|
(document_dir / "leftover.txt").write_text("orphan", encoding="utf-8")
|
|
|
|
await service.delete_document(document)
|
|
|
|
assert not document_dir.exists()
|
|
|
|
with pytest.raises(DocumentError):
|
|
await service.read_document_detail(document.id)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_document_removes_populated_storage_tree(default_session_factory, tmp_path):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
service.settings.upload_dir = tmp_path
|
|
|
|
document = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="tree-delete",
|
|
document_type="memo",
|
|
)
|
|
)
|
|
|
|
document_dir = service.settings.upload_dir / "documents" / str(document.id)
|
|
(document_dir / "page-1.jpg").parent.mkdir(parents=True, exist_ok=True)
|
|
(document_dir / "page-1.jpg").write_bytes(b"one")
|
|
(document_dir / "page-2.jpg").write_bytes(b"two")
|
|
(document_dir / "nested" / "manifest.json").parent.mkdir(parents=True, exist_ok=True)
|
|
(document_dir / "nested" / "manifest.json").write_text('{"ok": true}', encoding="utf-8")
|
|
|
|
assert document_dir.exists()
|
|
|
|
await service.delete_document(document)
|
|
|
|
assert not document_dir.exists()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_person_detail_loads_document_links(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
document = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="linked-doc",
|
|
document_type="letter",
|
|
)
|
|
)
|
|
person = await service.create_person(Person(full_name="Linked Person"))
|
|
await service.create_document_person(
|
|
DocumentPerson(
|
|
document_id=document.id,
|
|
person_id=person.id,
|
|
role=DocumentPersonRole.AUTHOR,
|
|
)
|
|
)
|
|
|
|
detail = await service.read_person_detail(person.id)
|
|
|
|
assert detail.id == person.id
|
|
assert len(detail.document_people) == 1
|
|
assert detail.document_people[0].document is not None
|
|
assert detail.document_people[0].document.name == "linked-doc"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_person_refreshes_updated_timestamp(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
created = await service.create_person(
|
|
Person(
|
|
full_name="timestamp-person",
|
|
updated_at=datetime(2000, 1, 1, tzinfo=UTC),
|
|
)
|
|
)
|
|
original_updated_at = created.updated_at
|
|
created.display_name = "updated"
|
|
|
|
updated = await service.update_person(created)
|
|
|
|
assert updated.display_name == "updated"
|
|
assert updated.updated_at >= original_updated_at
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_person_removes_links_when_linked_documents_exist(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
document = await service.create_document(
|
|
Document(
|
|
id=uuid4(),
|
|
name="block-person-delete-doc",
|
|
document_type="record",
|
|
)
|
|
)
|
|
person = await service.create_person(Person(full_name="Blocked Person"))
|
|
await service.create_document_person(
|
|
DocumentPerson(
|
|
document_id=document.id,
|
|
person_id=person.id,
|
|
role=DocumentPersonRole.AUTHOR,
|
|
)
|
|
)
|
|
|
|
await service.delete_person(person)
|
|
|
|
links = await service.list_document_people(person_id=person.id)
|
|
assert links == []
|
|
|
|
with pytest.raises(DocumentError):
|
|
await service.read_person_detail(person.id)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_person_succeeds_when_unlinked(default_session_factory):
|
|
service = DocumentService(session_factory=default_session_factory)
|
|
|
|
person = await service.create_person(Person(full_name="Free Person"))
|
|
|
|
await service.delete_person(person)
|
|
|
|
with pytest.raises(DocumentError):
|
|
await service.read_person_detail(person.id)
|