aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/jams.py51
-rw-r--r--tests/bot/cogs/test_jams.py62
2 files changed, 73 insertions, 40 deletions
diff --git a/bot/cogs/jams.py b/bot/cogs/jams.py
index a48dbc49a..b3102db2f 100644
--- a/bot/cogs/jams.py
+++ b/bot/cogs/jams.py
@@ -1,7 +1,7 @@
import logging
import typing as t
-from discord import CategoryChannel, Guild, Member, PermissionOverwrite, Role, utils
+from discord import CategoryChannel, Guild, Member, PermissionOverwrite, Role
from discord.ext import commands
from more_itertools import unique_everseen
@@ -11,6 +11,9 @@ from bot.decorators import with_role
log = logging.getLogger(__name__)
+MAX_CHANNELS = 50
+CATEGORY_NAME = "Code Jam"
+
class CodeJams(commands.Cog):
"""Manages the code-jam related parts of our server."""
@@ -50,30 +53,38 @@ class CodeJams(commands.Cog):
f"**Team Members:** {' '.join(member.mention for member in members[1:])}"
)
+ async def get_category(self, guild: Guild) -> CategoryChannel:
+ """
+ Return a code jam category.
+
+ 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 MAX_CHANNELS - len(category.channels) >= 2:
+ return category
+
+ return await self.create_category(guild)
+
@staticmethod
- async def get_category(guild: Guild) -> CategoryChannel:
- """Create a Code Jam category if it doesn't exist and return it."""
- code_jam_category = utils.get(guild.categories, name="Code Jam")
-
- if code_jam_category is None:
- log.info("Code Jam category not found, creating it.")
-
- category_overwrites = {
- guild.default_role: PermissionOverwrite(read_messages=False),
- guild.me: PermissionOverwrite(read_messages=True)
- }
-
- code_jam_category = await guild.create_category_channel(
- "Code Jam",
- overwrites=category_overwrites,
- reason="It's code jam time!"
- )
+ async def create_category(guild: Guild) -> CategoryChannel:
+ """Create a new code jam category and return it."""
+ log.info("Creating a new code jam category.")
- return code_jam_category
+ category_overwrites = {
+ guild.default_role: PermissionOverwrite(read_messages=False),
+ guild.me: PermissionOverwrite(read_messages=True)
+ }
+
+ return await guild.create_category_channel(
+ CATEGORY_NAME,
+ overwrites=category_overwrites,
+ reason="It's code jam time!"
+ )
@staticmethod
def get_overwrites(members: t.List[Member], guild: Guild) -> t.Dict[t.Union[Member, Role], PermissionOverwrite]:
- """Get Code Jam team channels permission overwrites."""
+ """Get code jam team channels permission overwrites."""
# First member is always the team leader
team_channel_overwrites = {
members[0]: PermissionOverwrite(
diff --git a/tests/bot/cogs/test_jams.py b/tests/bot/cogs/test_jams.py
index 81fbcb798..b4ad8535f 100644
--- a/tests/bot/cogs/test_jams.py
+++ b/tests/bot/cogs/test_jams.py
@@ -1,11 +1,22 @@
import unittest
-from unittest.mock import AsyncMock, MagicMock, patch
+from unittest.mock import AsyncMock, MagicMock, create_autospec
-from bot.cogs.jams import CodeJams, setup
+from discord import CategoryChannel
+
+from bot.cogs import jams
from bot.constants import Roles
from tests.helpers import MockBot, MockContext, MockGuild, MockMember, MockRole, MockTextChannel
+def get_mock_category(channel_count: int, name: str) -> CategoryChannel:
+ """Return a mocked code jam category."""
+ category = create_autospec(CategoryChannel, spec_set=True, instance=True)
+ category.name = name
+ category.channels = [MockTextChannel() for _ in range(channel_count)]
+
+ return category
+
+
class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
"""Tests for `createteam` command."""
@@ -15,11 +26,7 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
self.command_user = MockMember([self.admin_role])
self.guild = MockGuild([self.admin_role])
self.ctx = MockContext(bot=self.bot, author=self.command_user, guild=self.guild)
- self.cog = CodeJams(self.bot)
-
- utils_patcher = patch("bot.cogs.jams.utils")
- self.utils_mock = utils_patcher.start()
- self.addCleanup(utils_patcher.stop)
+ 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."""
@@ -29,7 +36,6 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
self.cog.add_roles = AsyncMock()
self.ctx.reset_mock()
- self.utils_mock.reset_mock()
members = (MockMember() for _ in range(case))
await self.cog.createteam(self.cog, self.ctx, "foo", members)
@@ -61,22 +67,39 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
self.cog.add_roles.assert_awaited_once()
self.ctx.send.assert_awaited_once()
- async def test_category_dont_exist(self):
- """Should create code jam category."""
- self.utils_mock.get.return_value = None
+ 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 - 2, "other")],
+ )
+
+ for categories in subtests:
+ self.guild.reset_mock()
+ self.guild.categories = categories
- await self.cog.get_category(self.guild)
+ with self.subTest(categories=categories):
+ actual_category = await self.cog.get_category(self.guild)
- self.guild.create_category_channel.assert_awaited_once()
- category_overwrites = self.guild.create_category_channel.call_args[1]["overwrites"]
+ self.guild.create_category_channel.assert_awaited_once()
+ category_overwrites = self.guild.create_category_channel.call_args[1]["overwrites"]
- self.assertFalse(category_overwrites[self.guild.default_role].read_messages)
- self.assertTrue(category_overwrites[self.guild.me].read_messages)
+ self.assertFalse(category_overwrites[self.guild.default_role].read_messages)
+ self.assertTrue(category_overwrites[self.guild.me].read_messages)
+ self.assertEqual(self.guild.create_category_channel.return_value, actual_category)
async def test_category_channel_exist(self):
"""Should not try to create category channel."""
- await self.cog.get_category(self.guild)
- self.guild.create_category_channel.assert_not_awaited()
+ expected_category = get_mock_category(jams.MAX_CHANNELS - 2, jams.CATEGORY_NAME)
+ self.guild.categories = [
+ get_mock_category(jams.MAX_CHANNELS - 2, "other"),
+ expected_category,
+ get_mock_category(0, jams.CATEGORY_NAME),
+ ]
+
+ actual_category = await self.cog.get_category(self.guild)
+ self.assertEqual(expected_category, actual_category)
async def test_channel_overwrites(self):
"""Should have correct permission overwrites for users and roles."""
@@ -103,7 +126,6 @@ class JamCreateTeamTests(unittest.IsolatedAsyncioTestCase):
async def test_team_channels_creation(self):
"""Should create new voice and text channel for team."""
- self.utils_mock.get.return_value = "foo"
members = [MockMember() for _ in range(5)]
self.cog.get_overwrites = MagicMock()
@@ -147,5 +169,5 @@ class CodeJamSetup(unittest.TestCase):
def test_setup(self):
"""Should call `bot.add_cog`."""
bot = MockBot()
- setup(bot)
+ jams.setup(bot)
bot.add_cog.assert_called_once()