from __future__ import annotations from types import SimpleNamespace import pytest from fastapi import FastAPI from httpx import ASGITransport, AsyncClient from app.api.ai_steward_api import routes_capture from app.core.database import get_db from app.dependencies.auth import get_current_user from app.dependencies.tenant import get_tenant_id from app.services.ai_steward_service import AIStewardService @pytest.mark.asyncio async def test_project_from_text_returns_enveloped_signal_sources(monkeypatch) -> None: async def fake_create_project_from_natural_language(self, **kwargs): # noqa: ANN001 _ = (self, kwargs) return { "project": {"id": "11", "name": "AI 客服", "title": "AI 客服平台", "description": "demo", "status": "active"}, "signal": {"id": "21", "content": "main signal", "impact_score": 0.91}, "charter": {"id": "31", "title": "宪章", "content": {"summary": "demo"}}, "tasks": [], "risks": [], "analysis": { "project_name": "AI 客服", "project_title": "AI 客服平台", "tech_stack": ["FastAPI", "React"], "timeline": "3 周", "primary_role": "backend", "requirement_items": [ { "section": "核心痛点", "title": "内容本地化", "description": "翻译公司贵、慢、不地道", } ], }, "signal_sources": [ { "id": "101", "source_kind": "custom", "source_name": "核心痛点 - 内容本地化", "source_identifier": "custom:core-pain-content-localization", "description": "翻译公司贵、慢、不地道", "section": "核心痛点", } ], } async def _fake_get_db(): yield object() monkeypatch.setattr(AIStewardService, "create_project_from_natural_language", fake_create_project_from_natural_language) app = FastAPI() app.include_router(routes_capture.router) app.dependency_overrides[get_db] = _fake_get_db app.dependency_overrides[get_tenant_id] = lambda: 1 app.dependency_overrides[get_current_user] = lambda: SimpleNamespace( id=9, tenant_id=1, name="管理员", username="admin", role="ADMIN", ) transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post("/ai-steward/project-from-text", json={"input_text": "我们要做一个 AI 客服工具"}) assert response.status_code == 200 payload = response.json() assert payload["code"] == 0 assert payload["message"] == "success" assert payload["data"]["project"]["id"] == "11" assert payload["data"]["signal_sources"][0]["source_name"] == "核心痛点 - 内容本地化"