"""Telegram Help must retain inline buttons in both command and chat modes.""" import sys import unittest from pathlib import Path from types import SimpleNamespace from unittest.mock import AsyncMock, patch BASE = Path(__file__).resolve().parents[1] sys.path[:0] = [str(BASE / "bot-utility"), str(BASE)] import main class FakeTGChannel: tg_username = "test_bot" @staticmethod def is_admin(uid): return True def private_message(text="/help"): return SimpleNamespace( from_user=SimpleNamespace(id=123, is_bot=False), chat=SimpleNamespace(id=123, type="private"), text=text, caption=None, photo=[], entities=[], ) class TelegramHelpTests(unittest.IsolatedAsyncioTestCase): async def run_root_help(self, mode): bot = SimpleNamespace(send_message=AsyncMock(), id=999) store = SimpleNamespace(get_mode=lambda *args: mode) with patch.object(main, "ModeStore", return_value=store), \ patch.object(main.identity, "resolve", return_value=1), \ patch.object(main.help_ui, "chat_help", new=AsyncMock(return_value="chat help")) as chat_help, \ patch.object(main, "handle_message", new=AsyncMock()) as dispatch: await main.make_tg_handler(FakeTGChannel())(private_message(), bot) return bot, chat_help, dispatch async def test_command_root_help_has_buttons(self): bot, chat_help, dispatch = await self.run_root_help("command") kwargs = bot.send_message.await_args.kwargs self.assertIsNotNone(kwargs.get("reply_markup")) self.assertIn("服务列表", bot.send_message.await_args.args[1]) chat_help.assert_not_awaited() dispatch.assert_not_awaited() async def test_chat_root_help_has_buttons_and_skips_legacy_dispatch(self): bot, chat_help, dispatch = await self.run_root_help("chat") kwargs = bot.send_message.await_args.kwargs self.assertIsNotNone(kwargs.get("reply_markup")) self.assertEqual(bot.send_message.await_args.args[1], "chat help") chat_help.assert_awaited_once_with(1, None, True) dispatch.assert_not_awaited() async def test_chat_help_callback_keeps_buttons_and_mode_aware_content(self): bot = SimpleNamespace(send_message=AsyncMock()) callback = SimpleNamespace( from_user=SimpleNamespace(id=123), message=SimpleNamespace(chat=SimpleNamespace(id=123, type="private")), data="help:1", answer=AsyncMock(), ) store = SimpleNamespace(get_mode=lambda *args: "chat") with patch.object(main, "ModeStore", return_value=store), \ patch.object(main.identity, "resolve", return_value=1), \ patch.object(main.help_ui, "chat_help", new=AsyncMock(return_value="setu chat help")) as chat_help: await main.make_tg_help_callback(FakeTGChannel())(callback, bot) chat_help.assert_awaited_once_with(1, "setu", True) self.assertEqual(bot.send_message.await_args.args[1], "setu chat help") self.assertIsNotNone(bot.send_message.await_args.kwargs.get("reply_markup")) if __name__ == "__main__": unittest.main()