Align API error envelopes
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import HTTPException
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.main import app, create_app
|
||||
|
||||
|
||||
def assert_contract_error(payload: dict, code: str) -> None:
|
||||
assert payload["error"] == code
|
||||
assert isinstance(payload["message"], str)
|
||||
assert "details" in payload
|
||||
assert "request_id" in payload
|
||||
|
||||
|
||||
def test_app_error_uses_top_level_api_error_contract() -> None:
|
||||
client = TestClient(app)
|
||||
|
||||
response = client.get("/api/v1/external/providers/unknown")
|
||||
|
||||
assert response.status_code == 404
|
||||
assert_contract_error(response.json(), "PROVIDER_NOT_FOUND")
|
||||
assert response.json()["message"] == "Provider not found"
|
||||
|
||||
|
||||
def test_http_exception_uses_top_level_api_error_contract() -> None:
|
||||
test_app = create_app()
|
||||
|
||||
@test_app.get("/__test__/http-error")
|
||||
def raise_http_error() -> None:
|
||||
raise HTTPException(status_code=404, detail="Project not found")
|
||||
|
||||
client = TestClient(test_app)
|
||||
response = client.get("/__test__/http-error")
|
||||
|
||||
assert response.status_code == 404
|
||||
assert_contract_error(response.json(), "HTTP_ERROR")
|
||||
assert response.json()["message"] == "Project not found"
|
||||
|
||||
|
||||
def test_validation_error_uses_top_level_api_error_contract() -> None:
|
||||
client = TestClient(app)
|
||||
|
||||
response = client.get("/api/v1/projects/not-a-uuid")
|
||||
|
||||
assert response.status_code == 422
|
||||
assert_contract_error(response.json(), "VALIDATION_ERROR")
|
||||
assert response.json()["message"] == "Validation failed"
|
||||
assert isinstance(response.json()["details"], list)
|
||||
@@ -0,0 +1,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def test_frontend_api_client_accepts_top_level_error_contract() -> None:
|
||||
client = (ROOT / "frontend" / "src" / "services" / "api" / "client.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert 'typeof payload?.error === "string"' in client
|
||||
assert "payload?.message" in client
|
||||
assert "payload?.details" in client
|
||||
|
||||
|
||||
def test_frontend_api_client_remains_legacy_error_tolerant() -> None:
|
||||
client = (ROOT / "frontend" / "src" / "services" / "api" / "client.ts").read_text(encoding="utf-8")
|
||||
|
||||
assert "legacyError?.code" in client
|
||||
assert "legacyError?.message" in client
|
||||
assert "legacyError?.details" in client
|
||||
@@ -103,7 +103,8 @@ def test_provider_api_envelopes_and_invalid_provider() -> None:
|
||||
|
||||
invalid_response = client.get("/api/v1/external/providers/unknown")
|
||||
assert invalid_response.status_code == 404
|
||||
assert invalid_response.json()["error"]["code"] == "PROVIDER_NOT_FOUND"
|
||||
assert invalid_response.json()["error"] == "PROVIDER_NOT_FOUND"
|
||||
assert invalid_response.json()["message"] == "Provider not found"
|
||||
|
||||
|
||||
def test_provider_import_api_returns_clear_not_configured_response() -> None:
|
||||
|
||||
Reference in New Issue
Block a user