Пример #1
0
    async def test_on_raw_reaction_add_returns_for_bot_and_non_staff_members(
            self):
        """The `on_raw_reaction_add` event handler should return for bot users or non-staff members."""
        channel_id = 1234
        message_id = 2345
        user_id = 3456

        channel, message, _, payload = self._raw_reaction_mocks(
            channel_id, message_id, user_id)

        test_cases = (
            ("non-staff member", helpers.MockMember(id=user_id)),
            ("bot staff member",
             helpers.MockMember(id=user_id, roles=[self.staff_role],
                                bot=True)),
        )

        payload.emoji = self.duck_pond_emoji

        for description, member in test_cases:
            message.guild.members = (member, )
            with self.subTest(test_case=description), patch(
                    f"{MODULE_PATH}.DuckPond.has_green_checkmark"
            ) as checkmark:
                checkmark.side_effect = AssertionError(
                    "Expected method to return before calling `self.has_green_checkmark`."
                )
                self.assertIsNone(await self.cog.on_raw_reaction_add(payload))

                # Check that we did make it past the payload checks
                channel.fetch_message.assert_called_once()
                channel.fetch_message.reset_mock()
Пример #2
0
    def test_reaction_check_for_valid_emoji_and_authors(self):
        """Should return True if authors are identical or are a bot and a core dev, respectively."""
        user_subtests = (
            (
                helpers.MockMember(id=77),
                helpers.MockMember(id=77),
                "identical users",
            ),
            (
                helpers.MockMember(id=77, bot=True),
                helpers.MockMember(id=43, roles=[self.core_dev_role]),
                "bot author and core-dev reactor",
            ),
        )

        for emoji in self.syncer._REACTION_EMOJIS:
            for author, user, msg in user_subtests:
                with self.subTest(author=author,
                                  user=user,
                                  emoji=emoji,
                                  msg=msg):
                    message, reaction = self.get_message_reaction(emoji)
                    ret_val = self.syncer._reaction_check(
                        author, message, reaction, user)

                    self.assertTrue(ret_val)
Пример #3
0
 def _get_reaction(self,
                   emoji: typing.Union[str, helpers.MockEmoji],
                   staff: int = 0,
                   nonstaff: int = 0) -> helpers.MockReaction:
     staffers = [
         helpers.MockMember(roles=[self.staff_role]) for _ in range(staff)
     ]
     nonstaffers = [helpers.MockMember() for _ in range(nonstaff)]
     return helpers.MockReaction(emoji=emoji, users=staffers + nonstaffers)
Пример #4
0
    async def test_ship_command(self):
        context = helpers.MockContext(
            guild=helpers.MockGuild(
                members=[helpers.MockMember(), helpers.MockMember()]
            )
        )

        await self.cog.ship(self.cog, context)

        self.assertEqual(context.send.call_args.kwargs.get("embed"), None)
Пример #5
0
    def test_mock_guild_alternative_arguments(self):
        """Test if MockGuild initializes with the arguments provided."""
        core_developer = helpers.MockRole(name="Core Developer", position=2)
        guild = helpers.MockGuild(
            roles=[core_developer],
            members=[helpers.MockMember(id=54321)],
        )

        self.assertListEqual(guild.roles, [helpers.MockRole(name="@everyone", position=1, id=0), core_developer])
        self.assertListEqual(guild.members, [helpers.MockMember(id=54321)])
Пример #6
0
    def setUp(self):
        """Set up steps executed before each test is run."""
        self.bot = helpers.MockBot()
        self.cog = information.Information(self.bot)

        self.moderator_role = helpers.MockRole(name="Moderators", id=2, position=10)
        self.flautist_role = helpers.MockRole(name="Flautists", id=3, position=2)
        self.bassist_role = helpers.MockRole(name="Bassists", id=4, position=3)

        self.author = helpers.MockMember(id=1, name="syntaxaire")
        self.moderator = helpers.MockMember(id=2, name="riffautae", roles=[self.moderator_role])
        self.target = helpers.MockMember(id=3, name="__fluzz__")
