aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ToxicKidz <[email protected]>2021-07-05 19:48:29 -0400
committerGravatar ToxicKidz <[email protected]>2021-07-05 19:48:29 -0400
commit2a5a15f69d8ea3079f60e0e5d44387bc59061de5 (patch)
tree39fac2cbc9992c7692e8eecc37d731ab5eefeab9
parentchore: Add the codejam create command (diff)
chore: Update tests for the new codejam create command
-rw-r--r--bot/exts/utils/jams.py1
-rw-r--r--tests/bot/exts/utils/test_jams.py137
-rw-r--r--tests/helpers.py22
3 files changed, 92 insertions, 68 deletions
diff --git a/bot/exts/utils/jams.py b/bot/exts/utils/jams.py
index d45f9b57f..0fc84c2eb 100644
--- a/bot/exts/utils/jams.py
+++ b/bot/exts/utils/jams.py
@@ -79,7 +79,6 @@ class CodeJams(commands.Cog):
If all categories are full or none exist, create a new category.
"""
for category in guild.categories:
- # Need 2 available spaces: one for the text channel and one for voice.
if category.name == CATEGORY_NAME and len(category.channels) < MAX_CHANNELS:
return category
diff --git a/tests/bot/exts/utils/test_jams.py b/tests/bot/exts/utils/test_jams.py
index 85d6a1173..368a15476 100644
--- a/tests/bot/exts/utils/test_jams.py
+++ b/tests/bot/exts/utils/test_jams.py
@@ -2,10 +2,24 @@ import unittest
from unittest.mock import AsyncMock, MagicMock, create_autospec
from discord import CategoryChannel
+from discord.ext.commands import BadArgument
from bot.constants import Roles
from bot.exts.utils import jams
-from tests.helpers import MockBot, MockContext, MockGuild, MockMember, MockRole, MockTextChannel
+from tests.helpers import (
+ MockAttachment, MockBot, MockCategoryChannel, MockContext,
+ MockGuild, MockMember, MockRole, MockTextChannel
+)
+
+TEST_CSV = b"""\
+Team Name,Team Member Discord ID,Team Leader
+Annoyed Alligators,12345,Y
+Annoyed Alligators,54321,N
+Oscillating Otters,12358,Y
+Oscillating Otters,74832,N
+Oscillating Otters,19903,N
+Annoyed Alligators,11111,N
+"""
def get_mock_category(channel_count: int, name: str) -> CategoryChannel:
@@ -17,8 +31,8 @@ def get_mock_category(channel_count: int, name: str) -> CategoryChannel:
return category
-class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
- """Tests for `createteam` command."""
+class JamCodejamCreateTests(unittest.IsolatedAsyncioTestCase):
+ """Tests for `codejam create` command."""
def setUp(self):
self.bot = MockBot()
@@ -28,60 +42,64 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
self.ctx = MockContext(bot=self.bot, author=self.command_user, guild=self.guild)
self.cog = jams.CodeJams(self.bot)
- async def test_too_small_amount_of_team_members_passed(self):
- """Should `ctx.send` and exit early when too small amount of members."""
- for case in (1, 2):
- with self.subTest(amount_of_members=case):
- self.cog.create_channels = AsyncMock()
- self.cog.add_roles = AsyncMock()
+ async def test_message_without_attachments(self):
+ """If no link or attachments are provided, commands.BadArgument should be raised."""
+ self.ctx.message.attachments = []
- self.ctx.reset_mock()
- members = (MockMember() for _ in range(case))
- await self.cog.createteam(self.cog, self.ctx, "foo", members)
+ with self.assertRaises(BadArgument):
+ await self.cog.create(self.cog, self.ctx, None)
- self.ctx.send.assert_awaited_once()
- self.cog.create_channels.assert_not_awaited()
- self.cog.add_roles.assert_not_awaited()
+ async def test_result_sending(self):
+ """Should call `ctx.send` when everything goes right."""
+ self.ctx.message.attachments = [MockAttachment()]
+ self.ctx.message.attachments[0].read = AsyncMock()
+ self.ctx.message.attachments[0].read.return_value = TEST_CSV
+
+ team_leaders = MockRole()
+
+ self.guild.get_member.return_value = MockMember()
- async def test_duplicate_members_provided(self):
- """Should `ctx.send` and exit early because duplicate members provided and total there is only 1 member."""
- self.cog.create_channels = AsyncMock()
+ self.ctx.guild.create_role = AsyncMock()
+ self.ctx.guild.create_role.return_value = team_leaders
+ self.cog.create_team_channel = AsyncMock()
+ self.cog.create_team_leader_channel = AsyncMock()
self.cog.add_roles = AsyncMock()
- member = MockMember()
- await self.cog.createteam(self.cog, self.ctx, "foo", (member for _ in range(5)))
+ await self.cog.create(self.cog, self.ctx, None)
+ self.cog.create_team_channel.assert_awaited()
+ self.cog.create_team_leader_channel.assert_awaited_once_with(
+ self.ctx.guild, team_leaders
+ )
self.ctx.send.assert_awaited_once()
- self.cog.create_channels.assert_not_awaited()
- self.cog.add_roles.assert_not_awaited()
-
- async def test_result_sending(self):
- """Should call `ctx.send` when everything goes right."""
- self.cog.create_channels = AsyncMock()
- self.cog.add_roles = AsyncMock()
- members = [MockMember() for _ in range(5)]
- await self.cog.createteam(self.cog, self.ctx, "foo", members)
+ async def test_link_returning_non_200_status(self):
+ """When the URL passed returns a non 200 status, it should send a message informing them."""
+ self.bot.http_session.get.return_value = mock = MagicMock()
+ mock.status = 404
+ await self.cog.create(self.cog, self.ctx, "https://not-a-real-link.com")
- self.cog.create_channels.assert_awaited_once()
- self.cog.add_roles.assert_awaited_once()
self.ctx.send.assert_awaited_once()
async def test_category_doesnt_exist(self):
"""Should create a new code jam category."""
subtests = (
[],
- [get_mock_category(jams.MAX_CHANNELS - 1, jams.CATEGORY_NAME)],
+ [get_mock_category(jams.MAX_CHANNELS, jams.CATEGORY_NAME)],
[get_mock_category(jams.MAX_CHANNELS - 2, "other")],
)
+ self.cog.send_status_update = AsyncMock()
+
for categories in subtests:
+ self.cog.send_status_update.reset_mock()
self.guild.reset_mock()
self.guild.categories = categories
with self.subTest(categories=categories):
actual_category = await self.cog.get_category(self.guild)
+ self.cog.send_status_update.assert_called_once()
self.guild.create_category_channel.assert_awaited_once()
category_overwrites = self.guild.create_category_channel.call_args[1]["overwrites"]
@@ -103,62 +121,47 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
async def test_channel_overwrites(self):
"""Should have correct permission overwrites for users and roles."""
- leader = MockMember()
- members = [leader] + [MockMember() for _ in range(4)]
+ leader = (MockMember(), True)
+ members = [leader] + [(MockMember(), False) for _ in range(4)]
overwrites = self.cog.get_overwrites(members, self.guild)
- # Leader permission overwrites
- self.assertTrue(overwrites[leader].manage_messages)
- self.assertTrue(overwrites[leader].read_messages)
- self.assertTrue(overwrites[leader].manage_webhooks)
- self.assertTrue(overwrites[leader].connect)
-
- # Other members permission overwrites
- for member in members[1:]:
+ for member, _ in members:
self.assertTrue(overwrites[member].read_messages)
- self.assertTrue(overwrites[member].connect)
-
- # Everyone role overwrite
- self.assertFalse(overwrites[self.guild.default_role].read_messages)
- self.assertFalse(overwrites[self.guild.default_role].connect)
async def test_team_channels_creation(self):
- """Should create new voice and text channel for team."""
- members = [MockMember() for _ in range(5)]
+ """Should create a text channel for a team."""
+ team_leaders = MockRole()
+ members = [(MockMember(), True)] + [(MockMember(), False) for _ in range(5)]
+ category = MockCategoryChannel()
+ category.create_text_channel = AsyncMock()
self.cog.get_overwrites = MagicMock()
self.cog.get_category = AsyncMock()
- self.ctx.guild.create_text_channel.return_value = MockTextChannel(mention="foobar-channel")
- actual = await self.cog.create_channels(self.guild, "my-team", members)
+ self.cog.get_category.return_value = category
+ self.cog.add_team_leader_roles = AsyncMock()
- self.assertEqual("foobar-channel", actual)
+ await self.cog.create_team_channel(self.guild, "my-team", members, team_leaders)
+ self.cog.add_team_leader_roles.assert_awaited_once_with(members, team_leaders)
self.cog.get_overwrites.assert_called_once_with(members, self.guild)
self.cog.get_category.assert_awaited_once_with(self.guild)
- self.guild.create_text_channel.assert_awaited_once_with(
+ category.create_text_channel.assert_awaited_once_with(
"my-team",
- overwrites=self.cog.get_overwrites.return_value,
- category=self.cog.get_category.return_value
- )
- self.guild.create_voice_channel.assert_awaited_once_with(
- "My Team",
- overwrites=self.cog.get_overwrites.return_value,
- category=self.cog.get_category.return_value
+ overwrites=self.cog.get_overwrites.return_value
)
async def test_jam_roles_adding(self):
"""Should add team leader role to leader and jam role to every team member."""
leader_role = MockRole(name="Team Leader")
- jam_role = MockRole(name="Jammer")
- self.guild.get_role.side_effect = [leader_role, jam_role]
leader = MockMember()
- members = [leader] + [MockMember() for _ in range(4)]
- await self.cog.add_roles(self.guild, members)
+ members = [(leader, True)] + [(MockMember(), False) for _ in range(4)]
+ await self.cog.add_team_leader_roles(members, leader_role)
- leader.add_roles.assert_any_await(leader_role)
- for member in members:
- member.add_roles.assert_any_await(jam_role)
+ leader.add_roles.assert_awaited_once_with(leader_role)
+ for member, is_leader in members:
+ if not is_leader:
+ member.add_roles.assert_not_awaited()
class CodeJamSetup(unittest.TestCase):
diff --git a/tests/helpers.py b/tests/helpers.py
index e3dc5fe5b..eedd7a601 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -361,6 +361,27 @@ class MockDMChannel(CustomMockMixin, unittest.mock.Mock, HashableMixin):
super().__init__(**collections.ChainMap(kwargs, default_kwargs))
+# Create CategoryChannel instance to get a realistic MagicMock of `discord.CategoryChannel`
+category_channel_data = {
+ 'id': 1,
+ 'type': discord.ChannelType.category,
+ 'name': 'category',
+ 'position': 1,
+}
+
+state = unittest.mock.MagicMock()
+guild = unittest.mock.MagicMock()
+category_channel_instance = discord.CategoryChannel(
+ state=state, guild=guild, data=category_channel_data
+)
+
+
+class MockCategoryChannel(CustomMockMixin, unittest.mock.Mock, HashableMixin):
+ def __init__(self, **kwargs) -> None:
+ default_kwargs = {'id': next(self.discord_id)}
+ super().__init__(**collections.ChainMap(default_kwargs, kwargs))
+
+
# Create a Message instance to get a realistic MagicMock of `discord.Message`
message_data = {
'id': 1,
@@ -403,6 +424,7 @@ class MockContext(CustomMockMixin, unittest.mock.MagicMock):
self.guild = kwargs.get('guild', MockGuild())
self.author = kwargs.get('author', MockMember())
self.channel = kwargs.get('channel', MockTextChannel())
+ self.message = kwargs.get('message', MockMessage())
self.invoked_from_error_handler = kwargs.get('invoked_from_error_handler', False)