Initial import of Shirobana bot backend
Include utility modules, shared channels, prompts, read-only skills, wardrobe memory and regression tests. Externalize legacy credentials and exclude private runtime state.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user