generated from john/python-template
119 lines
4.0 KiB
Python
119 lines
4.0 KiB
Python
"""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
|