diff options
| author | 2021-04-27 11:04:02 +0100 | |
|---|---|---|
| committer | 2021-04-27 11:04:02 +0100 | |
| commit | 4a5980c71318eb0a0db1f431ab53a2e763d7ecd7 (patch) | |
| tree | b50da96c6c01f9d21fceac7e5f67455ea209a7b6 /tests | |
| parent | Merge two comments into one (diff) | |
| parent | Merge pull request #1426 from python-discord/feat/1365/add-bot-badges-to-user (diff) | |
Merge branch 'main' into master
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/README.md | 2 | ||||
| -rw-r--r-- | tests/bot/exts/backend/sync/test_users.py | 29 | ||||
| -rw-r--r-- | tests/bot/exts/filters/test_token_remover.py | 4 | ||||
| -rw-r--r-- | tests/bot/exts/info/doc/__init__.py | 0 | ||||
| -rw-r--r-- | tests/bot/exts/info/doc/test_parsing.py | 66 | ||||
| -rw-r--r-- | tests/bot/exts/info/test_information.py | 25 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/infraction/test_infractions.py | 52 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/infraction/test_utils.py | 12 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/test_silence.py | 15 | ||||
| -rw-r--r-- | tests/bot/exts/moderation/test_slowmode.py | 16 | ||||
| -rw-r--r-- | tests/bot/exts/utils/test_jams.py | 4 | ||||
| -rw-r--r-- | tests/bot/test_api.py | 8 | ||||
| -rw-r--r-- | tests/bot/test_converters.py | 21 | ||||
| -rw-r--r-- | tests/bot/utils/test_services.py | 4 | ||||
| -rw-r--r-- | tests/helpers.py | 2 | 
15 files changed, 168 insertions, 92 deletions
| diff --git a/tests/README.md b/tests/README.md index 4f62edd68..092324123 100644 --- a/tests/README.md +++ b/tests/README.md @@ -114,7 +114,7 @@ class BotCogTests(unittest.TestCase):  ### Mocking coroutines -By default, the `unittest.mock.Mock` and `unittest.mock.MagicMock` classes cannot mock coroutines, since the `__call__` method they provide is synchronous. In anticipation of the `AsyncMock` that will be [introduced in Python 3.8](https://docs.python.org/3.9/whatsnew/3.8.html#unittest), we have added an `AsyncMock` helper to [`helpers.py`](/tests/helpers.py). Do note that this drop-in replacement only implements an asynchronous `__call__` method, not the additional assertions that will come with the new `AsyncMock` type in Python 3.8. +By default, the `unittest.mock.Mock` and `unittest.mock.MagicMock` classes cannot mock coroutines, since the `__call__` method they provide is synchronous. The [`AsyncMock`](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.AsyncMock) that has been [introduced in Python 3.8](https://docs.python.org/3.9/whatsnew/3.8.html#unittest) is an asynchronous version of `MagicMock` that can be used anywhere a coroutine is expected.  ### Special mocks for some `discord.py` types diff --git a/tests/bot/exts/backend/sync/test_users.py b/tests/bot/exts/backend/sync/test_users.py index 61673e1bb..27932be95 100644 --- a/tests/bot/exts/backend/sync/test_users.py +++ b/tests/bot/exts/backend/sync/test_users.py @@ -188,30 +188,37 @@ class UserSyncerSyncTests(unittest.IsolatedAsyncioTestCase):      """Tests for the API requests that sync users."""      def setUp(self): -        patcher = mock.patch("bot.instance", new=helpers.MockBot()) -        self.bot = patcher.start() -        self.addCleanup(patcher.stop) +        bot_patcher = mock.patch("bot.instance", new=helpers.MockBot()) +        self.bot = bot_patcher.start() +        self.addCleanup(bot_patcher.stop) + +        chunk_patcher = mock.patch("bot.exts.backend.sync._syncers.CHUNK_SIZE", 2) +        self.chunk_size = chunk_patcher.start() +        self.addCleanup(chunk_patcher.stop) + +        self.chunk_count = 2 +        self.users = [fake_user(id=i) for i in range(self.chunk_size * self.chunk_count)]      async def test_sync_created_users(self):          """Only POST requests should be made with the correct payload.""" -        users = [fake_user(id=111), fake_user(id=222)] - -        diff = _Diff(users, [], None) +        diff = _Diff(self.users, [], None)          await UserSyncer._sync(diff) -        self.bot.api_client.post.assert_called_once_with("bot/users", json=diff.created) +        self.bot.api_client.post.assert_any_call("bot/users", json=diff.created[:self.chunk_size]) +        self.bot.api_client.post.assert_any_call("bot/users", json=diff.created[self.chunk_size:]) +        self.assertEqual(self.bot.api_client.post.call_count, self.chunk_count)          self.bot.api_client.put.assert_not_called()          self.bot.api_client.delete.assert_not_called()      async def test_sync_updated_users(self):          """Only PUT requests should be made with the correct payload.""" -        users = [fake_user(id=111), fake_user(id=222)] - -        diff = _Diff([], users, None) +        diff = _Diff([], self.users, None)          await UserSyncer._sync(diff) -        self.bot.api_client.patch.assert_called_once_with("bot/users/bulk_patch", json=diff.updated) +        self.bot.api_client.patch.assert_any_call("bot/users/bulk_patch", json=diff.updated[:self.chunk_size]) +        self.bot.api_client.patch.assert_any_call("bot/users/bulk_patch", json=diff.updated[self.chunk_size:]) +        self.assertEqual(self.bot.api_client.patch.call_count, self.chunk_count)          self.bot.api_client.post.assert_not_called()          self.bot.api_client.delete.assert_not_called() diff --git a/tests/bot/exts/filters/test_token_remover.py b/tests/bot/exts/filters/test_token_remover.py index f99cc3370..51feae9cb 100644 --- a/tests/bot/exts/filters/test_token_remover.py +++ b/tests/bot/exts/filters/test_token_remover.py @@ -291,7 +291,7 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):              channel=self.msg.channel.mention,              user_id=token.user_id,              timestamp=token.timestamp, -            hmac="x" * len(token.hmac), +            hmac="xxxxxxxxxxxxxxxxxxxxxxxxjf4",          )      @autospec("bot.exts.filters.token_remover", "UNKNOWN_USER_LOG_MESSAGE") @@ -318,7 +318,7 @@ class TokenRemoverTests(unittest.IsolatedAsyncioTestCase):          return_value = TokenRemover.format_userid_log_message(msg, token) -        self.assertEqual(return_value, (known_user_log_message.format.return_value, False)) +        self.assertEqual(return_value, (known_user_log_message.format.return_value, True))          known_user_log_message.format.assert_called_once_with(              user_id=472265943062413332, diff --git a/tests/bot/exts/info/doc/__init__.py b/tests/bot/exts/info/doc/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/bot/exts/info/doc/__init__.py diff --git a/tests/bot/exts/info/doc/test_parsing.py b/tests/bot/exts/info/doc/test_parsing.py new file mode 100644 index 000000000..1663d8491 --- /dev/null +++ b/tests/bot/exts/info/doc/test_parsing.py @@ -0,0 +1,66 @@ +from unittest import TestCase + +from bot.exts.info.doc import _parsing as parsing + + +class SignatureSplitter(TestCase): + +    def test_basic_split(self): +        test_cases = ( +            ("0,0,0", ["0", "0", "0"]), +            ("0,a=0,a=0", ["0", "a=0", "a=0"]), +        ) +        self._run_tests(test_cases) + +    def test_commas_ignored_in_brackets(self): +        test_cases = ( +            ("0,[0,0],0,[0,0],0", ["0", "[0,0]", "0", "[0,0]", "0"]), +            ("(0,),0,(0,(0,),0),0", ["(0,)", "0", "(0,(0,),0)", "0"]), +        ) +        self._run_tests(test_cases) + +    def test_mixed_brackets(self): +        tests_cases = ( +            ("[0,{0},0],0,{0:0},0", ["[0,{0},0]", "0", "{0:0}", "0"]), +            ("([0],0,0),0,(0,0),0", ["([0],0,0)", "0", "(0,0)", "0"]), +            ("([(0,),(0,)],0),0", ["([(0,),(0,)],0)", "0"]), +        ) +        self._run_tests(tests_cases) + +    def test_string_contents_ignored(self): +        test_cases = ( +            ("'0,0',0,',',0", ["'0,0'", "0", "','", "0"]), +            ("0,[']',0],0", ["0", "[']',0]", "0"]), +            ("{0,0,'}}',0,'{'},0", ["{0,0,'}}',0,'{'}", "0"]), +        ) +        self._run_tests(test_cases) + +    def test_mixed_quotes(self): +        test_cases = ( +            ("\"0',0',\",'0,0',0", ["\"0',0',\"", "'0,0'", "0"]), +            ("\",',\",'\",',0", ["\",',\"", "'\",'", "0"]), +        ) +        self._run_tests(test_cases) + +    def test_quote_escaped(self): +        test_cases = ( +            (r"'\',','\\',0", [r"'\','", r"'\\'", "0"]), +            (r"'0\',0\\\'\\',0", [r"'0\',0\\\'\\'", "0"]), +        ) +        self._run_tests(test_cases) + +    def test_real_signatures(self): +        test_cases = ( +            ("start, stop[, step]", ["start", " stop[, step]"]), +            ("object=b'', encoding='utf-8', errors='strict'", ["object=b''", " encoding='utf-8'", " errors='strict'"]), +            ( +                "typename, field_names, *, rename=False, defaults=None, module=None", +                ["typename", " field_names", " *", " rename=False", " defaults=None", " module=None"] +            ), +        ) +        self._run_tests(test_cases) + +    def _run_tests(self, test_cases): +        for input_string, expected_output in test_cases: +            with self.subTest(input_string=input_string): +                self.assertEqual(list(parsing._split_parameters(input_string)), expected_output) diff --git a/tests/bot/exts/info/test_information.py b/tests/bot/exts/info/test_information.py index daede54c5..770660fe3 100644 --- a/tests/bot/exts/info/test_information.py +++ b/tests/bot/exts/info/test_information.py @@ -65,7 +65,7 @@ class InformationCogTests(unittest.IsolatedAsyncioTestCase):              permissions=discord.Permissions(0),          ) -        self.ctx.guild.roles.append([dummy_role, admin_role]) +        self.ctx.guild.roles.extend([dummy_role, admin_role])          self.cog.role_info.can_run = unittest.mock.AsyncMock()          self.cog.role_info.can_run.return_value = True @@ -281,8 +281,10 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          """The embed should use the string representation of the user if they don't have a nick."""          ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))          user = helpers.MockMember() +        user.public_flags = unittest.mock.MagicMock(verified_bot=False)          user.nick = None          user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock") +        user.colour = 0          embed = await self.cog.create_user_embed(ctx, user) @@ -296,8 +298,10 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          """The embed should use the nick if it's available."""          ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))          user = helpers.MockMember() +        user.public_flags = unittest.mock.MagicMock(verified_bot=False)          user.nick = "Cat lover"          user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock") +        user.colour = 0          embed = await self.cog.create_user_embed(ctx, user) @@ -311,10 +315,9 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          """Created `!user` embeds should not contain mention of the @everyone-role."""          ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))          admins_role = helpers.MockRole(name='Admins') -        admins_role.colour = 100          # A `MockMember` has the @Everyone role by default; we add the Admins to that. -        user = helpers.MockMember(roles=[admins_role], top_role=admins_role) +        user = helpers.MockMember(roles=[admins_role], colour=100)          embed = await self.cog.create_user_embed(ctx, user) @@ -332,12 +335,11 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=50))          moderators_role = helpers.MockRole(name='Moderators') -        moderators_role.colour = 100          infraction_counts.return_value = ("Infractions", "expanded infractions info")          nomination_counts.return_value = ("Nominations", "nomination info") -        user = helpers.MockMember(id=314, roles=[moderators_role], top_role=moderators_role) +        user = helpers.MockMember(id=314, roles=[moderators_role], colour=100)          embed = await self.cog.create_user_embed(ctx, user)          infraction_counts.assert_called_once_with(user) @@ -355,6 +357,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          self.assertEqual(              textwrap.dedent(f"""                  Joined: {"1 year ago"} +                Verified: {"True"}                  Roles: &Moderators              """).strip(),              embed.fields[1].value @@ -366,11 +369,10 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=100))          moderators_role = helpers.MockRole(name='Moderators') -        moderators_role.colour = 100          infraction_counts.return_value = ("Infractions", "basic infractions info") -        user = helpers.MockMember(id=314, roles=[moderators_role], top_role=moderators_role) +        user = helpers.MockMember(id=314, roles=[moderators_role], colour=100)          embed = await self.cog.create_user_embed(ctx, user)          infraction_counts.assert_called_once_with(user) @@ -406,12 +408,11 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          ctx = helpers.MockContext()          moderators_role = helpers.MockRole(name='Moderators') -        moderators_role.colour = 100 -        user = helpers.MockMember(id=314, roles=[moderators_role], top_role=moderators_role) +        user = helpers.MockMember(id=314, roles=[moderators_role], colour=100)          embed = await self.cog.create_user_embed(ctx, user) -        self.assertEqual(embed.colour, discord.Colour(moderators_role.colour)) +        self.assertEqual(embed.colour, discord.Colour(100))      @unittest.mock.patch(          f"{COG_PATH}.basic_user_infraction_counts", @@ -421,7 +422,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          """The embed should be created with a blurple colour if the user has no assigned roles."""          ctx = helpers.MockContext() -        user = helpers.MockMember(id=217) +        user = helpers.MockMember(id=217, colour=discord.Colour.default())          embed = await self.cog.create_user_embed(ctx, user)          self.assertEqual(embed.colour, discord.Colour.blurple()) @@ -434,7 +435,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):          """The embed thumbnail should be set to the user's avatar in `png` format."""          ctx = helpers.MockContext() -        user = helpers.MockMember(id=217) +        user = helpers.MockMember(id=217, colour=0)          user.avatar_url_as.return_value = "avatar url"          embed = await self.cog.create_user_embed(ctx, user) diff --git a/tests/bot/exts/moderation/infraction/test_infractions.py b/tests/bot/exts/moderation/infraction/test_infractions.py index bf557a484..08f39cd50 100644 --- a/tests/bot/exts/moderation/infraction/test_infractions.py +++ b/tests/bot/exts/moderation/infraction/test_infractions.py @@ -1,10 +1,12 @@ +import inspect  import textwrap  import unittest -from unittest.mock import AsyncMock, MagicMock, Mock, patch +from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch  from bot.constants import Event +from bot.exts.moderation.infraction import _utils  from bot.exts.moderation.infraction.infractions import Infractions -from tests.helpers import MockBot, MockContext, MockGuild, MockMember, MockRole +from tests.helpers import MockBot, MockContext, MockGuild, MockMember, MockRole, MockUser, autospec  class TruncationTests(unittest.IsolatedAsyncioTestCase): @@ -37,7 +39,7 @@ class TruncationTests(unittest.IsolatedAsyncioTestCase):              delete_message_days=0          )          self.cog.apply_infraction.assert_awaited_once_with( -            self.ctx, {"foo": "bar"}, self.target, self.ctx.guild.ban.return_value +            self.ctx, {"foo": "bar", "purge": ""}, self.target, self.ctx.guild.ban.return_value          )      @patch("bot.exts.moderation.infraction._utils.post_infraction") @@ -132,20 +134,29 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):          self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar"))          self.cog.mod_log.ignore.assert_called_once_with(Event.member_update, self.user.id) +    async def action_tester(self, action, reason: str) -> None: +        """Helper method to test voice ban action.""" +        self.assertTrue(inspect.iscoroutine(action)) +        await action + +        self.user.move_to.assert_called_once_with(None, reason=ANY) +        self.user.remove_roles.assert_called_once_with(self.cog._voice_verified_role, reason=reason) +      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction")      async def test_voice_ban_apply_infraction(self, get_active_infraction, post_infraction_mock):          """Should ignore Voice Verified role removing."""          self.cog.mod_log.ignore = MagicMock()          self.cog.apply_infraction = AsyncMock() -        self.user.remove_roles = MagicMock(return_value="my_return_value")          get_active_infraction.return_value = None          post_infraction_mock.return_value = {"foo": "bar"} -        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar")) -        self.user.remove_roles.assert_called_once_with(self.cog._voice_verified_role, reason="foobar") -        self.cog.apply_infraction.assert_awaited_once_with(self.ctx, {"foo": "bar"}, self.user, "my_return_value") +        reason = "foobar" +        self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, reason)) +        self.cog.apply_infraction.assert_awaited_once_with(self.ctx, {"foo": "bar"}, self.user, ANY) + +        await self.action_tester(self.cog.apply_infraction.call_args[0][-1], reason)      @patch("bot.exts.moderation.infraction.infractions._utils.post_infraction")      @patch("bot.exts.moderation.infraction.infractions._utils.get_active_infraction") @@ -153,16 +164,33 @@ class VoiceBanTests(unittest.IsolatedAsyncioTestCase):          """Should truncate reason for voice ban."""          self.cog.mod_log.ignore = MagicMock()          self.cog.apply_infraction = AsyncMock() -        self.user.remove_roles = MagicMock(return_value="my_return_value")          get_active_infraction.return_value = None          post_infraction_mock.return_value = {"foo": "bar"}          self.assertIsNone(await self.cog.apply_voice_ban(self.ctx, self.user, "foobar" * 3000)) -        self.user.remove_roles.assert_called_once_with( -            self.cog._voice_verified_role, reason=textwrap.shorten("foobar" * 3000, 512, placeholder="...") -        ) -        self.cog.apply_infraction.assert_awaited_once_with(self.ctx, {"foo": "bar"}, self.user, "my_return_value") +        self.cog.apply_infraction.assert_awaited_once_with(self.ctx, {"foo": "bar"}, self.user, ANY) + +        # Test action +        action = self.cog.apply_infraction.call_args[0][-1] +        await self.action_tester(action, textwrap.shorten("foobar" * 3000, 512, placeholder="...")) + +    @autospec(_utils, "post_infraction", "get_active_infraction", return_value=None) +    @autospec(Infractions, "apply_infraction") +    async def test_voice_ban_user_left_guild(self, apply_infraction_mock, post_infraction_mock, _): +        """Should voice ban user that left the guild without throwing an error.""" +        infraction = {"foo": "bar"} +        post_infraction_mock.return_value = {"foo": "bar"} + +        user = MockUser() +        await self.cog.voiceban(self.cog, self.ctx, user, reason=None) +        post_infraction_mock.assert_called_once_with(self.ctx, user, "voice_ban", None, active=True) +        apply_infraction_mock.assert_called_once_with(self.cog, self.ctx, infraction, user, ANY) + +        # Test action +        action = self.cog.apply_infraction.call_args[0][-1] +        self.assertTrue(inspect.iscoroutine(action)) +        await action      async def test_voice_unban_user_not_found(self):          """Should include info to return dict when user was not found from guild.""" diff --git a/tests/bot/exts/moderation/infraction/test_utils.py b/tests/bot/exts/moderation/infraction/test_utils.py index 5b62463e0..ee9ff650c 100644 --- a/tests/bot/exts/moderation/infraction/test_utils.py +++ b/tests/bot/exts/moderation/infraction/test_utils.py @@ -146,7 +146,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.token_removed -                ).set_footer(text=utils.INFRACTION_APPEAL_FOOTER), +                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER),                  "send_result": True              },              { @@ -164,9 +164,11 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                      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 +            # correctly, even though that message is deliberately never sent.              {                  "args": (self.user, "note", None, None, Icons.defcon_denied),                  "expected_output": Embed( @@ -182,7 +184,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                      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              },              { @@ -200,7 +202,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.defcon_denied -                ).set_footer(text=utils.INFRACTION_APPEAL_FOOTER), +                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER),                  "send_result": False              },              { @@ -218,7 +220,7 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):                      name=utils.INFRACTION_AUTHOR_NAME,                      url=utils.RULES_URL,                      icon_url=Icons.defcon_denied -                ).set_footer(text=utils.INFRACTION_APPEAL_FOOTER), +                ).set_footer(text=utils.INFRACTION_APPEAL_MODMAIL_FOOTER),                  "send_result": True              }          ] diff --git a/tests/bot/exts/moderation/test_silence.py b/tests/bot/exts/moderation/test_silence.py index 104293d8e..fa5fc9e81 100644 --- a/tests/bot/exts/moderation/test_silence.py +++ b/tests/bot/exts/moderation/test_silence.py @@ -117,15 +117,6 @@ class SilenceCogTests(unittest.IsolatedAsyncioTestCase):          self.bot.get_guild.assert_called_once_with(Guild.id)      @autospec(silence, "SilenceNotifier", pass_mocks=False) -    async def test_async_init_got_role(self): -        """Got `Roles.verified` role from guild.""" -        guild = self.bot.get_guild() -        guild.get_role.side_effect = lambda id_: Mock(id=id_) - -        await self.cog._async_init() -        self.assertEqual(self.cog._verified_role.id, Roles.verified) - -    @autospec(silence, "SilenceNotifier", pass_mocks=False)      async def test_async_init_got_channels(self):          """Got channels from bot."""          self.bot.get_channel.side_effect = lambda id_: MockTextChannel(id=id_) @@ -302,7 +293,7 @@ class SilenceTests(unittest.IsolatedAsyncioTestCase):          self.assertFalse(self.overwrite.send_messages)          self.assertFalse(self.overwrite.add_reactions)          self.channel.set_permissions.assert_awaited_once_with( -            self.cog._verified_role, +            self.cog._everyone_role,              overwrite=self.overwrite          ) @@ -435,7 +426,7 @@ class UnsilenceTests(unittest.IsolatedAsyncioTestCase):          """Channel's `send_message` and `add_reactions` overwrites were restored."""          await self.cog._unsilence(self.channel)          self.channel.set_permissions.assert_awaited_once_with( -            self.cog._verified_role, +            self.cog._everyone_role,              overwrite=self.overwrite,          ) @@ -449,7 +440,7 @@ class UnsilenceTests(unittest.IsolatedAsyncioTestCase):          await self.cog._unsilence(self.channel)          self.channel.set_permissions.assert_awaited_once_with( -            self.cog._verified_role, +            self.cog._everyone_role,              overwrite=self.overwrite,          ) diff --git a/tests/bot/exts/moderation/test_slowmode.py b/tests/bot/exts/moderation/test_slowmode.py index dad751e0d..5483b7a64 100644 --- a/tests/bot/exts/moderation/test_slowmode.py +++ b/tests/bot/exts/moderation/test_slowmode.py @@ -85,22 +85,14 @@ class SlowmodeTests(unittest.IsolatedAsyncioTestCase):              self.ctx.reset_mock() -    async def test_reset_slowmode_no_channel(self) -> None: -        """Reset slowmode without a given channel.""" -        self.ctx.channel = MockTextChannel(name='careers', slowmode_delay=6) - -        await self.cog.reset_slowmode(self.cog, self.ctx, None) -        self.ctx.send.assert_called_once_with( -            f'{Emojis.check_mark} The slowmode delay for #careers has been reset to 0 seconds.' -        ) - -    async def test_reset_slowmode_with_channel(self) -> None: +    async def test_reset_slowmode_sets_delay_to_zero(self) -> None:          """Reset slowmode with a given channel."""          text_channel = MockTextChannel(name='meta', slowmode_delay=1) +        self.cog.set_slowmode = mock.AsyncMock()          await self.cog.reset_slowmode(self.cog, self.ctx, text_channel) -        self.ctx.send.assert_called_once_with( -            f'{Emojis.check_mark} The slowmode delay for #meta has been reset to 0 seconds.' +        self.cog.set_slowmode.assert_awaited_once_with( +            self.ctx, text_channel, relativedelta(seconds=0)          )      @mock.patch("bot.exts.moderation.slowmode.has_any_role") diff --git a/tests/bot/exts/utils/test_jams.py b/tests/bot/exts/utils/test_jams.py index 45e7b5b51..85d6a1173 100644 --- a/tests/bot/exts/utils/test_jams.py +++ b/tests/bot/exts/utils/test_jams.py @@ -118,11 +118,9 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):              self.assertTrue(overwrites[member].read_messages)              self.assertTrue(overwrites[member].connect) -        # Everyone and verified role overwrite +        # Everyone role overwrite          self.assertFalse(overwrites[self.guild.default_role].read_messages)          self.assertFalse(overwrites[self.guild.default_role].connect) -        self.assertFalse(overwrites[self.guild.get_role(Roles.verified)].read_messages) -        self.assertFalse(overwrites[self.guild.get_role(Roles.verified)].connect)      async def test_team_channels_creation(self):          """Should create new voice and text channel for team.""" diff --git a/tests/bot/test_api.py b/tests/bot/test_api.py index 99e942813..76bcb481d 100644 --- a/tests/bot/test_api.py +++ b/tests/bot/test_api.py @@ -13,14 +13,6 @@ class APIClientTests(unittest.IsolatedAsyncioTestCase):          cls.error_api_response = MagicMock()          cls.error_api_response.status = 999 -    def test_loop_is_not_running_by_default(self): -        """The event loop should not be running by default.""" -        self.assertFalse(api.loop_is_running()) - -    async def test_loop_is_running_in_async_context(self): -        """The event loop should be running in an async context.""" -        self.assertTrue(api.loop_is_running()) -      def test_response_code_error_default_initialization(self):          """Test the default initialization of `ResponseCodeError` without `text` or `json`"""          error = api.ResponseCodeError(response=self.error_api_response) diff --git a/tests/bot/test_converters.py b/tests/bot/test_converters.py index c42111f3f..4af84dde5 100644 --- a/tests/bot/test_converters.py +++ b/tests/bot/test_converters.py @@ -10,9 +10,9 @@ from bot.converters import (      Duration,      HushDurationConverter,      ISODateTime, +    PackageName,      TagContentConverter,      TagNameConverter, -    ValidPythonIdentifier,  ) @@ -78,24 +78,23 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):                  with self.assertRaisesRegex(BadArgument, re.escape(exception_message)):                      await TagNameConverter.convert(self.context, invalid_name) -    async def test_valid_python_identifier_for_valid(self): -        """ValidPythonIdentifier returns valid identifiers unchanged.""" -        test_values = ('foo', 'lemon') +    async def test_package_name_for_valid(self): +        """PackageName returns valid package names unchanged.""" +        test_values = ('foo', 'le_mon', 'num83r')          for name in test_values:              with self.subTest(identifier=name): -                conversion = await ValidPythonIdentifier.convert(self.context, name) +                conversion = await PackageName.convert(self.context, name)                  self.assertEqual(name, conversion) -    async def test_valid_python_identifier_for_invalid(self): -        """ValidPythonIdentifier raises the proper exception for invalid identifiers.""" -        test_values = ('nested.stuff', '#####') +    async def test_package_name_for_invalid(self): +        """PackageName raises the proper exception for invalid package names.""" +        test_values = ('text_with_a_dot.', 'UpperCaseName', 'dashed-name')          for name in test_values:              with self.subTest(identifier=name): -                exception_message = f'`{name}` is not a valid Python identifier' -                with self.assertRaisesRegex(BadArgument, re.escape(exception_message)): -                    await ValidPythonIdentifier.convert(self.context, name) +                with self.assertRaises(BadArgument): +                    await PackageName.convert(self.context, name)      async def test_duration_converter_for_valid(self):          """Duration returns the correct `datetime` for valid duration strings.""" diff --git a/tests/bot/utils/test_services.py b/tests/bot/utils/test_services.py index 1b48f6560..3b71022db 100644 --- a/tests/bot/utils/test_services.py +++ b/tests/bot/utils/test_services.py @@ -30,9 +30,9 @@ class PasteTests(unittest.IsolatedAsyncioTestCase):          """Url with specified extension is returned on successful requests."""          key = "paste_key"          test_cases = ( -            (f"https://paste_service.com/{key}.txt", "txt"), +            (f"https://paste_service.com/{key}.txt?noredirect", "txt"),              (f"https://paste_service.com/{key}.py", "py"), -            (f"https://paste_service.com/{key}", ""), +            (f"https://paste_service.com/{key}?noredirect", ""),          )          response = MagicMock(              json=AsyncMock(return_value={"key": key}) diff --git a/tests/helpers.py b/tests/helpers.py index 870f66197..496363ae3 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -230,7 +230,7 @@ class MockMember(CustomMockMixin, unittest.mock.Mock, ColourMixin, HashableMixin      spec_set = member_instance      def __init__(self, roles: Optional[Iterable[MockRole]] = None, **kwargs) -> None: -        default_kwargs = {'name': 'member', 'id': next(self.discord_id), 'bot': False} +        default_kwargs = {'name': 'member', 'id': next(self.discord_id), 'bot': False, "pending": False}          super().__init__(**collections.ChainMap(kwargs, default_kwargs))          self.roles = [MockRole(name="@everyone", position=1, id=0)] | 
