Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8a83d68
Move the `sync` cog tests to `unittest`.
jchristgit Oct 12, 2019
42abcc5
Move `tests.test_resources` to `unittest`.
jchristgit Oct 12, 2019
e1c4f08
Move `tests.test_pagination` to `unittest`.
jchristgit Oct 12, 2019
4f22550
Move the `rules.attachments` module tests to `unittest`.
jchristgit Oct 12, 2019
6d3af7c
Move the `antispam` cog tests to `unittest`.
jchristgit Oct 12, 2019
63fad8b
Move the `security` cog tests to `unittest`.
jchristgit Oct 12, 2019
8656973
Move the `token_remover` cog tests to `unittest`.
jchristgit Oct 12, 2019
a186252
Merge pull request #520 from python-discord/sync-cog-to-unittest
SebastiaanZ Oct 13, 2019
7768616
Add subTest + move test_resource to resources subdir
SebastiaanZ Oct 13, 2019
88d8f62
Merge branch 'resources-to-unittest' into unittest-migration
SebastiaanZ Oct 13, 2019
562ede8
Move test_attachments.py to tests/bot/rules dir
SebastiaanZ Oct 13, 2019
86e942d
Merge branch 'rules-attachment-tests-unittest' into unittest-migration
SebastiaanZ Oct 13, 2019
7bd0be0
Move test_antispam.py to tests.bot.cogs
SebastiaanZ Oct 13, 2019
4cbbe6f
Merge branch 'cogs-antispam-unittest' into unittest-migration
SebastiaanZ Oct 13, 2019
5032521
Move sync tests to tests.bot.cogs.sync
SebastiaanZ Oct 13, 2019
612994a
Use `MockBot` and `MockContext`.
jchristgit Oct 13, 2019
2e18b41
Move test_pagination to tests.bot subdir
SebastiaanZ Oct 14, 2019
699b7df
Merge branch 'pagination-tests-to-unittest' into unittest-migration
SebastiaanZ Oct 14, 2019
0dabafc
Move test_security to tests.bot.cogs
SebastiaanZ Oct 14, 2019
6c7735a
Merge branch 'cogs-security-unittest' into unittest-migration
SebastiaanZ Oct 14, 2019
ffe5dba
Remove empty tests.cogs folder
SebastiaanZ Oct 14, 2019
9de24c0
Migrate test_constants to unittest
SebastiaanZ Oct 14, 2019
e7e2479
Use `MockBot`.
jchristgit Oct 14, 2019
45e82e0
Merge pull request #531 from python-discord/unittest-bot-constants
jchristgit Oct 14, 2019
e4e01cd
Add more specialized Mocks to tests.helpers
SebastiaanZ Oct 14, 2019
57432d5
Merge branch 'unittest-migration' of github.com:python-discord/bot in…
SebastiaanZ Oct 14, 2019
0ccb798
Move the `token_remover` cog tests to `unittest`.
jchristgit Oct 12, 2019
ae01774
Use `MockBot`.
jchristgit Oct 14, 2019
e662373
Make test_token_remover use our discord Mocks
SebastiaanZ Oct 14, 2019
83df79c
Merge branch 'cogs-tokenremover-unittest' of github.com:python-discor…
SebastiaanZ Oct 14, 2019
a7df533
Removing moved/duplicated files
SebastiaanZ Oct 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added tests/bot/cogs/sync/__init__.py
Empty file.
126 changes: 126 additions & 0 deletions tests/bot/cogs/sync/test_roles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import unittest

from bot.cogs.sync.syncers import Role, get_roles_for_sync


class GetRolesForSyncTests(unittest.TestCase):
"""Tests constructing the roles to synchronize with the site."""

def test_get_roles_for_sync_empty_return_for_equal_roles(self):
"""No roles should be synced when no diff is found."""
api_roles = {Role(id=41, name='name', colour=33, permissions=0x8, position=1)}
guild_roles = {Role(id=41, name='name', colour=33, permissions=0x8, position=1)}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(set(), set(), set())
)

def test_get_roles_for_sync_returns_roles_to_update_with_non_id_diff(self):
"""Roles to be synced are returned when non-ID attributes differ."""
api_roles = {Role(id=41, name='old name', colour=35, permissions=0x8, position=1)}
guild_roles = {Role(id=41, name='new name', colour=33, permissions=0x8, position=2)}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(set(), guild_roles, set())
)

