"""Tests for system routes — health, version. These tests use the FastAPI TestClient against the real app. The health and version endpoints do NOT require authentication, so we can test them without setting up the full dependency injection. """ import pytest from fastapi.testclient import TestClient from ledgrab import __version__ from ledgrab.config import get_config def _auth_headers() -> dict[str, str]: """Resolve the configured API key lazily so test ordering doesn't matter. Evaluating ``get_config()`` at module import time produced a stale empty key when other tests mutated the global config before this module ran. """ api_key = next(iter(get_config().auth.api_keys.values()), "") return {"Authorization": f"Bearer {api_key}"} if api_key else {} @pytest.fixture(scope="module") def client(): """Provide a test client for the main app. The app module initializes stores from the default config on import, which is acceptable for read-only endpoints tested here. """ from ledgrab.main import app return TestClient(app, raise_server_exceptions=False) class TestHealthEndpoint: def test_health_returns_200(self, client): resp = client.get("/health") assert resp.status_code == 200 def test_health_response_structure(self, client): data = client.get("/health").json() assert data["status"] == "healthy" assert data["version"] == __version__ assert "timestamp" in data def test_health_no_auth_required(self, client): """Health endpoint should work without Authorization header.""" resp = client.get("/health") assert resp.status_code == 200 class TestVersionEndpoint: def test_version_returns_200(self, client): resp = client.get("/api/v1/version") assert resp.status_code == 200 def test_version_response_fields(self, client): data = client.get("/api/v1/version").json() assert data["version"] == __version__ assert "python_version" in data assert data["api_version"] == "v1" assert "demo_mode" in data class TestOpenAPIEndpoint: def test_openapi_available(self, client): resp = client.get("/openapi.json", headers=_auth_headers()) assert resp.status_code == 200 data = resp.json() assert "info" in data assert data["info"]["version"] == __version__ def test_swagger_ui(self, client): resp = client.get("/docs", headers=_auth_headers()) assert resp.status_code == 200 assert "text/html" in resp.headers["content-type"] def test_openapi_requires_auth(self, client): """Without a valid bearer token, the OpenAPI surface is unreachable.""" resp = client.get("/openapi.json") assert resp.status_code == 401 def test_swagger_requires_auth(self, client): resp = client.get("/docs") assert resp.status_code == 401 class TestRootEndpoint: def test_root_returns_html(self, client): resp = client.get("/") assert resp.status_code == 200 assert "text/html" in resp.headers["content-type"]