from fastapi.testclient import TestClient from app.main import app def test_health() -> None: client = TestClient(app) response = client.get("/health") assert response.status_code == 200 body = response.json() assert body["status"] == "ok" def test_health_head_ok_no_body() -> None: """HEAD /health — то, что реально шлёт внешний uptime-monitor через Caddy (`handle /health { reverse_proxy backend:8000 }`, Caddyfile:60), не GET. Starlette не добавляет HEAD автоматически к `@app.get()` (в отличие от низкоуровневого `Route(methods=["GET"])`) — без явного `@app.head()` прод-эндпоинт отдаёт 405 на HEAD. """ client = TestClient(app) response = client.head("/health") assert response.status_code == 200 assert response.content == b"" # RFC 9110 §9.3.2 — заголовки представления (Content-Type) должны совпадать # с GET; Content-Length допустимо не совпадать (payload header field, MAY # быть опущен для HEAD). assert response.headers["content-type"] == "application/json"