def test_get_roles_only_returns_roles_that_require_update(self):
"""Roles that require an update should be returned as the second tuple element."""
api_roles = {
Role(id=41, name='old name', colour=33, permissions=0x8, position=1),
Role(id=53, name='other role', colour=55, permissions=0, position=3)
}
guild_roles = {
Role(id=41, name='new name', colour=35, permissions=0x8, position=2),
Role(id=53, name='other role', colour=55, permissions=0, position=3)
}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(
set(),
{Role(id=41, name='new name', colour=35, permissions=0x8, position=2)},
set(),
)
)

def test_get_roles_returns_new_roles_in_first_tuple_element(self):
"""Newly created roles are returned as the first tuple element."""
api_roles = {
Role(id=41, name='name', colour=35, permissions=0x8, position=1),
}
guild_roles = {
Role(id=41, name='name', colour=35, permissions=0x8, position=1),
Role(id=53, name='other role', colour=55, permissions=0, position=2)
}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(
{Role(id=53, name='other role', colour=55, permissions=0, position=2)},
set(),
set(),
)
)

def test_get_roles_returns_roles_to_update_and_new_roles(self):
"""Newly created and updated roles should be returned together."""
api_roles = {
Role(id=41, name='old name', colour=35, permissions=0x8, position=1),
}
guild_roles = {
Role(id=41, name='new name', colour=40, permissions=0x16, position=2),
Role(id=53, name='other role', colour=55, permissions=0, position=3)
}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(
{Role(id=53, name='other role', colour=55, permissions=0, position=3)},
{Role(id=41, name='new name', colour=40, permissions=0x16, position=2)},
set(),
)
)

def test_get_roles_returns_roles_to_delete(self):
"""Roles to be deleted should be returned as the third tuple element."""
api_roles = {
Role(id=41, name='name', colour=35, permissions=0x8, position=1),
Role(id=61, name='to delete', colour=99, permissions=0x9, position=2),
}
guild_roles = {
Role(id=41, name='name', colour=35, permissions=0x8, position=1),
}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(
set(),
set(),
{Role(id=61, name='to delete', colour=99, permissions=0x9, position=2)},
)
)

def test_get_roles_returns_roles_to_delete_update_and_new_roles(self):
"""When roles were added, updated, and removed, all of them are returned properly."""
api_roles = {
Role(id=41, name='not changed', colour=35, permissions=0x8, position=1),
Role(id=61, name='to delete', colour=99, permissions=0x9, position=2),
Role(id=71, name='to update', colour=99, permissions=0x9, position=3),
}
guild_roles = {
Role(id=41, name='not changed', colour=35, permissions=0x8, position=1),
Role(id=81, name='to create', colour=99, permissions=0x9, position=4),
Role(id=71, name='updated', colour=101, permissions=0x5, position=3),
}

self.assertEqual(
get_roles_for_sync(guild_roles, api_roles),
(
{Role(id=81, name='to create', colour=99, permissions=0x9, position=4)},
{Role(id=71, name='updated', colour=101, permissions=0x5, position=3)},
{Role(id=61, name='to delete', colour=99, permissions=0x9, position=2)},
)
)
84 changes: 84 additions & 0 deletions tests/bot/cogs/sync/test_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import unittest

from bot.cogs.sync.syncers import User, get_users_for_sync


def fake_user(**kwargs):
kwargs.setdefault('id', 43)
kwargs.setdefault('name', 'bob the test man')
kwargs.setdefault('discriminator', 1337)
kwargs.setdefault('avatar_hash', None)
kwargs.setdefault('roles', (666,))
kwargs.setdefault('in_guild', True)
return User(**kwargs)


class GetUsersForSyncTests(unittest.TestCase):
"""Tests constructing the users to synchronize with the site."""

def test_get_users_for_sync_returns_nothing_for_empty_params(self):
"""When no users are given, none are returned."""
self.assertEqual(
get_users_for_sync({}, {}),
(set(), set())
)

def test_get_users_for_sync_returns_nothing_for_equal_users(self):
"""When no users are updated, none are returned."""
api_users = {43: fake_user()}
guild_users = {43: fake_user()}

self.assertEqual(
get_users_for_sync(guild_users, api_users),
(set(), set())
)

def test_get_users_for_sync_returns_users_to_update_on_non_id_field_diff(self):
"""When a non-ID-field differs, the user to update is returned."""
api_users = {43: fake_user()}
guild_users = {43: fake_user(name='new fancy name')}

self.assertEqual(
get_users_for_sync(guild_users, api_users),
(set(), {fake_user(name='new fancy name')})
)

def test_get_users_for_sync_returns_users_to_create_with_new_ids_on_guild(self):
"""When new users join the guild, they are returned as the first tuple element."""
api_users = {43: fake_user()}
guild_users = {43: fake_user(), 63: fake_user(id=63)}