Пример #7
0
    def test_is_staff_returns_correct_values_based_on_instance_passed(self):
        """The `is_staff` method should return correct values based on the instance passed."""
        test_cases = (
            (helpers.MockUser(name="User instance"), False),
            (helpers.MockMember(name="Member instance without staff role"), False),
            (helpers.MockMember(name="Member instance with staff role", roles=[self.staff_role]), True)
        )

        for user, expected_return in test_cases:
            actual_return = self.cog.is_staff(user)
            with self.subTest(user_type=user.name, expected_return=expected_return, actual_return=actual_return):
                self.assertEqual(expected_return, actual_return)
Пример #8
0
    def setUpClass(cls):
        """Sets up the objects that only have to be initialized once."""
        cls.nonstaff_member = helpers.MockMember(name="Non-staffer")

        cls.staff_role = helpers.MockRole(name="Staff role", id=constants.STAFF_ROLES[0])
        cls.staff_member = helpers.MockMember(name="staffer", roles=[cls.staff_role])

        cls.checkmark_emoji = "\N{White Heavy Check Mark}"
        cls.thumbs_up_emoji = "\N{Thumbs Up Sign}"
        cls.unicode_duck_emoji = "\N{Duck}"
        cls.duck_pond_emoji = helpers.MockPartialEmoji(id=constants.DuckPond.custom_emojis[0])
        cls.non_duck_custom_emoji = helpers.MockPartialEmoji(id=123)
Пример #9
0
    async def test_sync_cog_on_member_update_roles(self):
        """Members should be patched if their roles have changed."""
        self.assertTrue(self.cog.on_member_update.__cog_listener__)

        # Roles are intentionally unsorted.
        before_roles = [helpers.MockRole(id=12), helpers.MockRole(id=30), helpers.MockRole(id=20)]
        before_member = helpers.MockMember(roles=before_roles, guild=self.guild)
        after_member = helpers.MockMember(roles=before_roles[1:], guild=self.guild)

        await self.cog.on_member_update(before_member, after_member)

        data = {"roles": sorted(role.id for role in after_member.roles)}
        self.cog.patch_user.assert_called_once_with(after_member.id, json=data)
Пример #10
0
    def test_create_user_embed_basic_information_outside_of_moderation_channels(
            self, infraction_counts):
        """The embed should contain only basic infraction data outside of mod channels."""
        ctx = helpers.MockContext(channel=helpers.MockTextChannel(
            channel_id=100))

        moderators_role = helpers.MockRole('Moderators')
        moderators_role.colour = 100

        infraction_counts.return_value = "basic infractions info"

        user = helpers.MockMember(user_id=314,
                                  roles=[moderators_role],
                                  top_role=moderators_role)
        embed = asyncio.run(self.cog.create_user_embed(ctx, user))

        infraction_counts.assert_called_once_with(user)

        self.assertEqual(
            textwrap.dedent(f"""
                **User Information**
                Created: {"1 year ago"}
                Profile: {user.mention}
                ID: {user.id}

                **Member Information**
                Joined: {"1 year ago"}
                Roles: &Moderators

                basic infractions info
            """).strip(), embed.description)
Пример #11
0
    def setUp(self):
        self.bot = helpers.MockBot(user=helpers.MockMember(bot=True))
        self.syncer = TestSyncer(self.bot)
        self.guild = helpers.MockGuild()

        # Make sure `_get_diff` returns a MagicMock, not an AsyncMock
        self.syncer._get_diff.return_value = mock.MagicMock()
