Spaces:
Running
Running
| import io | |
| import pytest | |
| from main import create_app | |
| from config import Config | |
| class TestConfig(Config): | |
| API_KEY = "test-key-123" | |
| DEBUG = True | |
| def app(): | |
| app = create_app(TestConfig) | |
| app.config["TESTING"] = True | |
| return app | |
| def client(app): | |
| return app.test_client() | |
| class TestHealthCheck: | |
| def test_health_no_auth_required(self, client): | |
| resp = client.get("/health") | |
| assert resp.status_code in (200, 503) | |
| data = resp.get_json() | |
| assert "status" in data | |
| assert "uptime_seconds" in data | |
| def test_health_returns_checks(self, client): | |
| resp = client.get("/health") | |
| data = resp.get_json() | |
| assert "checks" in data | |
| assert "upload_directory" in data["checks"] | |
| class TestAuth: | |
| def test_no_api_key_returns_401(self, client): | |
| resp = client.post("/api/ocr") | |
| assert resp.status_code == 401 | |
| def test_wrong_api_key_returns_401(self, client): | |
| resp = client.post("/api/ocr", headers={"X-API-Key": "wrong-key"}) | |
| assert resp.status_code == 401 | |
| def test_correct_api_key_passes_auth(self, client): | |
| # Will get 400 (no doc_type) but not 401 | |
| resp = client.post("/api/ocr", headers={"X-API-Key": "test-key-123"}) | |
| assert resp.status_code == 400 | |
| class TestOCREndpoint: | |
| def test_missing_doc_type_returns_400(self, client): | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| ) | |
| assert resp.status_code == 400 | |
| assert "doc_type is required" in resp.get_json()["error"] | |
| def test_invalid_doc_type_returns_400(self, client): | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| data={"doc_type": "invalid_type"}, | |
| ) | |
| assert resp.status_code == 400 | |
| assert "Invalid doc_type" in resp.get_json()["error"] | |
| def test_no_file_returns_400(self, client): | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| data={"doc_type": "sa_id_card"}, | |
| ) | |
| assert resp.status_code == 400 | |
| assert "No front image" in resp.get_json()["error"] | |
| def test_invalid_file_type_returns_400(self, client): | |
| data = { | |
| "front": (io.BytesIO(b"not an image"), "test.txt"), | |
| "doc_type": "sa_id_card", | |
| } | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| data=data, | |
| content_type="multipart/form-data", | |
| ) | |
| assert resp.status_code == 400 | |
| assert "Invalid file type" in resp.get_json()["error"] | |
| def test_back_rejected_for_non_id_card(self, client): | |
| data = { | |
| "front": (io.BytesIO(b"\x89PNG\r\n"), "front.png"), | |
| "back": (io.BytesIO(b"\x89PNG\r\n"), "back.png"), | |
| "doc_type": "sa_id_book", | |
| } | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| data=data, | |
| content_type="multipart/form-data", | |
| ) | |
| assert resp.status_code == 400 | |
| assert "only accepted for doc_type=sa_id_card" in resp.get_json()["error"] | |
| def test_legacy_file_key_accepted(self, client): | |
| """Legacy 'file' key should work as front image.""" | |
| data = { | |
| "file": (io.BytesIO(b"not an image"), "test.txt"), | |
| "doc_type": "sa_id_card", | |
| } | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| data=data, | |
| content_type="multipart/form-data", | |
| ) | |
| # 400 for invalid file type (not 400 for missing file) | |
| assert resp.status_code == 400 | |
| assert "Invalid file type" in resp.get_json()["error"] | |
| def test_request_id_in_response(self, client): | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123", "X-Request-ID": "test-req-123"}, | |
| data={"doc_type": "sa_id_card"}, | |
| ) | |
| assert resp.headers.get("X-Request-ID") == "test-req-123" | |
| def test_request_id_generated_if_missing(self, client): | |
| resp = client.post( | |
| "/api/ocr", | |
| headers={"X-API-Key": "test-key-123"}, | |
| data={"doc_type": "sa_id_card"}, | |
| ) | |
| assert resp.headers.get("X-Request-ID") is not None | |
| class TestWarmEndpoint: | |
| def test_warm_no_auth_required(self, client): | |
| resp = client.get("/warm") | |
| assert resp.status_code == 200 | |
| data = resp.get_json() | |
| assert "status" in data | |
| assert "engines" in data | |
| class TestNotFound: | |
| def test_unknown_route_returns_404(self, client): | |
| resp = client.get("/api/unknown", headers={"X-API-Key": "test-key-123"}) | |
| assert resp.status_code == 404 | |
| data = resp.get_json() | |
| assert "error" in data | |