self.assertEqual(
get_users_for_sync(guild_users, api_users),
({fake_user(id=63)}, set())
)

def test_get_users_for_sync_updates_in_guild_field_on_user_leave(self):
"""When a user leaves the guild, the `in_guild` flag is updated to `False`."""
api_users = {43: fake_user(), 63: fake_user(id=63)}
guild_users = {43: fake_user()}

self.assertEqual(
get_users_for_sync(guild_users, api_users),
(set(), {fake_user(id=63, in_guild=False)})
)

def test_get_users_for_sync_updates_and_creates_users_as_needed(self):
"""When one user left and another one was updated, both are returned."""
api_users = {43: fake_user()}
guild_users = {63: fake_user(id=63)}

self.assertEqual(
get_users_for_sync(guild_users, api_users),
({fake_user(id=63)}, {fake_user(in_guild=False)})
)

def test_get_users_for_sync_does_not_duplicate_update_users(self):
"""When the API knows a user the guild doesn't, nothing is performed."""
api_users = {43: fake_user(in_guild=False)}
guild_users = {}

self.assertEqual(
get_users_for_sync(guild_users, api_users),
(set(), set())
)
35 changes: 35 additions & 0 deletions tests/bot/cogs/test_antispam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import unittest

from bot.cogs import antispam


class AntispamConfigurationValidationTests(unittest.TestCase):
"""Tests validation of the antispam cog configuration."""

def test_default_antispam_config_is_valid(self):
"""The default antispam configuration is valid."""
validation_errors = antispam.validate_config()
self.assertEqual(validation_errors, {})

def test_unknown_rule_returns_error(self):
"""Configuring an unknown rule returns an error."""
self.assertEqual(
antispam.validate_config({'invalid-rule': {}}),
{'invalid-rule': "`invalid-rule` is not recognized as an antispam rule."}
)

def test_missing_keys_returns_error(self):
"""Not configuring required keys returns an error."""
keys = (('interval', 'max'), ('max', 'interval'))
for configured_key, unconfigured_key in keys:
with self.subTest(
configured_key=configured_key,
unconfigured_key=unconfigured_key
):
config = {'burst': {configured_key: 10}}
error = f"Key `{unconfigured_key}` is required but not set for rule `burst`"

self.assertEqual(
antispam.validate_config(config),
{'burst': error}
)
59 changes: 59 additions & 0 deletions tests/bot/cogs/test_security.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import logging
import unittest
from unittest.mock import MagicMock

from discord.ext.commands import NoPrivateMessage

from bot.cogs import security
from tests.helpers import MockBot, MockContext


class SecurityCogTests(unittest.TestCase):
"""Tests the `Security` cog."""

def setUp(self):
"""Attach an instance of the cog to the class for tests."""
self.bot = MockBot()
self.cog = security.Security(self.bot)
self.ctx = MockContext()

def test_check_additions(self):
"""The cog should add its checks after initialization."""
self.bot.check.assert_any_call(self.cog.check_on_guild)
self.bot.check.assert_any_call(self.cog.check_not_bot)

def test_check_not_bot_returns_false_for_humans(self):
"""The bot check should return `True` when invoked with human authors."""
self.ctx.author.bot = False
self.assertTrue(self.cog.check_not_bot(self.ctx))

def test_check_not_bot_returns_true_for_robots(self):
"""The bot check should return `False` when invoked with robotic authors."""
self.ctx.author.bot = True
self.assertFalse(self.cog.check_not_bot(self.ctx))

def test_check_on_guild_raises_when_outside_of_guild(self):
"""When invoked outside of a guild, `check_on_guild` should cause an error."""
self.ctx.guild = None

with self.assertRaises(NoPrivateMessage, msg="This command cannot be used in private messages."):
self.cog.check_on_guild(self.ctx)

def test_check_on_guild_returns_true_inside_of_guild(self):
"""When invoked inside of a guild, `check_on_guild` should return `True`."""
self.ctx.guild = "lemon's lemonade stand"
self.assertTrue(self.cog.check_on_guild(self.ctx))


class SecurityCogLoadTests(unittest.TestCase):
"""Tests loading the `Security` cog."""

def test_security_cog_load(self):
"""Cog loading logs a message at `INFO` level."""
bot = MagicMock()
with self.assertLogs(logger='bot.cogs.security', level=logging.INFO) as cm:
security.setup(bot)
bot.add_cog.assert_called_once()

[line] = cm.output
self.assertIn("Cog loaded: Security", line)
Loading