from collections.abc import AsyncIterator from uuid import uuid4 import pytest from fastapi.testclient import TestClient from sqlalchemy import delete, select from sqlalchemy.ext.asyncio import AsyncSession from app.api.controllers.agent_runs import get_session from app.api.dependencies.auth import build_request_context from app.core.contracts import RequestContext from app.infrastructure.db import SessionFactory from app.main import app from app.model.conversation import ConversationMessage from app.model.platform import AgentRun, RequestIdempotency pytestmark = pytest.mark.usefixtures("acceptance_registry") async def override_context() -> RequestContext: return RequestContext(user_id="1", trace_id=str(uuid4()), roles=("customer",), permissions=("agent:run",)) async def override_session() -> AsyncIterator[AsyncSession]: async with SessionFactory() as session: yield session @pytest.mark.integration def test_create_agent_run_returns_202_and_addresses() -> None: session_id = f"api-integration-{uuid4()}" key = f"api-key-{uuid4()}" app.dependency_overrides[build_request_context] = override_context app.dependency_overrides[get_session] = override_session try: with TestClient(app) as client: response = client.post( "/api/v1/agent-runs", json={ "agent_type": "customer_service", "message": "api test", "session_id": session_id, "idempotency_key": key, }, ) assert response.status_code == 202 # 文档 §3.3/§6.2:受理响应是 {data, meta} 信封,业务字段在 data 里。 body = response.json()["data"] assert body["run_id"] assert body["trace_id"] assert body["status"] == "queued" assert body["status_url"].endswith(body["run_id"]) finally: async def cleanup() -> None: async with SessionFactory() as session: run = await session.scalar( select(AgentRun).join(ConversationMessage, AgentRun.request_message_id == ConversationMessage.id).where( ConversationMessage.session_id == session_id ) ) if run is not None: await session.execute(delete(AgentRun).where(AgentRun.id == run.id)) await session.execute( delete(RequestIdempotency).where( RequestIdempotency.id == run.idempotency_id ) ) await session.execute( delete(ConversationMessage).where(ConversationMessage.session_id == session_id) ) await session.commit() import asyncio asyncio.run(cleanup()) app.dependency_overrides.clear()