Пример #12
0
    async def test_sync_confirmation_context_redirect(self):
        """If ctx is given, a new message should be sent and author should be ctx's author."""
        mock_member = helpers.MockMember()
        subtests = (
            (None, self.bot.user, None),
            (helpers.MockContext(author=mock_member), mock_member,
             helpers.MockMessage()),
        )

        for ctx, author, message in subtests:
            with self.subTest(ctx=ctx, author=author, message=message):
                if ctx is not None:
                    ctx.send.return_value = message

                # Make sure `_get_diff` returns a MagicMock, not an AsyncMock
                self.syncer._get_diff.return_value = mock.MagicMock()

                self.syncer._get_confirmation_result = mock.AsyncMock(
                    return_value=(False, None))

                guild = helpers.MockGuild()
                await self.syncer.sync(guild, ctx)

                if ctx is not None:
                    ctx.send.assert_called_once()

                self.syncer._get_confirmation_result.assert_called_once()
                self.assertEqual(
                    self.syncer._get_confirmation_result.call_args[0][1],
                    author)
                self.assertEqual(
                    self.syncer._get_confirmation_result.call_args[0][2],
                    message)
Пример #13
0
    def setUp(self):
        """Set up steps executed before each test is run."""
        self.bot = helpers.MockBot()
        self.cog = information.Information(self.bot)

        self.moderator_role = helpers.MockRole(name="Moderators", id=2, position=10)
        self.flautist_role = helpers.MockRole(name="Flautists", id=3, position=2)
        self.bassist_role = helpers.MockRole(name="Bassists", id=4, position=3)

        self.author = helpers.MockMember(id=1, name="syntaxaire")
        self.moderator = helpers.MockMember(id=2, name="riffautae", roles=[self.moderator_role])
        self.target = helpers.MockMember(id=3, name="__fluzz__")

        # There's no way to mock the channel constant without deferring imports. The constant is
        # used as a default value for a parameter, which gets defined upon import.
        self.bot_command_channel = helpers.MockTextChannel(id=constants.Channels.bot_commands)
Пример #14
0
    async def on_member_join_helper(self, side_effect: Exception) -> dict:
        """
        Helper to set `side_effect` for on_member_join and assert a PUT request was sent.

        The request data for the mock member is returned. All exceptions will be re-raised.
        """
        member = helpers.MockMember(
            discriminator="1234",
            roles=[helpers.MockRole(id=22),
                   helpers.MockRole(id=12)],
            guild=self.guild,
        )

        data = {
            "discriminator": int(member.discriminator),
            "id": member.id,
            "in_guild": True,
            "name": member.name,
            "roles": sorted(role.id for role in member.roles)
        }

        self.bot.api_client.put.reset_mock(side_effect=True)
        self.bot.api_client.put.side_effect = side_effect

        try:
            await self.cog.on_member_join(member)
        except Exception:
            raise
        finally:
            self.bot.api_client.put.assert_called_once_with(
                f"bot/users/{member.id}", json=data)

        return data
Пример #15
0
    def setUpClass(cls):
        """Set up helpers that only need to be defined once."""
        cls.bot_commands = helpers.MockTextChannel(id=123456789,
                                                   category_id=123456)
        cls.help_channel = helpers.MockTextChannel(id=987654321,
                                                   category_id=987654)
        cls.non_whitelisted_channel = helpers.MockTextChannel(id=666666)
        cls.dm_channel = helpers.MockDMChannel()

        cls.non_staff_member = helpers.MockMember()
        cls.staff_role = helpers.MockRole(id=121212)
        cls.staff_member = helpers.MockMember(roles=(cls.staff_role, ))

        cls.channels = (cls.bot_commands.id, )
        cls.categories = (cls.help_channel.category_id, )
        cls.roles = (cls.staff_role.id, )
Пример #16
0
    async def test_create_user_embed_basic_information_outside_of_moderation_channels(self, infraction_counts):
        """The embed should contain only basic infraction data outside of mod channels."""
        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)
        embed = await self.cog.create_user_embed(ctx, user)

        infraction_counts.assert_called_once_with(user)

        self.assertEqual(
            textwrap.dedent(f"""
                Created: {"1 year ago"}
                Profile: {user.mention}
                ID: {user.id}
            """).strip(),
            embed.fields[0].value
        )

        self.assertEqual(
            textwrap.dedent(f"""
                Joined: {"1 year ago"}
                Roles: &Moderators
            """).strip(),
            embed.fields[1].value
        )

        self.assertEqual(
            "basic infractions info",
            embed.fields[3].value
        )
