test_home_guild.py 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """Tests du serveur du bot : rien n'est accepté ailleurs. Lancer depuis la racine du projet : python -m unittest"""
  2. import unittest
  3. from unittest import mock
  4. import discord
  5. from discord import app_commands
  6. from bot.discord_bot import ChatBot, HomeTree
  7. from bot.memory_views import ERROR_MESSAGE
  8. HOME, OTHER = 1000, 2000
  9. CHANNEL_ID = 10
  10. def fake_bot(channel_found: bool = True) -> mock.Mock:
  11. bot = mock.Mock()
  12. bot.settings.channel_id = CHANNEL_ID
  13. bot.get_channel.return_value = mock.Mock(guild=mock.Mock(id=HOME)) if channel_found else None
  14. bot.home_guild_id = lambda: ChatBot.home_guild_id(bot)
  15. bot.handle_main_channel = mock.AsyncMock()
  16. bot.handle_mention = mock.AsyncMock()
  17. bot.register_members = mock.AsyncMock()
  18. return bot
  19. def fake_interaction(guild_id: int | None) -> mock.Mock:
  20. interaction = mock.Mock(guild_id=guild_id, type=discord.InteractionType.application_command,
  21. data={"name": "memoire-serveur"})
  22. interaction.response.send_message = mock.AsyncMock()
  23. return interaction
  24. class CommandsTest(unittest.IsolatedAsyncioTestCase):
  25. async def check(self, interaction: mock.Mock, channel_found: bool = True) -> bool:
  26. tree = object.__new__(HomeTree) # sans client Discord réel
  27. tree.client = fake_bot(channel_found)
  28. return await tree.interaction_check(interaction)
  29. async def test_home_guild_accepted(self):
  30. interaction = fake_interaction(HOME)
  31. self.assertTrue(await self.check(interaction))
  32. interaction.response.send_message.assert_not_awaited()
  33. async def test_other_guild_refused(self):
  34. # Administrateur d'un autre serveur où le bot a été invité : ni lecture ni écriture de la mémoire.
  35. interaction = fake_interaction(OTHER)
  36. self.assertFalse(await self.check(interaction))
  37. interaction.response.send_message.assert_awaited_once()
  38. async def test_direct_message_refused(self):
  39. self.assertFalse(await self.check(fake_interaction(None)))
  40. async def test_refused_while_channel_unknown(self):
  41. self.assertFalse(await self.check(fake_interaction(HOME), channel_found=False))
  42. async def test_command_error_reported(self):
  43. # Une exception dans une commande : un message à la personne, plus le seul « Échec de l'interaction ».
  44. interaction = fake_interaction(HOME)
  45. interaction.response.is_done.return_value = False
  46. tree = object.__new__(HomeTree)
  47. with self.assertLogs("chatbot.discord", "ERROR"):
  48. await tree.on_error(interaction, app_commands.AppCommandError("panne"))
  49. self.assertEqual(interaction.response.send_message.call_args.args[0], ERROR_MESSAGE)
  50. class MessagesTest(unittest.IsolatedAsyncioTestCase):
  51. async def receive(self, guild: mock.Mock | None, channel_id: int = CHANNEL_ID) -> mock.Mock:
  52. bot = fake_bot()
  53. message = mock.Mock(guild=guild, webhook_id=None, type=discord.MessageType.default)
  54. message.channel.id = channel_id
  55. message.author.bot = False
  56. message.mentions = [bot.user]
  57. await ChatBot.on_message(bot, message)
  58. return bot
  59. async def test_home_guild_answered(self):
  60. bot = await self.receive(mock.Mock(id=HOME))
  61. bot.handle_main_channel.assert_awaited_once()
  62. async def test_other_guild_ignored(self):
  63. # Même un salon qui porte le même identifiant ou une mention : rien n'est lu ni noté.
  64. bot = await self.receive(mock.Mock(id=OTHER))
  65. bot.handle_main_channel.assert_not_awaited()
  66. bot.handle_mention.assert_not_awaited()
  67. bot.register_members.assert_not_awaited()
  68. async def test_direct_message_ignored(self):
  69. bot = await self.receive(None, channel_id=99)
  70. bot.handle_mention.assert_not_awaited()
  71. bot.register_members.assert_not_awaited()
  72. if __name__ == "__main__":
  73. unittest.main()