"""接口集成测试。""" import fakeredis.aioredis import pytest import pytest_asyncio from httpx import ASGITransport, AsyncClient from app.config import settings from app.main import app AUTH = settings.gateway_auth ADMIN_AUTH = settings.admin_auth @pytest_asyncio.fixture async def client(): server = fakeredis.FakeServer() redis = fakeredis.aioredis.FakeRedis(server=server, decode_responses=True) app.state.redis = redis transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as c: yield c await redis.aclose() @pytest.mark.asyncio async def test_health(client): r = await client.get("/health") assert r.status_code == 200 assert r.json()["status"] == "ok" @pytest.mark.asyncio async def test_submit_and_query_task(client): r = await client.post("/api/cli/tasks", json={"auth": AUTH, "task_type": "compile", "task_tags": ["build"]}) assert r.status_code == 200 data = r.json() assert data["status"] == "pending" rid = data["request_id"] r2 = await client.get(f"/api/cli/tasks/{rid}", params={"auth": AUTH}) assert r2.status_code == 200 assert r2.json()["request_id"] == rid @pytest.mark.asyncio async def test_agent_register_heartbeat_result(client): # 注册 r = await client.post("/api/agent/register", json={"auth": AUTH, "agent_id": "a1", "endpoint": "e1", "agent_tags": ["compile"], "max_concurrent": 2}) assert r.status_code == 200 # 心跳 r = await client.post("/api/agent/heartbeat", json={"auth": AUTH, "agent_id": "a1", "current_load": 0}) assert r.status_code == 200 # 提交任务并等待调度(手动触发一次调度) r = await client.post("/api/cli/tasks", json={"auth": AUTH, "task_type": "compile", "task_tags": ["compile"]}) rid = r.json()["request_id"] from app.services.scheduler import Scheduler await Scheduler(app.state.redis).dispatch_pending(10) # 回传结果 r = await client.post("/api/agent/result", json={"auth": AUTH, "request_id": rid, "agent_id": "a1", "status": "success", "progress": 100, "result": {"ok": True}}) assert r.status_code == 200 detail = await client.get(f"/api/cli/tasks/{rid}", params={"auth": AUTH}) assert detail.json()["status"] == "success" @pytest.mark.asyncio async def test_admin_overview(client): r = await client.get("/api/admin/overview", headers={"X-Admin-Auth": ADMIN_AUTH}) assert r.status_code == 200 assert "task_total" in r.json() @pytest.mark.asyncio async def test_admin_rejects_bad_auth(client): r = await client.get("/api/admin/overview", headers={"X-Admin-Auth": "wrong-admin"}) assert r.status_code == 401 @pytest.mark.asyncio async def test_admin_requires_auth(client): r = await client.get("/api/admin/overview") assert r.status_code == 422 # 缺 X-Admin-Auth header @pytest.mark.asyncio async def test_agent_heartbeat_rejects_bad_auth(client): r = await client.post("/api/agent/heartbeat", json={"auth": "wrong", "agent_id": "x1", "current_load": 0}) assert r.status_code == 401 @pytest.mark.asyncio async def test_cli_query_rejects_bad_auth(client): r = await client.get("/api/cli/tasks/whatever", params={"auth": "wrong"}) assert r.status_code == 401 @pytest.mark.asyncio async def test_submit_task_rejects_bad_auth(client): r = await client.post("/api/cli/tasks", json={"auth": "wrong-password", "task_type": "compile"}) assert r.status_code == 401 @pytest.mark.asyncio async def test_submit_task_requires_auth(client): r = await client.post("/api/cli/tasks", json={"task_type": "compile"}) assert r.status_code == 422 # 缺 auth 字段 @pytest.mark.asyncio async def test_agent_register_rejects_bad_auth(client): r = await client.post("/api/agent/register", json={"auth": "wrong-password", "agent_id": "a9", "endpoint": "e9"}) assert r.status_code == 401