diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/__init__.py | 3 | ||||
| -rw-r--r-- | tests/base.py | 5 | ||||
| -rw-r--r-- | tests/bot/exts/backend/sync/test_base.py | 1 | ||||
| -rw-r--r-- | tests/bot/exts/backend/sync/test_cog.py | 7 | ||||
| -rw-r--r-- | tests/bot/exts/backend/sync/test_users.py | 7 | ||||
| -rw-r--r-- | tests/bot/exts/backend/test_error_handler.py | 2 | ||||
| -rw-r--r-- | tests/bot/exts/events/test_code_jams.py | 4 | ||||
| -rw-r--r-- | tests/bot/exts/filters/test_token_remover.py | 17 | ||||
| -rw-r--r-- | tests/bot/exts/info/test_information.py | 5 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/infraction/test_infractions.py | 14 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/infraction/test_utils.py | 20 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/test_incidents.py | 15 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/test_silence.py | 73 | ||||
| -rw-r--r-- | tests/bot/test_converters.py | 8 | ||||
| -rw-r--r-- | tests/bot/utils/test_checks.py | 1 | ||||
| -rw-r--r-- | tests/helpers.py | 34 | ||||
| -rw-r--r-- | tests/test_base.py | 11 | 
17 files changed, 143 insertions, 84 deletions
| diff --git a/tests/__init__.py b/tests/__init__.py index 2228110ad..c2b9d12dc 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,6 @@  import logging +from bot.log import get_logger -log = logging.getLogger() +log = get_logger()  log.setLevel(logging.CRITICAL) diff --git a/tests/base.py b/tests/base.py index d99b9ac31..5e304ea9d 100644 --- a/tests/base.py +++ b/tests/base.py @@ -6,6 +6,7 @@ from typing import Dict  import discord  from discord.ext import commands +from bot.log import get_logger  from tests import helpers @@ -42,7 +43,7 @@ class LoggingTestsMixin:          manager when we're testing under the assumption that no log records will be emitted.          """          if not isinstance(logger, logging.Logger): -            logger = logging.getLogger(logger) +            logger = get_logger(logger)          if level:              level = logging._nameToLevel.get(level, level) @@ -102,4 +103,4 @@ class CommandTestCase(unittest.IsolatedAsyncioTestCase):          with self.assertRaises(commands.MissingPermissions) as cm:              await cmd.can_run(ctx) -        self.assertCountEqual(permissions.keys(), cm.exception.missing_perms) +        self.assertCountEqual(permissions.keys(), cm.exception.missing_permissions) diff --git a/tests/bot/exts/backend/sync/test_base.py b/tests/bot/exts/backend/sync/test_base.py index 3ad9db9c3..9dc46005b 100644 --- a/tests/bot/exts/backend/sync/test_base.py +++ b/tests/bot/exts/backend/sync/test_base.py @@ -1,7 +1,6 @@  import unittest  from unittest import mock -  from bot.api import ResponseCodeError  from bot.exts.backend.sync._syncers import Syncer  from tests import helpers diff --git a/tests/bot/exts/backend/sync/test_cog.py b/tests/bot/exts/backend/sync/test_cog.py index 22a07313e..fdd0ab74a 100644 --- a/tests/bot/exts/backend/sync/test_cog.py +++ b/tests/bot/exts/backend/sync/test_cog.py @@ -60,13 +60,13 @@ class SyncCogTestCase(unittest.IsolatedAsyncioTestCase):  class SyncCogTests(SyncCogTestCase):      """Tests for the Sync cog.""" +    @mock.patch("bot.utils.scheduling.create_task")      @mock.patch.object(Sync, "sync_guild", new_callable=mock.MagicMock) -    def test_sync_cog_init(self, sync_guild): +    def test_sync_cog_init(self, sync_guild, create_task):          """Should instantiate syncers and run a sync for the guild."""          # Reset because a Sync cog was already instantiated in setUp.          self.RoleSyncer.reset_mock()          self.UserSyncer.reset_mock() -        self.bot.loop.create_task = mock.MagicMock()          mock_sync_guild_coro = mock.MagicMock()          sync_guild.return_value = mock_sync_guild_coro @@ -74,7 +74,8 @@ class SyncCogTests(SyncCogTestCase):          Sync(self.bot)          sync_guild.assert_called_once_with() -        self.bot.loop.create_task.assert_called_once_with(mock_sync_guild_coro) +        create_task.assert_called_once() +        self.assertEqual(create_task.call_args.args[0], mock_sync_guild_coro)      async def test_sync_cog_sync_guild(self):          """Roles and users should be synced only if a guild is successfully retrieved.""" diff --git a/tests/bot/exts/backend/sync/test_users.py b/tests/bot/exts/backend/sync/test_users.py index 27932be95..2fc97af2d 100644 --- a/tests/bot/exts/backend/sync/test_users.py +++ b/tests/bot/exts/backend/sync/test_users.py @@ -1,6 +1,8 @@  import unittest  from unittest import mock +from discord.errors import NotFound +  from bot.exts.backend.sync._syncers import UserSyncer, _Diff  from tests import helpers @@ -10,7 +12,7 @@ def fake_user(**kwargs):      kwargs.setdefault("id", 43)      kwargs.setdefault("name", "bob the test man")      kwargs.setdefault("discriminator", 1337) -    kwargs.setdefault("roles", [666]) +    kwargs.setdefault("roles", [helpers.MockRole(id=666)])      kwargs.setdefault("in_guild", True)      return kwargs @@ -134,6 +136,7 @@ class UserSyncerDiffTests(unittest.IsolatedAsyncioTestCase):              self.get_mock_member(fake_user()),              None          ] +        guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found")          actual_diff = await UserSyncer._get_diff(guild)          expected_diff = ([], [{"id": 63, "in_guild": False}], None) @@ -158,6 +161,7 @@ class UserSyncerDiffTests(unittest.IsolatedAsyncioTestCase):              self.get_mock_member(updated_user),              None          ] +        guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found")          actual_diff = await UserSyncer._get_diff(guild)          expected_diff = ([new_user], [{"id": 55, "name": "updated"}, {"id": 63, "in_guild": False}], None) @@ -177,6 +181,7 @@ class UserSyncerDiffTests(unittest.IsolatedAsyncioTestCase):              self.get_mock_member(fake_user()),              None          ] +        guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found")          actual_diff = await UserSyncer._get_diff(guild)          expected_diff = ([], [], None) diff --git a/tests/bot/exts/backend/test_error_handler.py b/tests/bot/exts/backend/test_error_handler.py index 2b0549b98..462f718e6 100644 --- a/tests/bot/exts/backend/test_error_handler.py +++ b/tests/bot/exts/backend/test_error_handler.py @@ -107,7 +107,7 @@ class ErrorHandlerTests(unittest.IsolatedAsyncioTestCase):          """Should send error with `ctx.send` when error is `CommandOnCooldown`."""          self.ctx.reset_mock()          cog = ErrorHandler(self.bot) -        error = errors.CommandOnCooldown(10, 9) +        error = errors.CommandOnCooldown(10, 9, type=None)          self.assertIsNone(await cog.on_command_error(self.ctx, error))          self.ctx.send.assert_awaited_once_with(error) diff --git a/tests/bot/exts/events/test_code_jams.py b/tests/bot/exts/events/test_code_jams.py index b9ee1e363..0856546af 100644 --- a/tests/bot/exts/events/test_code_jams.py +++ b/tests/bot/exts/events/test_code_jams.py @@ -8,8 +8,8 @@ from bot.constants import Roles  from bot.exts.events import code_jams  from bot.exts.events.code_jams import _channels, _cog  from tests.helpers import ( -    MockAttachment, MockBot, MockCategoryChannel, MockContext, -    MockGuild, MockMember, MockRole, MockTextChannel, autospec +    MockAttachment, MockBot, MockCategoryChannel, MockContext, MockGuild, MockMember, MockRole, MockTextChannel, +    autospec  )  TEST_CSV = b"""\ diff --git a/tests/bot/exts/filters/test_token_remover.py b/tests/bot/exts/filters/test_token_remover.py index 51feae9cb..4db27269a 100644 --- a/tests/bot/exts/filters/test_token_remover.py +++ b/tests/bot/exts/filters/test_token_remover.py @@ -26,7 +26,7 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          self.msg.guild.get_member.return_value.bot = False          self.msg.guild.get_member.return_value.__str__.return_value = "Woody"          self.msg.author.__str__ = MagicMock(return_value=self.msg.author.name) -        self.msg.author.avatar_url_as.return_value = "picture-lemon.png" +        self.msg.author.display_avatar.url = "picture-lemon.png"      def test_extract_user_id_valid(self):          """Should consider user IDs valid if they decode into an integer ID.""" @@ -295,20 +295,21 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          )      @autospec("bot.exts.filters.token_remover", "UNKNOWN_USER_LOG_MESSAGE") -    def test_format_userid_log_message_unknown(self, unknown_user_log_message): +    async def test_format_userid_log_message_unknown(self, unknown_user_log_message,):          """Should correctly format the user ID portion when the actual user it belongs to is unknown."""          token = Token("NDcyMjY1OTQzMDYyNDEzMzMy", "XsySD_", "s45jqDV_Iisn-symw0yDRrk_jf4")          unknown_user_log_message.format.return_value = " Partner"          msg = MockMessage(id=555, content="hello world")          msg.guild.get_member.return_value = None +        msg.guild.fetch_member.side_effect = NotFound(mock.Mock(status=404), "Not found") -        return_value = TokenRemover.format_userid_log_message(msg, token) +        return_value = await TokenRemover.format_userid_log_message(msg, token)          self.assertEqual(return_value, (unknown_user_log_message.format.return_value, False))          unknown_user_log_message.format.assert_called_once_with(user_id=472265943062413332)      @autospec("bot.exts.filters.token_remover", "KNOWN_USER_LOG_MESSAGE") -    def test_format_userid_log_message_bot(self, known_user_log_message): +    async def test_format_userid_log_message_bot(self, known_user_log_message):          """Should correctly format the user ID portion when the ID belongs to a known bot."""          token = Token("NDcyMjY1OTQzMDYyNDEzMzMy", "XsySD_", "s45jqDV_Iisn-symw0yDRrk_jf4")          known_user_log_message.format.return_value = " Partner" @@ -316,7 +317,7 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          msg.guild.get_member.return_value.__str__.return_value = "Sam"          msg.guild.get_member.return_value.bot = True -        return_value = TokenRemover.format_userid_log_message(msg, token) +        return_value = await TokenRemover.format_userid_log_message(msg, token)          self.assertEqual(return_value, (known_user_log_message.format.return_value, True)) @@ -327,12 +328,12 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          )      @autospec("bot.exts.filters.token_remover", "KNOWN_USER_LOG_MESSAGE") -    def test_format_log_message_user_token_user(self, user_token_message): +    async def test_format_log_message_user_token_user(self, user_token_message):          """Should correctly format the user ID portion when the ID belongs to a known user."""          token = Token("NDY3MjIzMjMwNjUwNzc3NjQx", "XsySD_", "s45jqDV_Iisn-symw0yDRrk_jf4")          user_token_message.format.return_value = "Partner" -        return_value = TokenRemover.format_userid_log_message(self.msg, token) +        return_value = await TokenRemover.format_userid_log_message(self.msg, token)          self.assertEqual(return_value, (user_token_message.format.return_value, True))          user_token_message.format.assert_called_once_with( @@ -375,7 +376,7 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):              colour=Colour(constants.Colours.soft_red),              title="Token removed!",              text=log_msg + "\n" + userid_log_message, -            thumbnail=self.msg.author.avatar_url_as.return_value, +            thumbnail=self.msg.author.display_avatar.url,              channel_id=constants.Channels.mod_alerts,              ping_everyone=True,          ) diff --git a/tests/bot/exts/info/test_information.py b/tests/bot/exts/info/test_information.py index d8250befb..4b50c3fd9 100644 --- a/tests/bot/exts/info/test_information.py +++ b/tests/bot/exts/info/test_information.py @@ -84,7 +84,7 @@ class InformationCogTests(unittest.IsolatedAsyncioTestCase):          self.assertEqual(dummy_embed.fields[0].value, str(dummy_role.id))          self.assertEqual(dummy_embed.fields[1].value, f"#{dummy_role.colour.value:0>6x}") -        self.assertEqual(dummy_embed.fields[2].value, "0.63 0.48 218") +        self.assertEqual(dummy_embed.fields[2].value, "0.65 0.64 242")          self.assertEqual(dummy_embed.fields[3].value, "1")          self.assertEqual(dummy_embed.fields[4].value, "10")          self.assertEqual(dummy_embed.fields[5].value, "0") @@ -435,10 +435,9 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          ctx = helpers.MockContext()          user = helpers.MockMember(id=217, colour=0) -        user.avatar_url_as.return_value = "avatar url" +        user.display_avatar.url = "avatar url"          embed = await self.cog.create_user_embed(ctx, user) -        user.avatar_url_as.assert_called_once_with(static_format="png")          self.assertEqual(embed.thumbnail.url, "avatar url") diff --git a/tests/bot/exts/moderation/infraction/test_infractions.py b/tests/bot/exts/moderation/infraction/test_infractions.py index f844a9181..4d01e18a5 100644 --- a/tests/bot/exts/moderation/infraction/test_infractions.py +++ b/tests/bot/exts/moderation/infraction/test_infractions.py @@ -3,6 +3,8 @@ import textwrap  import unittest  from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch +from discord.errors import NotFound +  from bot.constants import Event  from bot.exts.moderation.infraction import _utils  from bot.exts.moderation.infraction.infractions import Infractions @@ -13,12 +15,13 @@ class TruncationTests(unittest.IsolatedAsyncioTestCase):      """Tests for ban and kick command reason truncation."""      def setUp(self): +        self.me = MockMember(id=7890, roles=[MockRole(id=7890, position=5)])          self.bot = MockBot()          self.cog = Infractions(self.bot) -        self.user = MockMember(id=1234, top_role=MockRole(id=3577, position=10)) -        self.target = MockMember(id=1265, top_role=MockRole(id=9876, position=0)) +        self.user = MockMember(id=1234, roles=[MockRole(id=3577, position=10)]) +        self.target = MockMember(id=1265, roles=[MockRole(id=9876, position=1)])          self.guild = MockGuild(id=4567) -        self.ctx = MockContext(bot=self.bot, author=self.user, guild=self.guild) +        self.ctx = MockContext(me=self.me, bot=self.bot, author=self.user, guild=self.guild)      @patch("bot.exts.moderation.infraction._utils.get_active_infraction")      @patch("bot.exts.moderation.infraction._utils.post_infraction") @@ -64,8 +67,8 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):      def setUp(self):          self.bot = MockBot() -        self.mod = MockMember(top_role=10) -        self.user = MockMember(top_role=1, roles=[MockRole(id=123456)]) +        self.mod = MockMember(roles=[MockRole(id=7890123, position=10)]) +        self.user = MockMember(roles=[MockRole(id=123456, position=1)])          self.guild = MockGuild()          self.ctx = MockContext(bot=self.bot, author=self.mod)          self.cog = Infractions(self.bot) @@ -195,6 +198,7 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):      async def test_voice_unban_user_not_found(self):          """Should include info to return dict when user was not found from guild."""          self.guild.get_member.return_value = None +        self.guild.fetch_member.side_effect = NotFound(Mock(status=404), "Not found")          result = await self.cog.pardon_voice_ban(self.user.id, self.guild)          self.assertEqual(result, {"Info": "User was not found in the guild."}) diff --git a/tests/bot/exts/moderation/infraction/test_utils.py b/tests/bot/exts/moderation/infraction/test_utils.py index eb256f1fd..72eebb254 100644 --- a/tests/bot/exts/moderation/infraction/test_utils.py +++ b/tests/bot/exts/moderation/infraction/test_utils.py @@ -139,14 +139,14 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                          type="Ban",                          expires="2020-02-26 09:20 (23 hours and 59 minutes)",                          reason="No reason provided." -                    ), +                    ) + utils.INFRACTION_APPEAL_SERVER_FOOTER,                      colour=Colours.soft_red,                      url=utils.RULES_URL                  ).set_author(                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.token_removed -                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER), +                ),                  "send_result": True              },              { @@ -157,14 +157,14 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                          type="Warning",                          expires="N/A",                          reason="Test reason." -                    ), +                    ) + utils.INFRACTION_APPEAL_MODMAIL_FOOTER,                      colour=Colours.soft_red,                      url=utils.RULES_URL                  ).set_author(                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.token_removed -                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER), +                ),                  "send_result": False              },              # Note that this test case asserts that the DM that *would* get sent to the user is formatted @@ -177,14 +177,14 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                          type="Note",                          expires="N/A",                          reason="No reason provided." -                    ), +                    ) + utils.INFRACTION_APPEAL_MODMAIL_FOOTER,                      colour=Colours.soft_red,                      url=utils.RULES_URL                  ).set_author(                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.defcon_denied -                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER), +                ),                  "send_result": False              },              { @@ -195,14 +195,14 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                          type="Mute",                          expires="2020-02-26 09:20 (23 hours and 59 minutes)",                          reason="Test" -                    ), +                    ) + utils.INFRACTION_APPEAL_MODMAIL_FOOTER,                      colour=Colours.soft_red,                      url=utils.RULES_URL                  ).set_author(                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.defcon_denied -                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER), +                ),                  "send_result": False              },              { @@ -213,14 +213,14 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                          type="Mute",                          expires="N/A",                          reason="foo bar" * 4000 -                    )[:4093] + "...", +                    )[:4093-utils.LONGEST_EXTRAS] + "..." + utils.INFRACTION_APPEAL_MODMAIL_FOOTER,                      colour=Colours.soft_red,                      url=utils.RULES_URL                  ).set_author(                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.defcon_denied -                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER), +                ),                  "send_result": True              }          ] diff --git a/tests/bot/exts/moderation/test_incidents.py b/tests/bot/exts/moderation/test_incidents.py index cbf7f7bcf..ccc842050 100644 --- a/tests/bot/exts/moderation/test_incidents.py +++ b/tests/bot/exts/moderation/test_incidents.py @@ -3,7 +3,7 @@ import enum  import logging  import typing as t  import unittest -from unittest.mock import AsyncMock, MagicMock, call, patch +from unittest.mock import AsyncMock, MagicMock, Mock, call, patch  import aiohttp  import discord @@ -11,15 +11,8 @@ import discord  from bot.constants import Colours  from bot.exts.moderation import incidents  from tests.helpers import ( -    MockAsyncWebhook, -    MockAttachment, -    MockBot, -    MockMember, -    MockMessage, -    MockReaction, -    MockRole, -    MockTextChannel, -    MockUser, +    MockAsyncWebhook, MockAttachment, MockBot, MockMember, MockMessage, MockReaction, MockRole, MockTextChannel, +    MockUser  ) @@ -379,7 +372,7 @@ class TestArchive(TestIncidents):          # Define our own `incident` to be archived          incident = MockMessage(              content="this is an incident", -            author=MockUser(name="author_name", avatar_url="author_avatar"), +            author=MockUser(name="author_name", display_avatar=Mock(url="author_avatar")),              id=123,          )          built_embed = MagicMock(discord.Embed, id=123)  # We patch `make_embed` to return this diff --git a/tests/bot/exts/moderation/test_silence.py b/tests/bot/exts/moderation/test_silence.py index 59a5893ef..92ce3418a 100644 --- a/tests/bot/exts/moderation/test_silence.py +++ b/tests/bot/exts/moderation/test_silence.py @@ -12,14 +12,7 @@ from discord import PermissionOverwrite  from bot.constants import Channels, Guild, MODERATION_ROLES, Roles  from bot.exts.moderation import silence  from tests.helpers import ( -    MockBot, -    MockContext, -    MockGuild, -    MockMember, -    MockRole, -    MockTextChannel, -    MockVoiceChannel, -    autospec +    MockBot, MockContext, MockGuild, MockMember, MockRole, MockTextChannel, MockVoiceChannel, autospec  )  redis_session = None @@ -438,7 +431,13 @@ class SilenceTests(unittest.IsolatedAsyncioTestCase):          asyncio.run(self.cog._async_init())  # Populate instance attributes.          self.text_channel = MockTextChannel() -        self.text_overwrite = PermissionOverwrite(send_messages=True, add_reactions=False) +        self.text_overwrite = PermissionOverwrite( +            send_messages=True, +            add_reactions=False, +            create_private_threads=True, +            create_public_threads=False, +            send_messages_in_threads=True +        )          self.text_channel.overwrites_for.return_value = self.text_overwrite          self.voice_channel = MockVoiceChannel() @@ -509,9 +508,39 @@ class SilenceTests(unittest.IsolatedAsyncioTestCase):      async def test_skipped_already_silenced(self):          """Permissions were not set and `False` was returned for an already silenced channel."""          subtests = ( -            (False, MockTextChannel(), PermissionOverwrite(send_messages=False, add_reactions=False)), -            (True, MockTextChannel(), PermissionOverwrite(send_messages=True, add_reactions=True)), -            (True, MockTextChannel(), PermissionOverwrite(send_messages=False, add_reactions=False)), +            ( +                False, +                MockTextChannel(), +                PermissionOverwrite( +                    send_messages=False, +                    add_reactions=False, +                    create_private_threads=False, +                    create_public_threads=False, +                    send_messages_in_threads=False +                ) +            ), +            ( +                True, +                MockTextChannel(), +                PermissionOverwrite( +                    send_messages=True, +                    add_reactions=True, +                    create_private_threads=True, +                    create_public_threads=True, +                    send_messages_in_threads=True +                ) +            ), +            ( +                True, +                MockTextChannel(), +                PermissionOverwrite( +                    send_messages=False, +                    add_reactions=False, +                    create_private_threads=False, +                    create_public_threads=False, +                    send_messages_in_threads=False +                ) +            ),              (False, MockVoiceChannel(), PermissionOverwrite(connect=False, speak=False)),              (True, MockVoiceChannel(), PermissionOverwrite(connect=True, speak=True)),              (True, MockVoiceChannel(), PermissionOverwrite(connect=False, speak=False)), @@ -559,11 +588,16 @@ class SilenceTests(unittest.IsolatedAsyncioTestCase):          await self.cog._set_silence_overwrites(self.text_channel)          new_overwrite_dict = dict(self.text_overwrite) -        # Remove 'send_messages' & 'add_reactions' keys because they were changed by the method. -        del prev_overwrite_dict['send_messages'] -        del prev_overwrite_dict['add_reactions'] -        del new_overwrite_dict['send_messages'] -        del new_overwrite_dict['add_reactions'] +        # Remove related permission keys because they were changed by the method. +        for perm_name in ( +                "send_messages", +                "add_reactions", +                "create_private_threads", +                "create_public_threads", +                "send_messages_in_threads" +        ): +            del prev_overwrite_dict[perm_name] +            del new_overwrite_dict[perm_name]          self.assertDictEqual(prev_overwrite_dict, new_overwrite_dict) @@ -601,7 +635,10 @@ class SilenceTests(unittest.IsolatedAsyncioTestCase):      async def test_cached_previous_overwrites(self):          """Channel's previous overwrites were cached.""" -        overwrite_json = '{"send_messages": true, "add_reactions": false}' +        overwrite_json = ( +            '{"send_messages": true, "add_reactions": false, "create_private_threads": true, ' +            '"create_public_threads": false, "send_messages_in_threads": true}' +        )          await self.cog._set_silence_overwrites(self.text_channel)          self.cog.previous_overwrites.set.assert_awaited_once_with(self.text_channel.id, overwrite_json) diff --git a/tests/bot/test_converters.py b/tests/bot/test_converters.py index 6e3a6b898..ef6c8e19e 100644 --- a/tests/bot/test_converters.py +++ b/tests/bot/test_converters.py @@ -6,13 +6,7 @@ from unittest.mock import MagicMock, patch  from dateutil.relativedelta import relativedelta  from discord.ext.commands import BadArgument -from bot.converters import ( -    Duration, -    HushDurationConverter, -    ISODateTime, -    PackageName, -    TagNameConverter, -) +from bot.converters import Duration, HushDurationConverter, ISODateTime, PackageName, TagNameConverter  class ConverterTests(unittest.IsolatedAsyncioTestCase): diff --git a/tests/bot/utils/test_checks.py b/tests/bot/utils/test_checks.py index 883465e0b..4ae11d5d3 100644 --- a/tests/bot/utils/test_checks.py +++ b/tests/bot/utils/test_checks.py @@ -32,6 +32,7 @@ class ChecksTests(unittest.IsolatedAsyncioTestCase):      async def test_has_no_roles_check_without_guild(self):          """`has_no_roles_check` should return `False` when `Context.guild` is None."""          self.ctx.channel = MagicMock(DMChannel) +        self.ctx.guild = None          self.assertFalse(await checks.has_no_roles_check(self.ctx))      async def test_has_no_roles_check_returns_false_with_unwanted_role(self): diff --git a/tests/helpers.py b/tests/helpers.py index 3978076ed..9d4988d23 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -39,7 +39,7 @@ class HashableMixin(discord.mixins.EqualityComparable):  class ColourMixin: -    """A mixin for Mocks that provides the aliasing of color->colour like discord.py does.""" +    """A mixin for Mocks that provides the aliasing of (accent_)color->(accent_)colour like discord.py does."""      @property      def color(self) -> discord.Colour: @@ -49,6 +49,14 @@ class ColourMixin:      def color(self, color: discord.Colour) -> None:          self.colour = color +    @property +    def accent_color(self) -> discord.Colour: +        return self.accent_colour + +    @accent_color.setter +    def accent_color(self, color: discord.Colour) -> None: +        self.accent_colour = color +  class CustomMockMixin:      """ @@ -235,13 +243,20 @@ class MockMember(CustomMockMixin, unittest.mock.Mock, ColourMixin, HashableMixin          self.roles = [MockRole(name="@everyone", position=1, id=0)]          if roles:              self.roles.extend(roles) +        self.top_role = max(self.roles)          if 'mention' not in kwargs:              self.mention = f"@{self.name}"  # Create a User instance to get a realistic Mock of `discord.User` -user_instance = discord.User(data=unittest.mock.MagicMock(), state=unittest.mock.MagicMock()) +_user_data_mock = collections.defaultdict(unittest.mock.MagicMock, { +    "accent_color": 0 +}) +user_instance = discord.User( +    data=unittest.mock.MagicMock(get=unittest.mock.Mock(side_effect=_user_data_mock.get)), +    state=unittest.mock.MagicMock() +)  class MockUser(CustomMockMixin, unittest.mock.Mock, ColourMixin, HashableMixin): @@ -278,7 +293,10 @@ def _get_mock_loop() -> unittest.mock.Mock:      # Since calling `create_task` on our MockBot does not actually schedule the coroutine object      # as a task in the asyncio loop, this `side_effect` calls `close()` on the coroutine object      # to prevent "has not been awaited"-warnings. -    loop.create_task.side_effect = lambda coroutine: coroutine.close() +    def mock_create_task(coroutine, **kwargs): +        coroutine.close() +        return unittest.mock.Mock() +    loop.create_task.side_effect = mock_create_task      return loop @@ -424,7 +442,12 @@ message_instance = discord.Message(state=state, channel=channel, data=message_da  # Create a Context instance to get a realistic MagicMock of `discord.ext.commands.Context` -context_instance = Context(message=unittest.mock.MagicMock(), prefix=unittest.mock.MagicMock()) +context_instance = Context( +    message=unittest.mock.MagicMock(), +    prefix="$", +    bot=MockBot(), +    view=None +)  context_instance.invoked_from_error_handler = None @@ -439,6 +462,7 @@ class MockContext(CustomMockMixin, unittest.mock.MagicMock):      def __init__(self, **kwargs) -> None:          super().__init__(**kwargs) +        self.me = kwargs.get('me', MockMember())          self.bot = kwargs.get('bot', MockBot())          self.guild = kwargs.get('guild', MockGuild())          self.author = kwargs.get('author', MockMember()) @@ -532,7 +556,7 @@ class MockReaction(CustomMockMixin, unittest.mock.MagicMock):          self.__str__.return_value = str(self.emoji) -webhook_instance = discord.Webhook(data=unittest.mock.MagicMock(), adapter=unittest.mock.MagicMock()) +webhook_instance = discord.Webhook(data=unittest.mock.MagicMock(), session=unittest.mock.MagicMock())  class MockAsyncWebhook(CustomMockMixin, unittest.mock.MagicMock): diff --git a/tests/test_base.py b/tests/test_base.py index a7db4bf3e..365805a71 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,8 +1,7 @@  import logging -import unittest  import unittest.mock - +from bot.log import get_logger  from tests.base import LoggingTestsMixin, _CaptureLogHandler @@ -15,7 +14,7 @@ class LoggingTestCaseTests(unittest.TestCase):      @classmethod      def setUpClass(cls): -        cls.log = logging.getLogger(__name__) +        cls.log = get_logger(__name__)      def test_assert_not_logs_does_not_raise_with_no_logs(self):          """Test if LoggingTestCase.assertNotLogs does not raise when no logs were emitted.""" @@ -56,15 +55,15 @@ class LoggingTestCaseTests(unittest.TestCase):      def test_logging_test_case_works_with_logger_instance(self):          """Test if the LoggingTestCase captures logging for provided logger.""" -        log = logging.getLogger("new_logger") +        log = get_logger("new_logger")          with self.assertRaises(AssertionError):              with LoggingTestCase.assertNotLogs(self, logger=log):                  log.info("Hello, this should raise an AssertionError")      def test_logging_test_case_respects_alternative_logger(self):          """Test if LoggingTestCase only checks the provided logger.""" -        log_one = logging.getLogger("log one") -        log_two = logging.getLogger("log two") +        log_one = get_logger("log one") +        log_two = get_logger("log two")          with LoggingTestCase.assertNotLogs(self, logger=log_one):              log_two.info("Hello, this should not raise an AssertionError") | 
