@pytest_asyncio.fixture async def seed_job(app_client: tuple[FastAPI, TestClient]): """Return an async factory helper for seeding a Document -> Job -> Source tuple.""" app, _ = app_client fixtures_dir = Path(__file__).resolve().parents[1] / "fixtures" / "images" / "valid" async def _seed( *, filename: str = "sample.pdf", status: JobStatus = JobStatus.TRANSCRIBED, transcription_text: str | None = "Sample transcript text", error_detail: str | None = None, revision_text: str | None = None, source_file: Path | None = None, ) -> UUID: async with session_scope() as session: stored_path = app.state.settings.upload_dir / filename stored_path.parent.mkdir(parents=True, exist_ok=True) source_path = source_file or fixtures_dir / "small_png.png" stored_path.write_bytes(source_path.read_bytes()) document = Document(name=filename) session.add(document) await session.flush() job = Job( document_id=document.id, status=status, retry_count=0, provider="openrouter", model="google/gemini-2.5-flash", prompt_name="transcribe_document.md", ) session.add(job) await session.flush() source = Source( document_id=document.id, upload_name=filename, filename=filename, file_path=str(stored_path), ) session.add(source) await session.flush() if transcription_text is not None or error_detail is not None: session.add( JobSource( job_id=job.id, source_id=source.id, status=JobSourceStatus.TRANSCRIBED if transcription_text is not None else JobSourceStatus.FAILED, raw_transcription=transcription_text, error_detail=error_detail, ) ) if revision_text is not None: source.revised_text = revision_text source.date_revised = datetime.now(UTC) session.add(source) await session.commit() return job.id return _seed