Files
nanobot/tests/channels/test_slack_channel.py
Hua 35b8f4f3cd
Some checks failed
Test Suite / test (3.11) (push) Failing after 1m0s
Test Suite / test (3.12) (push) Failing after 19s
Test Suite / test (3.13) (push) Failing after 18s
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	nanobot/agent/tools/shell.py
#	tests/agent/test_evaluator.py
#	tests/channels/test_feishu_tool_hint_code_block.py
#	tests/providers/test_litellm_kwargs.py
#	tests/tools/test_web_search_tool.py
2026-03-24 16:38:50 +08:00

154 lines
4.4 KiB
Python

from __future__ import annotations
import pytest
# Check optional Slack dependencies before running tests
try:
import slack_sdk # noqa: F401
except ImportError:
pytest.skip("Slack dependencies not installed (slack-sdk)", allow_module_level=True)
from nanobot.bus.events import OutboundMessage
from nanobot.bus.queue import MessageBus
from nanobot.channels.slack import SlackChannel
from nanobot.config.schema import SlackConfig
class _FakeAsyncWebClient:
def __init__(self) -> None:
self.chat_post_calls: list[dict[str, object | None]] = []
self.file_upload_calls: list[dict[str, object | None]] = []
self.reactions_add_calls: list[dict[str, object | None]] = []
self.reactions_remove_calls: list[dict[str, object | None]] = []
async def chat_postMessage(
self,
*,
channel: str,
text: str,
thread_ts: str | None = None,
) -> None:
self.chat_post_calls.append(
{
"channel": channel,
"text": text,
"thread_ts": thread_ts,
}
)
async def files_upload_v2(
self,
*,
channel: str,
file: str,
thread_ts: str | None = None,
) -> None:
self.file_upload_calls.append(
{
"channel": channel,
"file": file,
"thread_ts": thread_ts,
}
)
async def reactions_add(
self,
*,
channel: str,
name: str,
timestamp: str,
) -> None:
self.reactions_add_calls.append(
{
"channel": channel,
"name": name,
"timestamp": timestamp,
}
)
async def reactions_remove(
self,
*,
channel: str,
name: str,
timestamp: str,
) -> None:
self.reactions_remove_calls.append(
{
"channel": channel,
"name": name,
"timestamp": timestamp,
}
)
@pytest.mark.asyncio
async def test_send_uses_thread_for_channel_messages() -> None:
channel = SlackChannel(SlackConfig(enabled=True), MessageBus())
fake_web = _FakeAsyncWebClient()
channel._web_client = fake_web
await channel.send(
OutboundMessage(
channel="slack",
chat_id="C123",
content="hello",
media=["/tmp/demo.txt"],
metadata={"slack": {"thread_ts": "1700000000.000100", "channel_type": "channel"}},
)
)
assert len(fake_web.chat_post_calls) == 1
assert fake_web.chat_post_calls[0]["text"] == "hello\n"
assert fake_web.chat_post_calls[0]["thread_ts"] == "1700000000.000100"
assert len(fake_web.file_upload_calls) == 1
assert fake_web.file_upload_calls[0]["thread_ts"] == "1700000000.000100"
@pytest.mark.asyncio
async def test_send_omits_thread_for_dm_messages() -> None:
channel = SlackChannel(SlackConfig(enabled=True), MessageBus())
fake_web = _FakeAsyncWebClient()
channel._web_client = fake_web
await channel.send(
OutboundMessage(
channel="slack",
chat_id="D123",
content="hello",
media=["/tmp/demo.txt"],
metadata={"slack": {"thread_ts": "1700000000.000100", "channel_type": "im"}},
)
)
assert len(fake_web.chat_post_calls) == 1
assert fake_web.chat_post_calls[0]["text"] == "hello\n"
assert fake_web.chat_post_calls[0]["thread_ts"] is None
assert len(fake_web.file_upload_calls) == 1
assert fake_web.file_upload_calls[0]["thread_ts"] is None
@pytest.mark.asyncio
async def test_send_updates_reaction_when_final_response_sent() -> None:
channel = SlackChannel(SlackConfig(enabled=True, react_emoji="eyes"), MessageBus())
fake_web = _FakeAsyncWebClient()
channel._web_client = fake_web
await channel.send(
OutboundMessage(
channel="slack",
chat_id="C123",
content="done",
metadata={
"slack": {"event": {"ts": "1700000000.000100"}, "channel_type": "channel"},
},
)
)
assert fake_web.reactions_remove_calls == [
{"channel": "C123", "name": "eyes", "timestamp": "1700000000.000100"}
]
assert fake_web.reactions_add_calls == [
{"channel": "C123", "name": "white_check_mark", "timestamp": "1700000000.000100"}
]