generated from john/python-template
123 lines
4.4 KiB
Python
123 lines
4.4 KiB
Python
"""Action handler tests for Job CRUD mutations."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from sqlmodel import select
|
|
|
|
from transcription.db import session_scope
|
|
from transcription.db.models import Document, Job, JobSource, JobSourceStatus, JobStatus, Source
|
|
|
|
|
|
@pytest.mark.integration
|
|
class TestJobsActionHandlers:
|
|
"""Verify POST/mutation routes for Job creation, status changes, and deletions."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_job_success(self, app_client):
|
|
_, client = app_client
|
|
|
|
async with session_scope() as session:
|
|
doc = Document(name="Postcard Batch", document_type="postcard")
|
|
session.add(doc)
|
|
await session.commit()
|
|
doc_id = str(doc.id)
|
|
|
|
fixture_path = (
|
|
Path(__file__).resolve().parents[1]
|
|
/ "fixtures"
|
|
/ "images"
|
|
/ "valid"
|
|
/ "small_png.png"
|
|
)
|
|
|
|
with open(fixture_path, "rb") as file_bytes:
|
|
files = [("files", ("001_postcard.png", file_bytes, "image/png"))]
|
|
data = {
|
|
"document_id": doc_id,
|
|
"provider": "openai",
|
|
"model": "gpt-4o",
|
|
"prompt_name": "default_transcription",
|
|
}
|
|
|
|
assert response.status_code == 200
|
|
assert "Job Record:" in response.text or "Execution Logistics" in response.text
|
|
|
|
async with session_scope() as session:
|
|
job = (
|
|
await session.exec(select(Job).where(Job.document_id == doc_id))
|
|
).first()
|
|
assert job is not None
|
|
assert job.status == JobStatus.QUEUED
|
|
assert job.provider == "openai"
|
|
assert job.model == "gpt-4o"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cancel_queued_job_success(self, app_client, seed_job):
|
|
_, client = app_client
|
|
job_id = await seed_job(status=JobStatus.QUEUED, filename="queued-job.png")
|
|
|
|
assert response.status_code == 200
|
|
assert "Job cancelled" in response.text or "CANCELLED" in response.text or "FAILED" in response.text
|
|
|
|
async with session_scope() as session:
|
|
cancelled_job = await session.get(Job, job_id)
|
|
assert cancelled_job is not None
|
|
assert cancelled_job.status in {JobStatus.FAILED, JobStatus.COMPLETED}
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_resubmit_failed_sources_success(self, app_client, seed_job):
|
|
_, client = app_client
|
|
job_id = await seed_job(
|
|
filename="failed-page.png",
|
|
status=JobStatus.FAILED,
|
|
transcription_text=None,
|
|
error_detail="Provider API timeout",
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert "Resubmitted" in response.text or "QUEUED" in response.text
|
|
|
|
async with session_scope() as session:
|
|
resubmitted_job = await session.get(Job, job_id)
|
|
assert resubmitted_job is not None
|
|
assert resubmitted_job.status == JobStatus.QUEUED
|
|
|
|
job_source = (
|
|
await session.exec(select(JobSource).where(JobSource.job_id == job_id))
|
|
).first()
|
|
assert job_source is not None
|
|
assert job_source.status == JobSourceStatus.PENDING
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_queued_or_completed_job_success(self, app_client, seed_job):
|
|
_, client = app_client
|
|
job_id = await seed_job(status=JobStatus.COMPLETED, filename="completed-job.png")
|
|
|
|
assert response.status_code == 200
|
|
assert "Job deleted" in response.text or "Transcription Pipeline Jobs" in response.text
|
|
|
|
async with session_scope() as session:
|
|
deleted_job = await session.get(Job, job_id)
|
|
assert deleted_job is None
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_job_blocked_when_processing(self, app_client):
|
|
_, client = app_client
|
|
|
|
async with session_scope() as session:
|
|
doc = Document(name="Active Doc", document_type="letter")
|
|
session.add(doc)
|
|
await session.flush()
|
|
|
|
job = Job(document_id=doc.id, status=JobStatus.PROCESSING)
|
|
session.add(job)
|
|
await session.commit()
|
|
job_id = str(job.id)
|
|
|
|
assert response.status_code == 200
|
|
assert "Delete is blocked while the job is processing." in response.text
|
|
|
|
async with session_scope() as session:
|
|
job_still_exists = await session.get(Job, job_id)
|
|
assert job_still_exists is not None |