Пример #17
0
    async def test_create_user_embed_expanded_information_in_moderation_channels(
            self, nomination_counts, infraction_counts):
        """The embed should contain expanded infractions and nomination info in mod channels."""
        ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=50))

        moderators_role = helpers.MockRole(name='Moderators')

        infraction_counts.return_value = ("Infractions",
                                          "expanded infractions info")
        nomination_counts.return_value = ("Nominations", "nomination info")

        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)
        nomination_counts.assert_called_once_with(user)

        self.assertEqual(
            textwrap.dedent(f"""
                Created: {"1 year ago"}
                Profile: {user.mention}
                ID: {user.id}
            """).strip(), embed.fields[0].value)

        self.assertEqual(
            textwrap.dedent(f"""
                Joined: {"1 year ago"}
                Verified: {"True"}
                Roles: &Moderators
            """).strip(), embed.fields[1].value)
Пример #18
0
    def test_create_user_embed_expanded_information_in_moderation_channels(
            self, nomination_counts, infraction_counts):
        """The embed should contain expanded infractions and nomination info in mod channels."""
        ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=50))

        moderators_role = helpers.MockRole(name='Moderators')
        moderators_role.colour = 100

        infraction_counts.return_value = "expanded infractions info"
        nomination_counts.return_value = "nomination info"

        user = helpers.MockMember(id=314,
                                  roles=[moderators_role],
                                  top_role=moderators_role)
        embed = asyncio.run(self.cog.create_user_embed(ctx, user))

        infraction_counts.assert_called_once_with(user)
        nomination_counts.assert_called_once_with(user)

        self.assertEqual(
            textwrap.dedent(f"""
                **User Information**
                Created: {"1 year ago"}
                Profile: {user.mention}
                ID: {user.id}

                **Member Information**
                Joined: {"1 year ago"}
                Roles: &Moderators

                expanded infractions info

                nomination info
            """).strip(), embed.description)
Пример #19
0
    async def test_confirmation_result_large_diff(self):
        """Should return True if confirmed and False if _send_prompt fails or aborted."""
        author = helpers.MockMember()
        mock_message = helpers.MockMessage()

        subtests = (
            (True, mock_message, True, "confirmed"),
            (False, None, False, "_send_prompt failed"),
            (False, mock_message, False, "aborted"),
        )

        for expected_result, expected_message, confirmed, msg in subtests:  # pragma: no cover
            with self.subTest(msg=msg):
                self.syncer._send_prompt = mock.AsyncMock(
                    return_value=expected_message)
                self.syncer._wait_for_confirmation = mock.AsyncMock(
                    return_value=confirmed)

                coro = self.syncer._get_confirmation_result(4, author)
                actual_result, actual_message = await coro

                self.syncer._send_prompt.assert_called_once_with(
                    None)  # message defaults to None
                self.assertIs(actual_result, expected_result)
                self.assertEqual(actual_message, expected_message)

                if expected_message:
                    self.syncer._wait_for_confirmation.assert_called_once_with(
                        author, expected_message)
Пример #20
0
 def get_mock_member(member: dict):
     member = member.copy()
     del member["in_guild"]
     mock_member = helpers.MockMember(**member)
     mock_member.roles = [
         helpers.MockRole(id=role_id) for role_id in member["roles"]
     ]
     return mock_member
Пример #21
0
    async def test_create_user_embed_uses_blurple_colour_when_user_has_no_roles(self):
        """The embed should be created with a blurple colour if the user has no assigned roles."""
        ctx = helpers.MockContext()

        user = helpers.MockMember(id=217)
        embed = await self.cog.create_user_embed(ctx, user)

        self.assertEqual(embed.colour, discord.Colour.blurple())
