"""Tests for transcription.models — Document, Job, Transcript persistence and relationships.""" from uuid import UUID import pytest from sqlalchemy.exc import IntegrityError from transcription.models import Document, Job, JobStatus, Transcript def _make_document(**overrides) -> Document: """Create a Document with sensible defaults.""" defaults = {"filename": "letter.jpg", "file_path": "/uploads/letter.jpg"} defaults.update(overrides) return Document(**defaults) def _persist_document(session) -> Document: """Create, persist, and return a Document.""" doc = _make_document() session.add(doc) session.commit() session.refresh(doc) return doc def _persist_job(session, document: Document) -> Job: """Create, persist, and return a Job linked to a Document.""" job = Job(document_id=document.id) session.add(job) session.commit() session.refresh(job) return job class TestDocumentModel: """Verify Document creation and default field population.""" def test_can_be_persisted(self, session): """A Document round-trips through the database with correct fields.""" doc = _persist_document(session) fetched = session.get(Document, doc.id) assert fetched is not None assert fetched.filename == "letter.jpg" assert fetched.file_path == "/uploads/letter.jpg" def test_defaults_are_populated(self, session): """id is a UUID and uploaded_at is populated on creation.""" doc = _persist_document(session) assert isinstance(doc.id, UUID) assert doc.uploaded_at is not None class TestJobModel: """Verify Job creation, defaults, and status transitions.""" def test_can_be_created_for_document(self, session): """A Job linked to a Document via FK persists correctly.""" doc = _persist_document(session) job = _persist_job(session, doc) fetched = session.get(Job, job.id) assert fetched is not None assert fetched.document_id == doc.id def test_defaults_are_populated(self, session): """Default status is queued; created_at and updated_at are populated.""" doc = _persist_document(session) job = _persist_job(session, doc) assert job.status == JobStatus.QUEUED assert job.retry_count == 0 assert job.created_at is not None assert job.updated_at is not None def test_transitions_to_transcribed(self, session): """Status updates from queued to processing to transcribed.""" doc = _persist_document(session) job = _persist_job(session, doc) assert job.status == JobStatus.QUEUED job.status = JobStatus.PROCESSING session.add(job) session.commit() session.refresh(job) assert job.status == JobStatus.PROCESSING job.status = JobStatus.TRANSCRIBED session.add(job) session.commit() session.refresh(job) assert job.status == JobStatus.TRANSCRIBED def test_transitions_to_failed(self, session): """Status updates from processing to failed.""" doc = _persist_document(session) job = _persist_job(session, doc) job.status = JobStatus.PROCESSING session.add(job) session.commit() session.refresh(job) job.status = JobStatus.FAILED session.add(job) session.commit() session.refresh(job) assert job.status == JobStatus.FAILED class TestTranscriptModel: """Verify Transcript persistence for success and failure cases.""" def test_success_record_persists(self, session): """A Transcript with text set and error_detail None persists correctly.""" doc = _persist_document(session) job = _persist_job(session, doc) transcript = Transcript(job_id=job.id, text="Dear Sir, ...") session.add(transcript) session.commit() session.refresh(transcript) fetched = session.get(Transcript, transcript.id) assert fetched is not None assert fetched.text == "Dear Sir, ..." assert fetched.error_detail is None def test_failure_record_persists(self, session): """A Transcript with text None and error_detail set persists correctly.""" doc = _persist_document(session) job = _persist_job(session, doc) transcript = Transcript(job_id=job.id, error_detail="Provider timeout") session.add(transcript) session.commit() session.refresh(transcript) fetched = session.get(Transcript, transcript.id) assert fetched is not None assert fetched.text is None assert fetched.error_detail == "Provider timeout" def test_job_id_is_unique(self, session): """Inserting two transcripts with the same job_id raises an integrity error.""" doc = _persist_document(session) job = _persist_job(session, doc) t1 = Transcript(job_id=job.id, text="First") session.add(t1) session.commit() t2 = Transcript(job_id=job.id, text="Duplicate") session.add(t2) with pytest.raises(IntegrityError): session.commit() class TestRelationships: """Verify SQLModel relationship navigation between models.""" def test_document_exposes_jobs(self, session): """document.jobs returns the linked Job list.""" doc = _persist_document(session) _persist_job(session, doc) _persist_job(session, doc) session.refresh(doc) assert len(doc.jobs) == 2 assert all(isinstance(j, Job) for j in doc.jobs) def test_job_exposes_transcript(self, session): """job.transcript returns the linked Transcript.""" doc = _persist_document(session) job = _persist_job(session, doc) transcript = Transcript(job_id=job.id, text="Transcribed text") session.add(transcript) session.commit() session.refresh(job) assert job.transcript is not None assert isinstance(job.transcript, Transcript) assert job.transcript.text == "Transcribed text"