from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock import sys import pytest from gateway.config import PlatformConfig def _ensure_discord_mock(): if "discord" in sys.modules and hasattr(sys.modules["discord"], "__file__"): return discord_mod = MagicMock() discord_mod.Intents.default.return_value = MagicMock() discord_mod.Client = MagicMock discord_mod.File = MagicMock discord_mod.DMChannel = type("DMChannel", (), {}) discord_mod.Thread = type("Thread", (), {}) discord_mod.ForumChannel = type("ForumChannel", (), {}) discord_mod.ui = SimpleNamespace(View=object, button=lambda *a, **k: (lambda fn: fn), Button=object) discord_mod.ButtonStyle = SimpleNamespace(success=1, primary=2, secondary=2, danger=3, green=1, grey=2, blurple=2, red=3) discord_mod.Color = SimpleNamespace(orange=lambda: 1, green=lambda: 2, blue=lambda: 3, red=lambda: 4, purple=lambda: 5) discord_mod.Interaction = object discord_mod.Embed = MagicMock discord_mod.app_commands = SimpleNamespace( describe=lambda **kwargs: (lambda fn: fn), choices=lambda **kwargs: (lambda fn: fn), Choice=lambda **kwargs: SimpleNamespace(**kwargs), ) ext_mod = MagicMock() commands_mod = MagicMock() commands_mod.Bot = MagicMock ext_mod.commands = commands_mod sys.modules.setdefault("discord", discord_mod) sys.modules.setdefault("discord.ext", ext_mod) sys.modules.setdefault("discord.ext.commands", commands_mod) _ensure_discord_mock() from gateway.platforms.discord import DiscordAdapter # noqa: E402 @pytest.mark.asyncio async def test_send_retries_without_reference_when_reply_target_is_system_message(): adapter = DiscordAdapter(PlatformConfig(enabled=True, token="***")) ref_msg = SimpleNamespace(id=99) sent_msg = SimpleNamespace(id=1234) send_calls = [] async def fake_send(*, content, reference=None): send_calls.append({"content": content, "reference": reference}) if len(send_calls) == 1: raise RuntimeError( "400 Bad Request (error code: 50035): Invalid Form Body\n" "In message_reference: Cannot reply to a system message" ) return sent_msg channel = SimpleNamespace( fetch_message=AsyncMock(return_value=ref_msg), send=AsyncMock(side_effect=fake_send), ) adapter._client = SimpleNamespace( get_channel=lambda _chat_id: channel, fetch_channel=AsyncMock(), ) result = await adapter.send("555", "hello", reply_to="99") assert result.success is True assert result.message_id == "1234" assert channel.fetch_message.await_count == 1 assert channel.send.await_count == 2 assert send_calls[0]["reference"] is ref_msg assert send_calls[1]["reference"] is None