Пример #22
0
    def test_reaction_check_for_invalid_reactions(self):
        """Should return False for invalid reaction events."""
        valid_emoji = self.syncer._REACTION_EMOJIS[0]
        subtests = (
            (
                helpers.MockMember(id=77),
                *self.get_message_reaction(valid_emoji),
                helpers.MockMember(id=43, roles=[self.core_dev_role]),
                "users are not identical",
            ),
            (
                helpers.MockMember(id=77, bot=True),
                *self.get_message_reaction(valid_emoji),
                helpers.MockMember(id=43),
                "reactor lacks the core-dev role",
            ),
            (
                helpers.MockMember(id=77, bot=True,
                                   roles=[self.core_dev_role]),
                *self.get_message_reaction(valid_emoji),
                helpers.MockMember(id=77, bot=True,
                                   roles=[self.core_dev_role]),
                "reactor is a bot",
            ),
            (
                helpers.MockMember(id=77),
                helpers.MockMessage(id=95),
                helpers.MockReaction(emoji=valid_emoji,
                                     message=helpers.MockMessage(id=26)),
                helpers.MockMember(id=77),
                "messages are not identical",
            ),
            (
                helpers.MockMember(id=77),
                *self.get_message_reaction("InVaLiD"),
                helpers.MockMember(id=77),
                "emoji is invalid",
            ),
        )

        for *args, msg in subtests:
            kwargs = dict(zip(("author", "message", "reaction", "user"), args))
            with self.subTest(**kwargs, msg=msg):
                ret_val = self.syncer._reaction_check(*args)
                self.assertFalse(ret_val)
Пример #23
0
    def test_mock_member_accepts_dynamic_arguments(self):
        """Test if MockMember accepts and sets abitrary keyword arguments."""
        member = helpers.MockMember(
            nick="Dino Man",
            colour=discord.Colour.default(),
        )

        self.assertEqual(member.nick, "Dino Man")
        self.assertEqual(member.colour, discord.Colour.default())
Пример #24
0
    async def test_sync_cog_on_member_remove(self):
        """Member should be patched to set in_guild as False."""
        self.assertTrue(self.cog.on_member_remove.__cog_listener__)

        member = helpers.MockMember(guild=self.guild)
        await self.cog.on_member_remove(member)

        self.cog.patch_user.assert_called_once_with(member.id,
                                                    json={"in_guild": False})
Пример #25
0
    async def test_create_user_embed_uses_png_format_of_user_avatar_as_thumbnail(self):
        """The embed thumbnail should be set to the user's avatar in `png` format."""
        ctx = helpers.MockContext()

        user = helpers.MockMember(id=217)
        user.avatar_url_as.return_value = "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")
Пример #26
0
    async def test_create_user_embed_uses_nick_in_title_if_available(self):
        """The embed should use the nick if it's available."""
        ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))
        user = helpers.MockMember()
        user.nick = "Cat lover"
        user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock")

        embed = await self.cog.create_user_embed(ctx, user)

        self.assertEqual(embed.title, "Cat lover (Mr. Hemlock)")
Пример #27
0
    async def test_create_user_embed_uses_string_representation_of_user_in_title_if_nick_is_not_available(self):
        """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.nick = None
        user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock")

        embed = await self.cog.create_user_embed(ctx, user)

        self.assertEqual(embed.title, "Mr. Hemlock")
Пример #28
0
    def test_mock_member_default_initialization(self):
        """Test if the default initialization of Mockmember results in the correct object."""
        member = helpers.MockMember()

        # The `spec` argument makes sure `isistance` checks with `discord.Member` pass
        self.assertIsInstance(member, discord.Member)

        self.assertEqual(member.name, "member")
        self.assertListEqual(member.roles, [helpers.MockRole(name="@everyone", position=1, id=0)])
        self.assertEqual(member.mention, "@member")
Пример #29
0
    async def test_match_command(self):
        context = helpers.MockContext()

        await self.cog.match(
            self.cog,
            context,
            user1=helpers.MockMember(name="Snake Bot", id=744747000293228684),
        )

        self.assertEqual(context.send.call_args.kwargs.get("embed"), None)
Пример #30
0
    async def test_create_user_embed_uses_top_role_colour_when_user_has_roles(self):
        """The embed should be created with the colour of the top role, if a top role is available."""
        ctx = helpers.MockContext()

        moderators_role = helpers.MockRole(name='Moderators')

        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(100))