mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 15:01:34 +08:00
- Fix duplicate 'timezone' import in e2e conftest - Fix test_text_before_command_not_detected asserting send() is awaited when no agent is present in mock setup (text messages don't produce command output)
107 lines
4.0 KiB
Python
107 lines
4.0 KiB
Python
"""Minimal e2e tests for Discord mention stripping + /command detection.
|
|
|
|
Covers the fix for slash commands not being recognized when sent via
|
|
@mention in a channel, especially after auto-threading.
|
|
"""
|
|
|
|
import asyncio
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
|
|
from tests.e2e.conftest import (
|
|
BOT_USER_ID,
|
|
E2E_MESSAGE_SETTLE_DELAY,
|
|
get_response_text,
|
|
make_discord_message,
|
|
make_fake_dm_channel,
|
|
make_fake_thread,
|
|
)
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
|
|
async def dispatch(adapter, msg):
|
|
await adapter._handle_message(msg)
|
|
await asyncio.sleep(E2E_MESSAGE_SETTLE_DELAY)
|
|
|
|
|
|
class TestMentionStrippedCommandDispatch:
|
|
async def test_mention_then_command(self, discord_adapter, bot_user):
|
|
"""<@BOT> /help → mention stripped, /help dispatched."""
|
|
msg = make_discord_message(
|
|
content=f"<@{BOT_USER_ID}> /help",
|
|
mentions=[bot_user],
|
|
)
|
|
await dispatch(discord_adapter, msg)
|
|
response = get_response_text(discord_adapter)
|
|
assert response is not None
|
|
assert "/new" in response
|
|
|
|
async def test_nickname_mention_then_command(self, discord_adapter, bot_user):
|
|
"""<@!BOT> /help → nickname mention also stripped, /help works."""
|
|
msg = make_discord_message(
|
|
content=f"<@!{BOT_USER_ID}> /help",
|
|
mentions=[bot_user],
|
|
)
|
|
await dispatch(discord_adapter, msg)
|
|
response = get_response_text(discord_adapter)
|
|
assert response is not None
|
|
assert "/new" in response
|
|
|
|
async def test_text_before_command_not_detected(self, discord_adapter, bot_user):
|
|
"""'<@BOT> something else /help' → mention stripped, but 'something else /help'
|
|
doesn't start with / so it's treated as text, not a command."""
|
|
msg = make_discord_message(
|
|
content=f"<@{BOT_USER_ID}> something else /help",
|
|
mentions=[bot_user],
|
|
)
|
|
await dispatch(discord_adapter, msg)
|
|
# Message is accepted (not dropped by mention gate), but since it doesn't
|
|
# start with / it's routed as text — no command output, and no agent in this
|
|
# mock setup means no send call either.
|
|
response = get_response_text(discord_adapter)
|
|
assert response is None or "/new" not in response
|
|
|
|
async def test_no_mention_in_channel_dropped(self, discord_adapter):
|
|
"""Message without @mention in server channel → silently dropped."""
|
|
msg = make_discord_message(content="/help", mentions=[])
|
|
await dispatch(discord_adapter, msg)
|
|
assert get_response_text(discord_adapter) is None
|
|
|
|
async def test_dm_no_mention_needed(self, discord_adapter):
|
|
"""DMs don't require @mention — /help works directly."""
|
|
dm = make_fake_dm_channel()
|
|
msg = make_discord_message(content="/help", channel=dm, mentions=[])
|
|
await dispatch(discord_adapter, msg)
|
|
response = get_response_text(discord_adapter)
|
|
assert response is not None
|
|
assert "/new" in response
|
|
|
|
|
|
class TestAutoThreadingPreservesCommand:
|
|
async def test_command_detected_after_auto_thread(self, discord_adapter, bot_user, monkeypatch):
|
|
"""@mention /help in channel with auto-thread → thread created AND command dispatched."""
|
|
monkeypatch.setenv("DISCORD_AUTO_THREAD", "true")
|
|
fake_thread = make_fake_thread(thread_id=90001, name="help")
|
|
msg = make_discord_message(
|
|
content=f"<@{BOT_USER_ID}> /help",
|
|
mentions=[bot_user],
|
|
)
|
|
|
|
# Simulate discord.py restoring the original raw content (with mention)
|
|
# after create_thread(), which undoes any prior mention stripping.
|
|
original_content = msg.content
|
|
|
|
async def clobber_content(**kwargs):
|
|
msg.content = original_content
|
|
return fake_thread
|
|
|
|
msg.create_thread = AsyncMock(side_effect=clobber_content)
|
|
await dispatch(discord_adapter, msg)
|
|
|
|
msg.create_thread.assert_awaited_once()
|
|
response = get_response_text(discord_adapter)
|
|
assert response is not None
|
|
assert "/new" in response
|