"""Tests for the AI health check script (scripts/ai_health_check.py).""" from __future__ import annotations import json import os import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest # Add scripts dir to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts")) def test_enumerate_routes_returns_api_routes(): """enumerate_routes should return only /api/ routes with methods.""" from ai_health_check import enumerate_routes routes = enumerate_routes() assert isinstance(routes, list) assert len(routes) > 0 for route in routes: assert route["path"].startswith("/api/") assert isinstance(route["methods"], list) assert len(route["methods"]) > 0 def test_enumerate_routes_excludes_non_api(): """enumerate_routes should not include non-API paths like /docs or /openapi.json.""" from ai_health_check import enumerate_routes routes = enumerate_routes() paths = [r["path"] for r in routes] assert not any(p.startswith("/docs") for p in paths) assert not any(p.startswith("/openapi") for p in paths) def test_format_json_report_structure(): """JSON report should have summary and endpoints keys.""" from ai_health_check import format_json_report results = [ {"endpoint": "/api/v1/health", "method": "GET", "status": 200, "response_time_ms": 5.0, "healthy": True, "tags": ["health"], "note": ""}, {"endpoint": "/api/v1/users", "method": "POST", "status": "skipped", "response_time_ms": 0, "healthy": True, "tags": ["users"], "note": "Non-GET method — documented only"}, ] report = json.loads(format_json_report(results)) assert "summary" in report assert "endpoints" in report assert report["summary"]["total_endpoints"] == 2 assert report["summary"]["healthy"] == 1 assert report["summary"]["skipped"] == 1 assert report["summary"]["all_healthy"] is True def test_format_json_report_with_failures(): """JSON report should mark all_healthy=False when failures exist.""" from ai_health_check import format_json_report results = [ {"endpoint": "/api/v1/health", "method": "GET", "status": 200, "response_time_ms": 5.0, "healthy": True, "tags": [], "note": ""}, {"endpoint": "/api/v1/broken", "method": "GET", "status": 500, "response_time_ms": 10.0, "healthy": False, "tags": [], "note": "HTTP 500"}, ] report = json.loads(format_json_report(results)) assert report["summary"]["failed"] == 1 assert report["summary"]["all_healthy"] is False def test_format_csv_report_has_header(): """CSV report should have a header row with expected columns.""" from ai_health_check import format_csv_report results = [ {"endpoint": "/api/v1/health", "method": "GET", "status": 200, "response_time_ms": 5.0, "healthy": True, "tags": ["health"], "note": ""}, ] csv_output = format_csv_report(results) lines = csv_output.strip().split("\n") assert "endpoint" in lines[0] assert "method" in lines[0] assert "status" in lines[0] assert "/api/v1/health" in lines[1] @pytest.mark.asyncio async def test_probe_all_endpoints_skips_non_get(): """probe_all_endpoints should skip POST/PUT/DELETE methods.""" from ai_health_check import probe_all_endpoints routes = [ {"path": "/api/v1/users", "methods": ["POST"], "tags": ["users"]}, ] results = await probe_all_endpoints("http://localhost:8000", "fake-token", routes) assert len(results) == 1 assert results[0]["status"] == "skipped" assert results[0]["healthy"] is True @pytest.mark.asyncio async def test_probe_all_endpoints_handles_connection_error(): """probe_all_endpoints should handle connection errors gracefully.""" from ai_health_check import probe_all_endpoints routes = [ {"path": "/api/v1/health", "methods": ["GET"], "tags": ["health"]}, ] results = await probe_all_endpoints("http://nonexistent-host:9999", "fake-token", routes) assert len(results) == 1 assert results[0]["healthy"] is False assert results[0]["status"] in ("connection_error", "error")