PMFlow/backend/tests/test_ai_steward_capture_fei...

89 lines
3.4 KiB
Python

import os
import tempfile
import unittest
from unittest.mock import AsyncMock, patch
from sqlalchemy import and_, select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from app.api.ai_steward import FeishuCaptureRequest, capture_feishu_signal
from app.models import Base, FeishuReplyOutbox, User
class CaptureFeishuSignalApiTest(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self) -> None:
tmp = tempfile.NamedTemporaryFile(prefix="pmflow-ai-steward-capture-", suffix=".db", delete=False)
tmp.close()
self.db_path = tmp.name
self.engine = create_async_engine(f"sqlite+aiosqlite:///{self.db_path}", future=True)
self.session_factory = async_sessionmaker(self.engine, expire_on_commit=False, class_=AsyncSession)
async with self.engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async def asyncTearDown(self) -> None:
await self.engine.dispose()
if getattr(self, "db_path", None):
try:
os.remove(self.db_path)
except FileNotFoundError:
pass
async def test_capture_feishu_signal_enqueues_outbox_when_direct_reply_required(self) -> None:
async with self.session_factory() as db:
user = User(
tenant_id=1,
username="capture_admin",
email="capture_admin@example.com",
password_hash="hash",
name="捕获管理员",
role="ADMIN",
status="active",
is_active=True,
)
db.add(user)
await db.commit()
await db.refresh(user)
with patch(
"app.api.ai_steward.ProactiveSignalCaptureService.capture_from_feishu",
AsyncMock(
return_value={
"handled": True,
"status": "captured",
"classification": "signal",
"ai_trace_id": "ai-pmo-123",
"direct_reply_required": True,
"direct_reply_text": "已收到,正在执行。",
}
),
):
payload = await capture_feishu_signal(
request=FeishuCaptureRequest(
group_chat_id="oc_test_001",
message_content="给 AI 劝退助手加一个复杂需求",
sender="老板",
feishu_message_id="om_test_001",
),
current_user=user,
db=db,
tenant_id=1,
)
self.assertTrue(payload["reply_outbox_enqueued"])
self.assertIsInstance(payload["reply_outbox_id"], int)
row = (
await db.execute(
select(FeishuReplyOutbox).where(
and_(
FeishuReplyOutbox.tenant_id == 1,
FeishuReplyOutbox.source_message_id == "om_test_001",
)
)
)
).scalar_one_or_none()
self.assertIsNotNone(row)
assert row is not None
self.assertEqual(row.chat_id, "oc_test_001")
self.assertEqual(row.message_text, "已收到,正在执行。")