"""Health check 엔드포인트 테스트.""" import pytest from contextlib import asynccontextmanager from unittest.mock import AsyncMock, MagicMock, patch import httpx @asynccontextmanager async def mock_lifespan(app): """테스트용 mock lifespan.""" yield @pytest.mark.asyncio async def test_health_basic(): """기본 health check가 200을 반환한다.""" from agent.webapp import app # Override lifespan for testing app.router.lifespan_context = mock_lifespan async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health") assert resp.status_code == 200 data = resp.json() assert data["status"] == "ok" @pytest.mark.asyncio async def test_health_queue(): """큐 health check가 pending 카운트를 반환한다.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan mock_queue = MagicMock() mock_queue.get_pending = AsyncMock(return_value=[{"id": "1"}, {"id": "2"}]) with patch("agent.task_queue.get_task_queue", new_callable=AsyncMock, return_value=mock_queue): async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/queue") assert resp.status_code == 200 data = resp.json() assert data["status"] == "ok" assert data["pending_tasks"] == 2 @pytest.mark.asyncio async def test_health_queue_empty(): """큐가 비어있을 때 0을 반환한다.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan mock_queue = MagicMock() mock_queue.get_pending = AsyncMock(return_value=[]) with patch("agent.task_queue.get_task_queue", new_callable=AsyncMock, return_value=mock_queue): async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/queue") assert resp.status_code == 200 data = resp.json() assert data["status"] == "ok" assert data["pending_tasks"] == 0 @pytest.mark.asyncio async def test_health_discord_not_configured(): """Discord가 설정되지 않았을 때.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan # Ensure no discord_handler on app.state if hasattr(app.state, "discord_handler"): delattr(app.state, "discord_handler") async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/discord") assert resp.status_code == 200 data = resp.json() assert data["status"] == "not_configured" @pytest.mark.asyncio async def test_health_discord_ready(): """Discord 봇이 준비되었을 때.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan mock_bot = MagicMock() mock_bot.is_ready.return_value = True mock_bot.user = "TestBot#1234" mock_handler = MagicMock() mock_handler.bot = mock_bot app.state.discord_handler = mock_handler async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/discord") assert resp.status_code == 200 data = resp.json() assert data["status"] == "ok" assert data["user"] == "TestBot#1234" @pytest.mark.asyncio async def test_health_discord_connecting(): """Discord 봇이 연결 중일 때.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan mock_bot = MagicMock() mock_bot.is_ready.return_value = False mock_handler = MagicMock() mock_handler.bot = mock_bot app.state.discord_handler = mock_handler async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/discord") assert resp.status_code == 200 data = resp.json() assert data["status"] == "connecting" @pytest.mark.asyncio async def test_health_gitea_ok(): """Gitea API 연결이 성공할 때.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan mock_response = MagicMock() mock_response.status_code = 200 mock_client = MagicMock() mock_client._client.get = AsyncMock(return_value=mock_response) with patch("agent.utils.gitea_client.get_gitea_client", return_value=mock_client): async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/gitea") assert resp.status_code == 200 data = resp.json() assert data["status"] == "ok" assert data["gitea_status_code"] == 200 @pytest.mark.asyncio async def test_health_gitea_error(): """Gitea API 연결이 실패할 때.""" from agent.webapp import app app.router.lifespan_context = mock_lifespan with patch("agent.utils.gitea_client.get_gitea_client", side_effect=Exception("Connection failed")): async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: resp = await client.get("/health/gitea") assert resp.status_code == 200 data = resp.json() assert data["status"] == "error" assert "Connection failed" in data["error"]