"""Tests for Step 3 functional API routes.""" from datetime import UTC from datetime import datetime from types import SimpleNamespace from uuid import uuid4 import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from transcription.api.errors import register_error_handlers from transcription.api.routes import router def _build_app() -> FastAPI: app = FastAPI() register_error_handlers(app) app.include_router(router) return app @pytest.mark.integration class TestFunctionalRoutes: """Verify jobs/revisions/search/export route behavior.""" def test_get_jobs_returns_serialized_rows(self, monkeypatch): """GET /api/jobs returns normalized job rows.""" now = datetime.now(UTC) job = SimpleNamespace( id=uuid4(), document_id=uuid4(), status=SimpleNamespace(value="queued"), created_at=now, updated_at=now, ) monkeypatch.setattr("transcription.api.routes.list_jobs", lambda: [job]) client = TestClient(_build_app()) response = client.get("/api/jobs") assert response.status_code == 200 payload = response.json() assert len(payload) == 1 assert payload[0]["id"] == str(job.id) assert payload[0]["status"] == "queued" def test_create_revision_returns_revision_payload(self, monkeypatch): """POST /api/jobs/{job_id}/revisions returns created revision fields.""" revision = SimpleNamespace( id=uuid4(), job_id=uuid4(), revision_number=2, text="edited text", source="user", accepted=False, created_at=datetime.now(UTC), ) monkeypatch.setattr("transcription.api.routes.add_revision", lambda **_kwargs: revision) client = TestClient(_build_app()) response = client.post( f"/api/jobs/{revision.job_id}/revisions", json={"text": "edited text", "source": "user", "accepted": False}, ) assert response.status_code == 200 payload = response.json() assert payload["id"] == str(revision.id) assert payload["revision_number"] == 2 assert payload["text"] == "edited text" def test_search_returns_results(self, monkeypatch): """GET /api/search returns accepted transcript matches.""" result = SimpleNamespace( id=uuid4(), job_id=uuid4(), revision_number=1, text="family archive", source="user", accepted=True, created_at=datetime.now(UTC), ) monkeypatch.setattr("transcription.api.routes.search_accepted_transcripts", lambda query: [result]) client = TestClient(_build_app()) response = client.get("/api/search", params={"query": "archive"}) assert response.status_code == 200 payload = response.json() assert len(payload) == 1 assert payload[0]["revision_id"] == str(result.id) assert payload[0]["accepted"] is True def test_export_returns_count_and_records(self, monkeypatch): """GET /api/export returns record count and payload list.""" records = [ { "job_id": str(uuid4()), "document_id": str(uuid4()), "filename": "letter.jpg", "revision_id": str(uuid4()), "revision_number": 1, "accepted": True, "source": "user", "text": "exported", "created_at": datetime.now(UTC).isoformat(), } ] monkeypatch.setattr("transcription.api.routes.export_transcripts", lambda accepted_only=True: records) client = TestClient(_build_app()) response = client.get("/api/export") assert response.status_code == 200 payload = response.json() assert payload["count"] == 1 assert payload["accepted_only"] is True assert payload["records"] == records