from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] BACKEND = ROOT / "backend" def test_no_untyped_fastapi_response_models_remain() -> None: route_root = BACKEND / "app" / "api" / "routes" route_sources = "\n".join( path.read_text(encoding="utf-8") for path in sorted(route_root.glob("*.py")) ) assert "response_model=dict" not in route_sources def test_every_json_success_response_has_a_concrete_canonical_schema() -> None: sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(BACKEND)) from app.main import create_app from scripts.audit_api_contracts import ( ALLOWED_NON_ENVELOPE_ENDPOINTS, _validate_response_contracts, ) openapi = create_app().openapi() assert _validate_response_contracts(openapi) == [] untyped_successes: set[tuple[str, str]] = set() for path, path_item in openapi["paths"].items(): for method, operation in path_item.items(): if method.upper() not in {"GET", "POST", "PATCH", "DELETE"}: continue has_json_schema = any( response.get("content", {}) .get("application/json", {}) .get("schema") for code, response in operation.get("responses", {}).items() if str(code).startswith("2") ) if not has_json_schema: untyped_successes.add((method.upper(), path)) assert untyped_successes == ALLOWED_NON_ENVELOPE_ENDPOINTS - { ("GET", "/health"), ("GET", "/health/live"), ("GET", "/health/ready"), }