100% Coverage

This commit is contained in:
Renn F
2026-05-06 21:02:31 +02:00
parent 64c48356d0
commit 9aa30fb945
106 changed files with 28143 additions and 423 deletions
+37 -11
View File
@@ -2,8 +2,11 @@
from __future__ import annotations
from http import HTTPStatus
from fastapi import FastAPI, HTTPException
from fastapi.testclient import TestClient
from pydantic import BaseModel
from roboco.api.middleware import (
get_status_code,
setup_middleware,
@@ -23,28 +26,30 @@ from roboco.exceptions import (
def test_get_status_code_for_not_found() -> None:
assert get_status_code(NotFoundError("Task", "abc")) == 404
assert get_status_code(NotFoundError("Task", "abc")) == HTTPStatus.NOT_FOUND
def test_get_status_code_for_validation() -> None:
assert get_status_code(ValidationError("x")) == 422
assert get_status_code(ValidationError("x")) == HTTPStatus.UNPROCESSABLE_ENTITY
def test_get_status_code_for_invalid_state() -> None:
assert get_status_code(InvalidStateError("pending", "complete")) == 409
assert (
get_status_code(InvalidStateError("pending", "complete")) == HTTPStatus.CONFLICT
)
def test_get_status_code_for_permission() -> None:
assert get_status_code(PermissionDeniedError("x")) == 403
assert get_status_code(PermissionDeniedError("x")) == HTTPStatus.FORBIDDEN
def test_get_status_code_for_auth() -> None:
assert get_status_code(AuthenticationError("x")) == 401
assert get_status_code(AuthenticationError("x")) == HTTPStatus.UNAUTHORIZED
def test_get_status_code_for_generic() -> None:
"""Unknown RobocoError subclass defaults to 400."""
assert get_status_code(RobocoError("x", code="other")) == 400
assert get_status_code(RobocoError("x", code="other")) == HTTPStatus.BAD_REQUEST
# ---------------------------------------------------------------------------
@@ -78,7 +83,7 @@ def _make_app() -> FastAPI:
def test_middleware_adds_correlation_id_header() -> None:
client = TestClient(_make_app())
response = client.get("/ok")
assert response.status_code == 200
assert response.status_code == HTTPStatus.OK
assert "X-Correlation-ID" in response.headers
@@ -95,16 +100,16 @@ def test_middleware_adds_response_time_header() -> None:
assert "X-Response-Time-Ms" in response.headers
def test_roboco_exception_translates_to_404(caplog) -> None:
def test_roboco_exception_translates_to_404() -> None:
client = TestClient(_make_app(), raise_server_exceptions=False)
response = client.get("/notfound")
assert response.status_code == 404
assert response.status_code == HTTPStatus.NOT_FOUND
def test_http_exception_handler_returns_standardized_format() -> None:
client = TestClient(_make_app(), raise_server_exceptions=False)
response = client.get("/http-error")
assert response.status_code == 403
assert response.status_code == HTTPStatus.FORBIDDEN
body = response.json()
assert "error" in body
@@ -112,6 +117,27 @@ def test_http_exception_handler_returns_standardized_format() -> None:
def test_generic_exception_returns_500() -> None:
client = TestClient(_make_app(), raise_server_exceptions=False)
response = client.get("/raise")
assert response.status_code == 500
assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
body = response.json()
assert "error" in body
def test_request_validation_handler_returns_422_with_details() -> None:
"""request_validation_handler logs + returns 422 with errors+body (251-260)."""
class _Body(BaseModel):
name: str
app = FastAPI()
setup_middleware(app)
@app.post("/validate")
async def _v(_data: _Body):
return {"ok": True}
client = TestClient(app, raise_server_exceptions=False)
response = client.post("/validate", json={"wrong_field": "x"})
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
body = response.json()
assert "detail" in body
assert "body" in body