89 lines
3.4 KiB
Python
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, "已收到,正在执行。")
|
|
|