"""Tests for Step 3 functional API routes.""" from datetime import datetime, timezone from types import SimpleNamespace from uuid import uuid4 from fastapi import FastAPI from fastapi.testclient import TestClient import pytest 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(timezone.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(timezone.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(timezone.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(timezone.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