wonq-backend / tests /test_api.py
Aaron
Sync backend with GitHub main (ce306d7): model registry expansion, ensemble OCR, FLD lines, Qwen3.6 AI analysis, opencv-contrib for cloud FLD support
d9106f7
Raw History Blame Contribute Delete
5.07 kB
"""
Integration tests for the FastAPI endpoints using TestClient.
"""
import io
import pytest
from fastapi.testclient import TestClient
class TestHealthEndpoint:
def test_returns_200(self, client):
resp = client.get("/health")
assert resp.status_code == 200
def test_status_is_healthy(self, client):
data = client.get("/health").json()
assert data["status"] == "healthy"
def test_all_processors_listed(self, client):
data = client.get("/health").json()
processors = data["processors"]
for name in ("image_enhancer", "line_extractor", "ocr_processor", "svg_generator"):
assert name in processors
class TestInfoEndpoint:
def test_returns_200(self, client):
assert client.get("/api/info").status_code == 200
def test_returns_processing_options(self, client):
data = client.get("/api/info").json()
assert "processing_options" in data
def test_all_options_listed(self, client):
opts = client.get("/api/info").json()["processing_options"]
for key in ("enhance", "extract_lines", "run_ocr", "generate_svg", "run_ai"):
assert key in opts
class TestProcessEndpoint:
def test_returns_200_with_valid_image(self, client, drawing_file):
resp = client.post("/api/process", files={"file": drawing_file})
assert resp.status_code == 200
def test_response_has_required_fields(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
for field in ("filename", "original_size", "processing_steps", "processing_time_s"):
assert field in data
def test_enhance_step_runs_by_default(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
assert "image_enhancement" in data["processing_steps"]
assert "enhanced_image" in data
def test_line_extraction_step_runs_by_default(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
assert "line_extraction" in data["processing_steps"]
assert "detected_lines" in data
def test_ocr_step_runs_by_default(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
assert "ocr" in data["processing_steps"]
assert "ocr_results" in data
def test_svg_not_generated_by_default(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
assert "svg_generation" not in data["processing_steps"]
def test_svg_generated_when_requested(self, client, drawing_file):
resp = client.post(
"/api/process",
files={"file": drawing_file},
data={"generate_svg": "true"},
)
data = resp.json()
assert "svg_generation" in data["processing_steps"]
assert "svg_output" in data
def test_enhance_only_skips_other_steps(self, client, drawing_file):
resp = client.post(
"/api/process",
files={"file": drawing_file},
data={"enhance": "true", "extract_lines": "false", "run_ocr": "false"},
)
data = resp.json()
assert "image_enhancement" in data["processing_steps"]
assert "line_extraction" not in data["processing_steps"]
assert "ocr" not in data["processing_steps"]
def test_detected_lines_is_integer(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
assert isinstance(data.get("detected_lines"), int)
def test_processing_time_is_float(self, client, drawing_file):
data = client.post("/api/process", files={"file": drawing_file}).json()
assert isinstance(data["processing_time_s"], float)
assert data["processing_time_s"] > 0
def test_invalid_file_returns_400(self, client):
fake_file = ("bad.png", io.BytesIO(b"not an image"), "image/png")
resp = client.post("/api/process", files={"file": fake_file})
assert resp.status_code == 400
def test_original_size_matches_image(self, client, drawing_bytes):
# Our synthetic image is 800×600
file = ("drawing.png", io.BytesIO(drawing_bytes), "image/png")
data = client.post("/api/process", files={"file": file}).json()
size = data["original_size"]
assert size["width"] == 800
assert size["height"] == 600
class TestAnalyzeEndpoint:
def test_returns_501_without_api_key(self, client, drawing_file, monkeypatch):
monkeypatch.setenv("ANTHROPIC_API_KEY", "")
resp = client.post("/api/analyze", files={"file": drawing_file})
assert resp.status_code == 501
def test_error_message_mentions_api_key(self, client, drawing_file, monkeypatch):
monkeypatch.setenv("ANTHROPIC_API_KEY", "")
data = client.post("/api/analyze", files={"file": drawing_file}).json()
assert "ANTHROPIC_API_KEY" in data["detail"]