def test_moderators_can_target_another_member(self, create_embed, constants): """A moderator should be able to use `!user` targeting another user.""" constants.MODERATION_ROLES = [self.moderator_role.id] constants.STAFF_ROLES = [self.moderator_role.id] ctx = helpers.MockContext(author=self.moderator, channel=helpers.MockTextChannel(id=50)) asyncio.run(self.cog.user_info.callback(self.cog, ctx, self.target)) create_embed.assert_called_once_with(ctx, self.target) ctx.send.assert_called_once()
async def test_create_user_embed_ignores_everyone_role(self): """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) embed = await self.cog.create_user_embed(ctx, user) self.assertIn("&Admins", embed.fields[1].value) self.assertNotIn("&Everyone", embed.fields[1].value)
def test_regular_user_can_explicitly_target_themselves( self, create_embed, constants): """A user should target itself with `!user` when a `user` argument was not provided.""" constants.STAFF_ROLES = [self.moderator_role.id] constants.Channels.bot_commands = 50 ctx = helpers.MockContext(author=self.author, channel=helpers.MockTextChannel(id=50)) asyncio.run(self.cog.user_info.callback(self.cog, ctx, self.author)) create_embed.assert_called_once_with(ctx, self.author) ctx.send.assert_called_once()
def test_staff_members_can_bypass_channel_restriction( self, create_embed, constants): """Staff members should be able to bypass the bot-commands channel restriction.""" constants.STAFF_ROLES = [self.moderator_role.id] constants.Channels.bot_commands = 50 ctx = helpers.MockContext(author=self.moderator, channel=helpers.MockTextChannel(id=200)) asyncio.run(self.cog.user_info.callback(self.cog, ctx)) create_embed.assert_called_once_with(ctx, self.moderator) ctx.send.assert_called_once()
def test_regular_member_cannot_use_command_outside_of_bot_commands( self, constants): """A regular user should not be able to use this command outside of bot-commands.""" constants.MODERATION_ROLES = [self.moderator_role.id] constants.STAFF_ROLES = [self.moderator_role.id] constants.Channels.bot_commands = 50 ctx = helpers.MockContext(author=self.author, channel=helpers.MockTextChannel(id=100)) msg = "Sorry, but you may only use this command within <#50>." with self.assertRaises(InWhitelistCheckFailure, msg=msg): asyncio.run(self.cog.user_info.callback(self.cog, ctx))
def test_regular_user_may_use_command_in_bot_commands_channel( self, create_embed, constants): """A regular user should be allowed to use `!user` targeting themselves in bot-commands.""" constants.STAFF_ROLES = [self.moderator_role.id] constants.Channels.bot_commands = 50 ctx = helpers.MockContext(author=self.author, channel=helpers.MockTextChannel(id=50)) asyncio.run(self.cog.user_info.callback(self.cog, ctx)) create_embed.assert_called_once_with(ctx, self.author) ctx.send.assert_called_once()
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.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) self.assertEqual(embed.title, "Mr. Hemlock")
def test_on_raw_reaction_remove_ignores_removal_of_non_checkmark_reactions(self): """The `on_raw_reaction_remove` listener should ignore the removal of non-check mark emojis.""" channel = helpers.MockTextChannel(id=98765) channel.fetch_message.side_effect = AssertionError( "Expected method to return before calling `channel.fetch_message`" ) self.bot.get_all_channels.return_value = (channel, ) payload = MagicMock(emoji=helpers.MockPartialEmoji(name=self.thumbs_up_emoji), channel_id=channel.id) self.assertIsNone(asyncio.run(self.cog.on_raw_reaction_remove(payload))) channel.fetch_message.assert_not_called()
def _raw_reaction_mocks(self, channel_id, message_id, user_id): """Sets up mocks for tests of the `on_raw_reaction_add` event listener.""" channel = helpers.MockTextChannel(id=channel_id) self.bot.get_all_channels.return_value = (channel,) message = helpers.MockMessage(id=message_id) channel.fetch_message.return_value = message member = helpers.MockMember(id=user_id, roles=[self.staff_role]) message.guild.members = (member,) payload = MagicMock(channel_id=channel_id, message_id=message_id, user_id=user_id) return channel, message, member, payload
async def test_on_raw_reaction_remove_prevents_removal_of_green_checkmark_depending_on_the_duck_count( self): """The `on_raw_reaction_remove` listener prevents removal of the check mark on messages with enough ducks.""" checkmark = helpers.MockPartialEmoji(name=self.checkmark_emoji) message = helpers.MockMessage(id=1234) channel = helpers.MockTextChannel(id=98765) channel.fetch_message.return_value = message self.bot.get_all_channels.return_value = (channel, ) payload = MagicMock(channel_id=channel.id, message_id=message.id, emoji=checkmark) test_cases = ( (constants.DuckPond.threshold - 1, False), (constants.DuckPond.threshold, True), (constants.DuckPond.threshold + 1, True), ) for duck_count, should_re_add_checkmark in test_cases: with patch(f"{MODULE_PATH}.DuckPond.count_ducks", new_callable=helpers.AsyncMock) as count_ducks: count_ducks.return_value = duck_count with self.subTest( duck_count=duck_count, should_re_add_checkmark=should_re_add_checkmark): await self.cog.on_raw_reaction_remove(payload) # Check if we fetched the message channel.fetch_message.assert_called_once_with(message.id) # Check if we actually counted the number of ducks count_ducks.assert_called_once_with(message) has_re_added_checkmark = message.add_reaction.called self.assertEqual(should_re_add_checkmark, has_re_added_checkmark) if should_re_add_checkmark: message.add_reaction.assert_called_once_with( self.checkmark_emoji) message.add_reaction.reset_mock() # reset mocks channel.fetch_message.reset_mock() message.reset_mock()
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)
def test_mocks_rejects_access_to_attributes_not_part_of_spec(self): """Accessing attributes that are invalid for the objects they mock should fail.""" mocks = ( helpers.MockGuild(), helpers.MockRole(), helpers.MockMember(), helpers.MockBot(), helpers.MockContext(), helpers.MockTextChannel(), helpers.MockMessage(), ) for mock in mocks: with self.subTest(mock=mock): with self.assertRaises(AttributeError): mock.the_cake_is_a_lie
def test_mocks_allows_access_to_attributes_part_of_spec(self): """Accessing attributes that are valid for the objects they mock should succeed.""" mocks = ( (helpers.MockGuild(), 'name'), (helpers.MockRole(), 'hoist'), (helpers.MockMember(), 'display_name'), (helpers.MockBot(), 'user'), (helpers.MockContext(), 'invoked_with'), (helpers.MockTextChannel(), 'last_message'), (helpers.MockMessage(), 'mention_everyone'), ) for mock, valid_attribute in mocks: with self.subTest(mock=mock): try: getattr(mock, valid_attribute) except AttributeError: msg = f"accessing valid attribute `{valid_attribute}` raised an AttributeError" self.fail(msg)
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') 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) 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: {"False"} Roles: &Moderators """).strip(), embed.fields[1].value )