Files
OpenOPC/tests/test_channel_runtime_integration.py
T
2026-07-01 17:56:31 +08:00

137 lines
4.9 KiB
Python

from __future__ import annotations
import contextlib
import shutil
import unittest
import uuid
from pathlib import Path
from opc.channels.email import EmailChannel
from opc.channels.slack import SlackChannel
from opc.channels.telegram import TelegramChannel
from opc.channels.whatsapp import WhatsAppChannel
from opc.core.config import OPCConfig
from opc.core.models import SystemMessage
from opc.layer0_interaction.message_bus import MessageBus
@contextlib.contextmanager
def _workspace_tempdir() -> Path:
base = Path.cwd() / ".tmp-test" / f"channel-runtime-{uuid.uuid4().hex}"
base.mkdir(parents=True, exist_ok=True)
try:
yield base
finally:
shutil.rmtree(base, ignore_errors=True)
class ChannelProviderRuntimeTests(unittest.IsolatedAsyncioTestCase):
async def test_email_send_sets_reply_headers(self) -> None:
config = OPCConfig()
config.channels.email.consent_granted = True
config.channels.email.imap_host = "imap.example.com"
config.channels.email.imap_username = "bot@example.com"
config.channels.email.imap_password = "secret"
config.channels.email.smtp_host = "smtp.example.com"
config.channels.email.smtp_username = "bot@example.com"
config.channels.email.smtp_password = "secret"
channel = EmailChannel(config.channels.email, MessageBus())
channel._last_subject_by_chat["user@example.com"] = "Original subject"
channel._last_message_id_by_chat["user@example.com"] = "<abc@example.com>"
sent = {}
def fake_smtp_send(message):
sent["message"] = message
channel._smtp_send = fake_smtp_send # type: ignore[method-assign]
await channel.send(
SystemMessage(
channel="email",
user_id="u",
session_id="sess",
content="hello",
metadata={"chat_id": "user@example.com"},
)
)
message = sent["message"]
self.assertEqual(message["To"], "user@example.com")
self.assertEqual(message["In-Reply-To"], "<abc@example.com>")
self.assertEqual(message["References"], "<abc@example.com>")
async def test_telegram_send_splits_messages_and_uses_reply(self) -> None:
config = OPCConfig()
config.channels.telegram.reply_to_message = True
channel = TelegramChannel(config.channels.telegram, MessageBus())
calls = []
class _Bot:
async def send_message(self, **kwargs):
calls.append(("message", kwargs))
async def send_document(self, **kwargs):
calls.append(("document", kwargs))
channel._bot = _Bot()
with _workspace_tempdir() as tmpdir:
attachment = tmpdir / "a.txt"
attachment.write_text("demo")
await channel.send(
SystemMessage(
channel="telegram",
user_id="u",
session_id="7",
content="x" * 4500,
metadata={"chat_id": "7", "reply_to": "11", "attachments": [str(attachment)]},
)
)
self.assertEqual(calls[0][0], "message")
self.assertEqual(calls[0][1]["reply_to_message_id"], 11)
self.assertEqual(calls[-1][0], "document")
async def test_slack_socket_event_produces_thread_scoped_session(self) -> None:
config = OPCConfig()
config.channels.slack.allow_from = ["*"]
bus = MessageBus()
channel = SlackChannel(config.channels.slack, bus)
channel._bot_user_id = "bot-1"
class _Client:
async def send_socket_mode_response(self, response):
return response
class _Req:
type = "events_api"
envelope_id = "env-1"
payload = {
"event": {
"type": "app_mention",
"user": "u1",
"channel": "c1",
"text": "<@bot-1> hi",
"thread_ts": "th-1",
"ts": "msg-1",
"channel_type": "channel",
}
}
await channel._on_socket_request(_Client(), _Req())
message = await bus._inbound_queue.get()
self.assertEqual(message.session_id, "slack:c1:th-1")
self.assertEqual(message.content, "hi")
async def test_whatsapp_bridge_message_publishes_inbound(self) -> None:
config = OPCConfig()
config.channels.whatsapp.allow_from = ["*"]
bus = MessageBus()
channel = WhatsAppChannel(config.channels.whatsapp, bus)
await channel._handle_bridge_message(
'{"type":"message","id":"m1","sender":"12345@s.whatsapp.net","message":{"chat_id":"12345@s.whatsapp.net","text":"hello"}}'
)
message = await bus._inbound_queue.get()
self.assertEqual(message.user_id, "12345")
self.assertEqual(message.metadata["chat_id"], "12345@s.whatsapp.net")