75 lines
2.9 KiB
Python
75 lines
2.9 KiB
Python
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()
|