"""Tests for GET /api/health/schema endpoint in musehub. Covers: - 200 {"ok": true} when schema matches ORM - 503 {"ok": false, "drift": [...]} when schema drift is detected - 503 on unexpected engine errors Run targeted: docker compose exec musehub pytest tests/test_health_schema.py -v """ from __future__ import annotations from unittest.mock import AsyncMock, MagicMock, patch import pytest from httpx import AsyncClient async def test_health_schema_returns_200_when_ok(client: AsyncClient) -> None: """Returns 200 {"ok": true} when assert_schema_matches_orm succeeds.""" with ( patch("musehub.db.database.get_engine", return_value=MagicMock()), patch( "musehub.db.schema_check.assert_schema_matches_orm", new_callable=AsyncMock, ), ): resp = await client.get("/api/health/schema") assert resp.status_code == 200 assert resp.json() == {"ok": True} async def test_health_schema_returns_503_on_drift(client: AsyncClient) -> None: """Returns 503 with drift list when assert_schema_matches_orm raises RuntimeError.""" error_msg = ( "Schema drift detected — 1 mismatch(es):\n" " • musehub_proposals.'breakage_count': nullable mismatch (ORM=False, DB=True)" ) with ( patch("musehub.db.database.get_engine", return_value=MagicMock()), patch( "musehub.db.schema_check.assert_schema_matches_orm", new_callable=AsyncMock, side_effect=RuntimeError(error_msg), ), ): resp = await client.get("/api/health/schema") assert resp.status_code == 503 body = resp.json() assert body["ok"] is False assert isinstance(body["drift"], list) assert len(body["drift"]) == 1 assert "breakage_count" in body["drift"][0] async def test_health_schema_returns_503_when_engine_unavailable(client: AsyncClient) -> None: """Returns 503 when the engine is not initialised yet.""" with patch( "musehub.db.database.get_engine", side_effect=RuntimeError("Database not initialized"), ): resp = await client.get("/api/health/schema") assert resp.status_code == 503 body = resp.json() assert body["ok"] is False