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
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)])
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__")
def test_mock_role_uses_position_for_less_than_greater_than(self): """Test if `<` and `>` comparisons for MockRole are based on its position attribute.""" role_one = helpers.MockRole(position=1) role_two = helpers.MockRole(position=2) role_three = helpers.MockRole(position=3) self.assertLess(role_one, role_two) self.assertLess(role_one, role_three) self.assertLess(role_two, role_three) self.assertGreater(role_three, role_two) self.assertGreater(role_three, role_one) self.assertGreater(role_two, role_one)
def test_mock_member_alternative_arguments(self): """Test if MockMember initializes with the arguments provided.""" core_developer = helpers.MockRole("Core Developer", 2) member = helpers.MockMember(name="Mark", user_id=12345, roles=[core_developer]) self.assertEqual(member.name, "Mark") self.assertEqual(member.id, 12345) self.assertListEqual( member.roles, [helpers.MockRole("@everyone", 1), core_developer]) self.assertEqual(member.mention, "@Mark")
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)
def test_role_info_command(self): """Tests the `role info` command.""" dummy_role = helpers.MockRole(name="Dummy", id=112233445566778899, colour=discord.Colour.blurple(), position=10, members=[self.ctx.author], permissions=discord.Permissions(0)) admin_role = helpers.MockRole( name="Admins", id=998877665544332211, colour=discord.Colour.red(), position=3, members=[self.ctx.author], permissions=discord.Permissions(0), ) self.ctx.guild.roles.append([dummy_role, admin_role]) self.cog.role_info.can_run = unittest.mock.AsyncMock() self.cog.role_info.can_run.return_value = True coroutine = self.cog.role_info.callback(self.cog, self.ctx, dummy_role, admin_role) self.assertIsNone(asyncio.run(coroutine)) self.assertEqual(self.ctx.send.call_count, 2) (_, dummy_kwargs), (_, admin_kwargs) = self.ctx.send.call_args_list dummy_embed = dummy_kwargs["embed"] admin_embed = admin_kwargs["embed"] self.assertEqual(dummy_embed.title, "Dummy info") self.assertEqual(dummy_embed.colour, discord.Colour.blurple()) 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[3].value, "1") self.assertEqual(dummy_embed.fields[4].value, "10") self.assertEqual(dummy_embed.fields[5].value, "0") self.assertEqual(admin_embed.title, "Admins info") self.assertEqual(admin_embed.colour, discord.Colour.red())
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)
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)
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 )
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)
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)
async def test_sync_cog_on_guild_role_delete(self): """A DELETE request should be sent.""" self.assertTrue(self.cog.on_guild_role_delete.__cog_listener__) role = helpers.MockRole(id=99, guild=self.guild) await self.cog.on_guild_role_delete(role) self.bot.api_client.delete.assert_called_once_with("bot/roles/99")
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
def fake_user(**kwargs): """Fixture to return a dictionary representing a user with default values set.""" kwargs.setdefault("id", 43) kwargs.setdefault("name", "bob the test man") kwargs.setdefault("discriminator", 1337) kwargs.setdefault("roles", [helpers.MockRole(id=666)]) kwargs.setdefault("in_guild", True) return kwargs
def test_mock_role_accepts_dynamic_arguments(self): """Test if MockRole accepts and sets abitrary keyword arguments.""" role = helpers.MockRole( guild="Dino Man", hoist=True, ) self.assertEqual(role.guild, "Dino Man") self.assertTrue(role.hoist)
def test_mock_guild_default_initialization(self): """Test if the default initialization of Mockguild results in the correct object.""" guild = helpers.MockGuild() # The `spec` argument makes sure `isistance` checks with `discord.Guild` pass self.assertIsInstance(guild, discord.Guild) self.assertListEqual(guild.roles, [helpers.MockRole("@everyone", 1)]) self.assertListEqual(guild.members, [])
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))
def test_mock_role_default_initialization(self): """Test if the default initialization of MockRole results in the correct object.""" role = helpers.MockRole() # The `spec` argument makes sure `isistance` checks with `discord.Role` pass self.assertIsInstance(role, discord.Role) self.assertEqual(role.name, "role") self.assertEqual(role.position, 1) self.assertEqual(role.mention, "&role")
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")
def get_guild(*roles): """Fixture to return a guild object with the given roles.""" guild = helpers.MockGuild() guild.roles = [] for role in roles: mock_role = helpers.MockRole(**role) mock_role.colour = discord.Colour(role["colour"]) mock_role.permissions = discord.Permissions(role["permissions"]) guild.roles.append(mock_role) return guild
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)
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') # A `MockMember` has the @Everyone role by default; we add the Admins to that. user = helpers.MockMember(roles=[admins_role], colour=100) 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_mock_role_alternative_arguments(self): """Test if MockRole initializes with the arguments provided.""" role = helpers.MockRole( name="Admins", role_id=90210, position=10, ) self.assertEqual(role.name, "Admins") self.assertEqual(role.id, 90210) self.assertEqual(role.position, 10) self.assertEqual(role.mention, "&Admins")
async def test_sync_cog_on_guild_role_update(self): """A PUT request should be sent if the colour, name, permissions, or position changes.""" self.assertTrue(self.cog.on_guild_role_update.__cog_listener__) role_data = { "colour": 49, "id": 777, "name": "rolename", "permissions": 8, "position": 23, } subtests = ( (True, ("colour", "name", "permissions", "position")), (False, ("hoist", "mentionable")), ) for should_put, attributes in subtests: for attribute in attributes: with self.subTest(should_put=should_put, changed_attribute=attribute): self.bot.api_client.put.reset_mock() after_role_data = role_data.copy() after_role_data[attribute] = 876 before_role = helpers.MockRole(**role_data, guild=self.guild) after_role = helpers.MockRole(**after_role_data, guild=self.guild) await self.cog.on_guild_role_update( before_role, after_role) if should_put: self.bot.api_client.put.assert_called_once_with( f"bot/roles/{after_role.id}", json=after_role_data) else: self.bot.api_client.put.assert_not_called()
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( channel_id=1)) admins_role = helpers.MockRole('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 = asyncio.run(self.cog.create_user_embed(ctx, user)) self.assertIn("&Admins", embed.description) self.assertNotIn("&Everyone", embed.description)
async def test_sync_cog_on_guild_role_create(self): """A POST request should be sent with the new role's data.""" self.assertTrue(self.cog.on_guild_role_create.__cog_listener__) role_data = { "colour": 49, "id": 777, "name": "rolename", "permissions": 8, "position": 23, } role = helpers.MockRole(**role_data, guild=self.guild) await self.cog.on_guild_role_create(role) self.bot.api_client.post.assert_called_once_with("bot/roles", json=role_data)
def get_guild(*members): """Fixture to return a guild object with the given members.""" guild = helpers.MockGuild() guild.members = [] for member in members: 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"]] guild.members.append(mock_member) return guild
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, )
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