# #region Test.Api.Health [C:3] [TYPE Module] [SEMANTICS test,health,api] # @BRIEF Unit tests for health API routes — summary, delete report. # @RELATION BINDS_TO -> [health_router] # @TEST_EDGE: feature_disabled -> 404 # @TEST_EDGE: report_not_found -> 404 # @TEST_EDGE: environment_filter -> 200 import os os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:") os.environ.setdefault("AUTH_DATABASE_URL", "sqlite:///:memory:") os.environ.setdefault("SECRET_KEY", "test-secret-key-for-tests") import sys from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import FastAPI from fastapi.testclient import TestClient _src = str(Path(__file__).resolve().parent.parent.parent / "src") if _src not in sys.path: sys.path.insert(0, _src) def _make_client(overrides: dict | None = None) -> TestClient: from src.api.routes.health import router from src.core.database import get_db from src.dependencies import get_config_manager, get_current_user, get_task_manager, has_permission from src.schemas.auth import User, RoleSchema app = FastAPI() app.include_router(router) mock_user = User( id="admin-1", username="admin", email="admin@x.com", auth_source="LOCAL", created_at=__import__("datetime").datetime.now(), roles=[RoleSchema(id="r1", name="Admin", description="", permissions=[])], ) defaults = { get_db: lambda: MagicMock(), get_config_manager: lambda: MagicMock(), get_task_manager: lambda: MagicMock(), get_current_user: lambda: mock_user, } if overrides: defaults.update(overrides) for dep, mock_fn in defaults.items(): app.dependency_overrides[dep] = mock_fn return TestClient(app) class TestGetHealthSummary: """GET /api/health/summary""" def test_summary_success(self): """Happy path: returns health summary.""" mock_config = MagicMock() mock_config.get_config.return_value.settings.features.health_monitor = True mock_service = AsyncMock() mock_service.get_health_summary.return_value = { "items": [], "pass_count": 0, "warn_count": 0, "fail_count": 0, "unknown_count": 0, } with patch("src.api.routes.health.HealthService", return_value=mock_service): from src.dependencies import get_config_manager client = _make_client({get_config_manager: lambda: mock_config}) resp = client.get("/api/health/summary") assert resp.status_code == 200 def test_summary_with_environment_filter(self): """Environment filter passed to service.""" mock_config = MagicMock() mock_config.get_config.return_value.settings.features.health_monitor = True mock_service = AsyncMock() mock_service.get_health_summary.return_value = { "items": [], "pass_count": 0, "warn_count": 0, "fail_count": 0, "unknown_count": 0, } with patch("src.api.routes.health.HealthService", return_value=mock_service): from src.dependencies import get_config_manager client = _make_client({get_config_manager: lambda: mock_config}) resp = client.get("/api/health/summary?environment_id=prod") assert resp.status_code == 200 mock_service.get_health_summary.assert_called_with(environment_id="prod") def test_summary_feature_disabled(self): """Health monitor disabled returns 404.""" mock_config = MagicMock() mock_config.get_config.return_value.settings.features.health_monitor = False from src.dependencies import get_config_manager client = _make_client({get_config_manager: lambda: mock_config}) resp = client.get("/api/health/summary") assert resp.status_code == 404 assert "Health monitor feature is disabled" in resp.text class TestDeleteHealthReport: """DELETE /api/health/summary/{record_id}""" def test_delete_report_success(self): """Happy path: report deleted returns 204.""" mock_config = MagicMock() mock_config.get_config.return_value.settings.features.health_monitor = True mock_service = MagicMock() mock_service.delete_validation_report.return_value = True with patch("src.api.routes.health.HealthService", return_value=mock_service): from src.dependencies import get_config_manager, get_task_manager client = _make_client({ get_config_manager: lambda: mock_config, get_task_manager: lambda: MagicMock(), }) resp = client.delete("/api/health/summary/rec-1") assert resp.status_code == 204 mock_service.delete_validation_report.assert_called_once() def test_delete_report_not_found(self): """Non-existent report returns 404.""" mock_config = MagicMock() mock_config.get_config.return_value.settings.features.health_monitor = True mock_service = MagicMock() mock_service.delete_validation_report.return_value = False with patch("src.api.routes.health.HealthService", return_value=mock_service): from src.dependencies import get_config_manager, get_task_manager client = _make_client({ get_config_manager: lambda: mock_config, get_task_manager: lambda: MagicMock(), }) resp = client.delete("/api/health/summary/rec-missing") assert resp.status_code == 404 assert "Health report not found" in resp.text def test_delete_report_feature_disabled(self): """Health monitor disabled returns 404.""" mock_config = MagicMock() mock_config.get_config.return_value.settings.features.health_monitor = False from src.dependencies import get_config_manager, get_task_manager client = _make_client({ get_config_manager: lambda: mock_config, get_task_manager: lambda: MagicMock(), }) resp = client.delete("/api/health/summary/rec-1") assert resp.status_code == 404 # #endregion Test.Api.Health