diff options
author | 2019-04-05 12:11:31 +0100 | |
---|---|---|
committer | 2019-04-05 12:11:31 +0100 | |
commit | ebda74029355ce3236ca9266acde40fd40329df7 (patch) | |
tree | aba491f902c874328c88b8e7ccb9772b5414c17f /api/tests | |
parent | Set `harakiri = 30`. (diff) |
[#176] Redo project layout
Diffstat (limited to 'api/tests')
-rw-r--r-- | api/tests/__init__.py | 0 | ||||
-rw-r--r-- | api/tests/base.py | 69 | ||||
-rw-r--r-- | api/tests/test_deleted_messages.py | 43 | ||||
-rw-r--r-- | api/tests/test_documentation_links.py | 161 | ||||
-rw-r--r-- | api/tests/test_healthcheck.py | 16 | ||||
-rw-r--r-- | api/tests/test_infractions.py | 359 | ||||
-rw-r--r-- | api/tests/test_models.py | 113 | ||||
-rw-r--r-- | api/tests/test_nominations.py | 41 | ||||
-rw-r--r-- | api/tests/test_off_topic_channel_names.py | 152 | ||||
-rw-r--r-- | api/tests/test_rules.py | 35 | ||||
-rw-r--r-- | api/tests/test_snake_names.py | 67 | ||||
-rw-r--r-- | api/tests/test_users.py | 121 | ||||
-rw-r--r-- | api/tests/test_validators.py | 213 |
13 files changed, 0 insertions, 1390 deletions
diff --git a/api/tests/__init__.py b/api/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/api/tests/__init__.py +++ /dev/null diff --git a/api/tests/base.py b/api/tests/base.py deleted file mode 100644 index 5d8ccf8c..00000000 --- a/api/tests/base.py +++ /dev/null @@ -1,69 +0,0 @@ -from django.contrib.auth.models import User -from rest_framework.test import APITestCase - - -test_user, _created = User.objects.get_or_create( - username='test', - email='[email protected]', - password='testpass', # noqa: S106 - is_superuser=True, - is_staff=True -) - - -class APISubdomainTestCase(APITestCase): - """ - Configures the test client to use the proper subdomain - for requests and forces authentication for the test user. - - The test user is considered staff and superuser. - If you want to test for a custom user (for example, to test model permissions), - create the user, assign the relevant permissions, and use - `self.client.force_authenticate(user=created_user)` to force authentication - through the created user. - - Using this performs the following niceties for you which ease writing tests: - - setting the `HTTP_HOST` request header to `api.pythondiscord.local:8000`, and - - forcing authentication for the test user. - If you don't want to force authentication (for example, to test a route's response - for an unauthenticated user), un-force authentication by using the following: - - >>> from api.test.base import APISubdomainTestCase - >>> class UnauthedUserTestCase(APISubdomainTestCase): - ... def setUp(self): - ... super().setUp() - ... self.client.force_authentication(user=None) - ... def test_can_read_objects_at_my_endpoint(self): - ... resp = self.client.get('/my-publicly-readable-endpoint') - ... self.assertEqual(resp.status_code, 200) - ... def test_cannot_delete_objects_at_my_endpoint(self): - ... resp = self.client.delete('/my-publicly-readable-endpoint/42') - ... self.assertEqual(resp.status_code, 401) - - Make sure to include the `super().setUp(self)` call, otherwise, you may get - status code 404 for some URLs due to the missing `HTTP_HOST` header. - - ## Example - Using this in a test case is rather straightforward: - - >>> from api.tests.base import APISubdomainTestCase - >>> class MyAPITestCase(APISubdomainTestCase): - ... def test_that_it_works(self): - ... response = self.client.get('/my-endpoint') - ... self.assertEqual(response.status_code, 200) - - To reverse URLs of the API host, you need to use `django_hosts`: - - >>> from django_hosts.resolvers import reverse - >>> from api.test.base import APISubdomainTestCase - >>> class MyReversedTestCase(APISubdomainTestCase): - ... def test_my_endpoint(self): - ... url = reverse('user-detail', host='api') - ... response = self.client.get(url) - ... self.assertEqual(response.status_code, 200) - """ - - def setUp(self): - super().setUp() - self.client.defaults['HTTP_HOST'] = 'api.pythondiscord.local:8000' - self.client.force_authenticate(test_user) diff --git a/api/tests/test_deleted_messages.py b/api/tests/test_deleted_messages.py deleted file mode 100644 index cd5acab0..00000000 --- a/api/tests/test_deleted_messages.py +++ /dev/null @@ -1,43 +0,0 @@ -from datetime import datetime - -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import User - - -class DeletedMessagesTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.author = User.objects.create( - id=55, - name='Robbie Rotten', - discriminator=55, - avatar_hash=None - ) - - cls.data = { - 'actor': None, - 'creation': datetime.utcnow().isoformat(), - 'deletedmessage_set': [ - { - 'author': cls.author.id, - 'id': 55, - 'channel_id': 5555, - 'content': "Terror Billy is a meanie", - 'embeds': [] - }, - { - 'author': cls.author.id, - 'id': 56, - 'channel_id': 5555, - 'content': "If you purge this, you're evil", - 'embeds': [] - } - ] - } - - def test_accepts_valid_data(self): - url = reverse('bot:messagedeletioncontext-list', host='api') - response = self.client.post(url, data=self.data) - self.assertEqual(response.status_code, 201) diff --git a/api/tests/test_documentation_links.py b/api/tests/test_documentation_links.py deleted file mode 100644 index f6c78391..00000000 --- a/api/tests/test_documentation_links.py +++ /dev/null @@ -1,161 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import DocumentationLink - - -class UnauthedDocumentationLinkAPITests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_detail_lookup_returns_401(self): - url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_list_returns_401(self): - url = reverse('bot:documentationlink-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_create_returns_401(self): - url = reverse('bot:documentationlink-list', host='api') - response = self.client.post(url, data={'hi': 'there'}) - - self.assertEqual(response.status_code, 401) - - def test_delete_returns_401(self): - url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 401) - - -class EmptyDatabaseDocumentationLinkAPITests(APISubdomainTestCase): - def test_detail_lookup_returns_404(self): - url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 404) - - def test_list_all_returns_empty_list(self): - url = reverse('bot:documentationlink-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) - - def test_delete_returns_404(self): - url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 404) - - -class DetailLookupDocumentationLinkAPITests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.doc_link = DocumentationLink.objects.create( - package='testpackage', - base_url='https://example.com', - inventory_url='https://example.com' - ) - - cls.doc_json = { - 'package': cls.doc_link.package, - 'base_url': cls.doc_link.base_url, - 'inventory_url': cls.doc_link.inventory_url - } - - def test_detail_lookup_unknown_package_returns_404(self): - url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 404) - - def test_detail_lookup_created_package_returns_package(self): - url = reverse('bot:documentationlink-detail', args=(self.doc_link.package,), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), self.doc_json) - - def test_list_all_packages_shows_created_package(self): - url = reverse('bot:documentationlink-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), [self.doc_json]) - - def test_create_invalid_body_returns_400(self): - url = reverse('bot:documentationlink-list', host='api') - response = self.client.post(url, data={'i': 'am', 'totally': 'valid'}) - - self.assertEqual(response.status_code, 400) - - def test_create_invalid_url_returns_400(self): - body = { - 'package': 'example', - 'base_url': 'https://example.com', - 'inventory_url': 'totally an url' - } - - url = reverse('bot:documentationlink-list', host='api') - response = self.client.post(url, data=body) - - self.assertEqual(response.status_code, 400) - - -class DocumentationLinkCreationTests(APISubdomainTestCase): - def setUp(self): - super().setUp() - - self.body = { - 'package': 'example', - 'base_url': 'https://example.com', - 'inventory_url': 'https://docs.example.com' - } - - url = reverse('bot:documentationlink-list', host='api') - response = self.client.post(url, data=self.body) - - self.assertEqual(response.status_code, 201) - - def test_package_in_full_list(self): - url = reverse('bot:documentationlink-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), [self.body]) - - def test_detail_lookup_works_with_package(self): - url = reverse('bot:documentationlink-detail', args=(self.body['package'],), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), self.body) - - -class DocumentationLinkDeletionTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.doc_link = DocumentationLink.objects.create( - package='example', - base_url='https://example.com', - inventory_url='https://docs.example.com' - ) - - def test_unknown_package_returns_404(self): - url = reverse('bot:documentationlink-detail', args=('whatever',), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 404) - - def test_delete_known_package_returns_204(self): - url = reverse('bot:documentationlink-detail', args=(self.doc_link.package,), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 204) diff --git a/api/tests/test_healthcheck.py b/api/tests/test_healthcheck.py deleted file mode 100644 index b0fd71bf..00000000 --- a/api/tests/test_healthcheck.py +++ /dev/null @@ -1,16 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase - - -class UnauthedHealthcheckAPITests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_can_access_healthcheck_view(self): - url = reverse('healthcheck', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), {'status': 'ok'}) diff --git a/api/tests/test_infractions.py b/api/tests/test_infractions.py deleted file mode 100644 index 7c370c17..00000000 --- a/api/tests/test_infractions.py +++ /dev/null @@ -1,359 +0,0 @@ -from datetime import datetime as dt, timedelta, timezone -from urllib.parse import quote - -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import Infraction, User - - -class UnauthenticatedTests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_detail_lookup_returns_401(self): - url = reverse('bot:infraction-detail', args=(5,), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_list_returns_401(self): - url = reverse('bot:infraction-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_create_returns_401(self): - url = reverse('bot:infraction-list', host='api') - response = self.client.post(url, data={'reason': 'Have a nice day.'}) - - self.assertEqual(response.status_code, 401) - - def test_partial_update_returns_401(self): - url = reverse('bot:infraction-detail', args=(5,), host='api') - response = self.client.patch(url, data={'reason': 'Have a nice day.'}) - - self.assertEqual(response.status_code, 401) - - -class InfractionTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.user = User.objects.create( - id=5, - name='james', - discriminator=1, - avatar_hash=None - ) - cls.ban_hidden = Infraction.objects.create( - user_id=cls.user.id, - actor_id=cls.user.id, - type='ban', - reason='He terk my jerb!', - hidden=True, - expires_at=dt(5018, 11, 20, 15, 52, tzinfo=timezone.utc) - ) - cls.ban_inactive = Infraction.objects.create( - user_id=cls.user.id, - actor_id=cls.user.id, - type='ban', - reason='James is an ass, and we won\'t be working with him again.', - active=False - ) - - def test_list_all(self): - url = reverse('bot:infraction-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - infractions = response.json() - - self.assertEqual(len(infractions), 2) - self.assertEqual(infractions[0]['id'], self.ban_hidden.id) - self.assertEqual(infractions[1]['id'], self.ban_inactive.id) - - def test_filter_search(self): - url = reverse('bot:infraction-list', host='api') - pattern = quote(r'^James(\s\w+){3},') - response = self.client.get(f'{url}?search={pattern}') - - self.assertEqual(response.status_code, 200) - infractions = response.json() - - self.assertEqual(len(infractions), 1) - self.assertEqual(infractions[0]['id'], self.ban_inactive.id) - - def test_filter_field(self): - url = reverse('bot:infraction-list', host='api') - response = self.client.get(f'{url}?type=ban&hidden=true') - - self.assertEqual(response.status_code, 200) - infractions = response.json() - - self.assertEqual(len(infractions), 1) - self.assertEqual(infractions[0]['id'], self.ban_hidden.id) - - def test_returns_empty_for_no_match(self): - url = reverse('bot:infraction-list', host='api') - response = self.client.get(f'{url}?type=ban&search=poop') - - self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.json()), 0) - - def test_ignores_bad_filters(self): - url = reverse('bot:infraction-list', host='api') - response = self.client.get(f'{url}?type=ban&hidden=maybe&foo=bar') - - self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.json()), 2) - - def test_retrieve_single_from_id(self): - url = reverse('bot:infraction-detail', args=(self.ban_inactive.id,), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json()['id'], self.ban_inactive.id) - - def test_retrieve_returns_404_for_absent_id(self): - url = reverse('bot:infraction-detail', args=(1337,), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 404) - - def test_partial_update(self): - url = reverse('bot:infraction-detail', args=(self.ban_hidden.id,), host='api') - data = { - 'expires_at': '4143-02-15T21:04:31+00:00', - 'active': False, - 'reason': 'durka derr' - } - - response = self.client.patch(url, data=data) - self.assertEqual(response.status_code, 200) - infraction = Infraction.objects.get(id=self.ban_hidden.id) - - # These fields were updated. - self.assertEqual(infraction.expires_at.isoformat(), data['expires_at']) - self.assertEqual(infraction.active, data['active']) - self.assertEqual(infraction.reason, data['reason']) - - # These fields are still the same. - self.assertEqual(infraction.id, self.ban_hidden.id) - self.assertEqual(infraction.inserted_at, self.ban_hidden.inserted_at) - self.assertEqual(infraction.user.id, self.ban_hidden.user.id) - self.assertEqual(infraction.actor.id, self.ban_hidden.actor.id) - self.assertEqual(infraction.type, self.ban_hidden.type) - self.assertEqual(infraction.hidden, self.ban_hidden.hidden) - - def test_partial_update_returns_400_for_frozen_field(self): - url = reverse('bot:infraction-detail', args=(self.ban_hidden.id,), host='api') - data = {'user': 6} - - response = self.client.patch(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'user': ['This field cannot be updated.'] - }) - - -class CreationTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.user = User.objects.create( - id=5, - name='james', - discriminator=1, - avatar_hash=None - ) - - def test_accepts_valid_data(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'ban', - 'reason': 'He terk my jerb!', - 'hidden': True, - 'expires_at': '5018-11-20T15:52:00+00:00' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 201) - - infraction = Infraction.objects.get(id=response.json()['id']) - self.assertAlmostEqual( - infraction.inserted_at, - dt.now(timezone.utc), - delta=timedelta(seconds=2) - ) - self.assertEqual(infraction.expires_at.isoformat(), data['expires_at']) - self.assertEqual(infraction.user.id, data['user']) - self.assertEqual(infraction.actor.id, data['actor']) - self.assertEqual(infraction.type, data['type']) - self.assertEqual(infraction.reason, data['reason']) - self.assertEqual(infraction.hidden, data['hidden']) - self.assertEqual(infraction.active, True) - - def test_returns_400_for_missing_user(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'actor': self.user.id, - 'type': 'kick' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'user': ['This field is required.'] - }) - - def test_returns_400_for_bad_user(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'user': 1337, - 'actor': self.user.id, - 'type': 'kick' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'user': ['Invalid pk "1337" - object does not exist.'] - }) - - def test_returns_400_for_bad_type(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'hug' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'type': ['"hug" is not a valid choice.'] - }) - - def test_returns_400_for_bad_expired_at_format(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'ban', - 'expires_at': '20/11/5018 15:52:00' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'expires_at': [ - 'Datetime has wrong format. Use one of these formats instead: ' - 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].' - ] - }) - - def test_returns_400_for_expiring_non_expirable_type(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'kick', - 'expires_at': '5018-11-20T15:52:00+00:00' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'expires_at': [f'{data["type"]} infractions cannot expire.'] - }) - - def test_returns_400_for_hidden_non_hideable_type(self): - url = reverse('bot:infraction-list', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'superstar', - 'hidden': True - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'hidden': [f'{data["type"]} infractions cannot be hidden.'] - }) - - -class ExpandedTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.user = User.objects.create( - id=5, - name='james', - discriminator=1, - avatar_hash=None - ) - cls.kick = Infraction.objects.create( - user_id=cls.user.id, - actor_id=cls.user.id, - type='kick' - ) - cls.warning = Infraction.objects.create( - user_id=cls.user.id, - actor_id=cls.user.id, - type='warning' - ) - - def check_expanded_fields(self, infraction): - for key in ('user', 'actor'): - obj = infraction[key] - for field in ('id', 'name', 'discriminator', 'avatar_hash', 'roles', 'in_guild'): - self.assertTrue(field in obj, msg=f'field "{field}" missing from {key}') - - def test_list_expanded(self): - url = reverse('bot:infraction-list-expanded', host='api') - - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - response_data = response.json() - self.assertEqual(len(response_data), 2) - - for infraction in response_data: - self.check_expanded_fields(infraction) - - def test_create_expanded(self): - url = reverse('bot:infraction-list-expanded', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'warning' - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 201) - - self.assertEqual(len(Infraction.objects.all()), 3) - self.check_expanded_fields(response.json()) - - def test_retrieve_expanded(self): - url = reverse('bot:infraction-detail-expanded', args=(self.warning.id,), host='api') - - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - - infraction = response.json() - self.assertEqual(infraction['id'], self.warning.id) - self.check_expanded_fields(infraction) - - def test_partial_update_expanded(self): - url = reverse('bot:infraction-detail-expanded', args=(self.kick.id,), host='api') - data = {'active': False} - - response = self.client.patch(url, data=data) - self.assertEqual(response.status_code, 200) - - infraction = Infraction.objects.get(id=self.kick.id) - self.assertEqual(infraction.active, data['active']) - self.check_expanded_fields(response.json()) diff --git a/api/tests/test_models.py b/api/tests/test_models.py deleted file mode 100644 index 43d1eb41..00000000 --- a/api/tests/test_models.py +++ /dev/null @@ -1,113 +0,0 @@ -from datetime import datetime as dt, timezone - -from django.test import SimpleTestCase - -from ..models import ( - BotSetting, DeletedMessage, - DocumentationLink, Infraction, - Message, MessageDeletionContext, - ModelReprMixin, OffTopicChannelName, - Reminder, Role, - SnakeFact, SnakeIdiom, - SnakeName, SpecialSnake, - Tag, User -) - - -class SimpleClass(ModelReprMixin): - def __init__(self, is_what): - self.the_cake = is_what - - -class ReprMixinTests(SimpleTestCase): - def setUp(self): - self.klass = SimpleClass('is a lie') - - def test_shows_attributes(self): - expected = "<SimpleClass(the_cake='is a lie')>" - self.assertEqual(repr(self.klass), expected) - - -class StringDunderMethodTests(SimpleTestCase): - def setUp(self): - self.objects = ( - DeletedMessage( - id=45, - author=User( - id=444, name='bill', - discriminator=5, avatar_hash=None - ), - channel_id=666, - content="wooey", - deletion_context=MessageDeletionContext( - actor=User( - id=5555, name='shawn', - discriminator=555, avatar_hash=None - ), - creation=dt.utcnow() - ), - embeds=[] - ), - DocumentationLink( - 'test', 'http://example.com', 'http://example.com' - ), - OffTopicChannelName(name='bob-the-builders-playground'), - SnakeFact(fact='snakes are cute'), - SnakeIdiom(idiom='snake snacks'), - SnakeName(name='python', scientific='3'), - SpecialSnake( - name='Pythagoras Pythonista', - info='The only python snake that is born a triangle' - ), - Role( - id=5, name='test role', - colour=0x5, permissions=0 - ), - Message( - id=45, - author=User( - id=444, name='bill', - discriminator=5, avatar_hash=None - ), - channel_id=666, - content="wooey", - embeds=[] - ), - MessageDeletionContext( - actor=User( - id=5555, name='shawn', - discriminator=555, avatar_hash=None - ), - creation=dt.utcnow() - ), - Tag( - title='bob', - embed={'content': "the builder"} - ), - User( - id=5, name='bob', - discriminator=1, avatar_hash=None - ), - Infraction( - user_id=5, actor_id=5, - type='kick', reason='He terk my jerb!' - ), - Infraction( - user_id=5, actor_id=5, hidden=True, - type='kick', reason='He terk my jerb!', - expires_at=dt(5018, 11, 20, 15, 52, tzinfo=timezone.utc) - ), - Reminder( - author=User( - id=452, name='billy', - discriminator=5, avatar_hash=None - ), - channel_id=555, - content="oh no", - expiration=dt(5018, 11, 20, 15, 52, tzinfo=timezone.utc) - ) - ) - - def test_returns_string(self): - for instance in self.objects: - self.assertIsInstance(str(instance), str) diff --git a/api/tests/test_nominations.py b/api/tests/test_nominations.py deleted file mode 100644 index 1f03d1b0..00000000 --- a/api/tests/test_nominations.py +++ /dev/null @@ -1,41 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import Nomination, User - - -class NominationTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.author = User.objects.create( - id=5152, - name='Ro Bert', - discriminator=256, - avatar_hash=None - ) - cls.user = cls.author - - cls.nomination = Nomination.objects.create( - author=cls.author, - reason="he's good", - user=cls.author - ) - - def test_returns_400_on_attempt_to_update_frozen_field(self): - url = reverse('bot:nomination-detail', args=(self.user.id,), host='api') - response = self.client.put( - url, - data={'inserted_at': 'something bad'} - ) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'inserted_at': ['This field cannot be updated.'] - }) - - def test_returns_200_on_successful_update(self): - url = reverse('bot:nomination-detail', args=(self.user.id,), host='api') - response = self.client.patch( - url, - data={'reason': 'there are many like it, but this test is mine'} - ) - self.assertEqual(response.status_code, 200) diff --git a/api/tests/test_off_topic_channel_names.py b/api/tests/test_off_topic_channel_names.py deleted file mode 100644 index 60af1f62..00000000 --- a/api/tests/test_off_topic_channel_names.py +++ /dev/null @@ -1,152 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import OffTopicChannelName - - -class UnauthenticatedTests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_cannot_read_off_topic_channel_name_list(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_cannot_read_off_topic_channel_name_list_with_random_item_param(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(f'{url}?random_items=no') - - self.assertEqual(response.status_code, 401) - - -class EmptyDatabaseTests(APISubdomainTestCase): - def test_returns_empty_object(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) - - def test_returns_empty_list_with_get_all_param(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(f'{url}?random_items=5') - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) - - def test_returns_400_for_bad_random_items_param(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(f'{url}?random_items=totally-a-valid-integer') - - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'random_items': ["Must be a valid integer."] - }) - - def test_returns_400_for_negative_random_items_param(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(f'{url}?random_items=-5') - - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'random_items': ["Must be a positive integer."] - }) - - -class ListTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.test_name = OffTopicChannelName.objects.create(name='lemons-lemonade-stand') - cls.test_name_2 = OffTopicChannelName.objects.create(name='bbq-with-bisk') - - def test_returns_name_in_list(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual( - response.json(), - [ - self.test_name.name, - self.test_name_2.name - ] - ) - - def test_returns_single_item_with_random_items_param_set_to_1(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(f'{url}?random_items=1') - - self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.json()), 1) - - -class CreationTests(APISubdomainTestCase): - def setUp(self): - super().setUp() - - url = reverse('bot:offtopicchannelname-list', host='api') - self.name = "lemonade-shop" - response = self.client.post(f'{url}?name={self.name}') - self.assertEqual(response.status_code, 201) - - def test_name_in_full_list(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), [self.name]) - - def test_returns_400_for_missing_name_param(self): - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.post(url) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'name': ["This query parameter is required."] - }) - - def test_returns_400_for_bad_name_param(self): - url = reverse('bot:offtopicchannelname-list', host='api') - invalid_names = ( - 'space between words', - 'UPPERCASE', - '$$$$$$$$' - ) - - for name in invalid_names: - response = self.client.post(f'{url}?name={name}') - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'name': ["Enter a valid value."] - }) - - -class DeletionTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.test_name = OffTopicChannelName.objects.create(name='lemons-lemonade-stand') - cls.test_name_2 = OffTopicChannelName.objects.create(name='bbq-with-bisk') - - def test_deleting_unknown_name_returns_404(self): - url = reverse('bot:offtopicchannelname-detail', args=('unknown-name',), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 404) - - def test_deleting_known_name_returns_204(self): - url = reverse('bot:offtopicchannelname-detail', args=(self.test_name.name,), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 204) - - def test_name_gets_deleted(self): - url = reverse('bot:offtopicchannelname-detail', args=(self.test_name_2.name,), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 204) - - url = reverse('bot:offtopicchannelname-list', host='api') - response = self.client.get(url) - self.assertNotIn(self.test_name_2.name, response.json()) diff --git a/api/tests/test_rules.py b/api/tests/test_rules.py deleted file mode 100644 index c94f89cc..00000000 --- a/api/tests/test_rules.py +++ /dev/null @@ -1,35 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..views import RulesView - - -class RuleAPITests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_can_access_rules_view(self): - url = reverse('rules', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertIsInstance(response.json(), list) - - def test_link_format_query_param_produces_different_results(self): - url = reverse('rules', host='api') - markdown_links_response = self.client.get(url + '?link_format=md') - html_links_response = self.client.get(url + '?link_format=html') - self.assertNotEqual( - markdown_links_response.json(), - html_links_response.json() - ) - - def test_format_link_raises_value_error_for_invalid_target(self): - with self.assertRaises(ValueError): - RulesView._format_link("a", "b", "c") - - def test_get_returns_400_for_wrong_link_format(self): - url = reverse('rules', host='api') - response = self.client.get(url + '?link_format=unknown') - self.assertEqual(response.status_code, 400) diff --git a/api/tests/test_snake_names.py b/api/tests/test_snake_names.py deleted file mode 100644 index 41dfae63..00000000 --- a/api/tests/test_snake_names.py +++ /dev/null @@ -1,67 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import SnakeName - - -class StatusTests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_cannot_read_snake_name_list(self): - url = reverse('bot:snakename-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_cannot_read_snake_names_with_get_all_param(self): - url = reverse('bot:snakename-list', host='api') - response = self.client.get(f'{url}?get_all=True') - - self.assertEqual(response.status_code, 401) - - -class EmptyDatabaseSnakeNameTests(APISubdomainTestCase): - def test_endpoint_returns_empty_object(self): - url = reverse('bot:snakename-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), {}) - - def test_endpoint_returns_empty_list_with_get_all_param(self): - url = reverse('bot:snakename-list', host='api') - response = self.client.get(f'{url}?get_all=True') - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), []) - - -class SnakeNameListTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.snake_python = SnakeName.objects.create(name='Python', scientific='Totally.') - - def test_endpoint_returns_all_snakes_with_get_all_param(self): - url = reverse('bot:snakename-list', host='api') - response = self.client.get(f'{url}?get_all=True') - - self.assertEqual(response.status_code, 200) - self.assertEqual( - response.json(), - [ - { - 'name': self.snake_python.name, - 'scientific': self.snake_python.scientific - } - ] - ) - - def test_endpoint_returns_single_snake_without_get_all_param(self): - url = reverse('bot:snakename-list', host='api') - response = self.client.get(url) - self.assertEqual(response.json(), { - 'name': self.snake_python.name, - 'scientific': self.snake_python.scientific - }) diff --git a/api/tests/test_users.py b/api/tests/test_users.py deleted file mode 100644 index 90bc3d30..00000000 --- a/api/tests/test_users.py +++ /dev/null @@ -1,121 +0,0 @@ -from django_hosts.resolvers import reverse - -from .base import APISubdomainTestCase -from ..models import Role, User - - -class UnauthedUserAPITests(APISubdomainTestCase): - def setUp(self): - super().setUp() - self.client.force_authenticate(user=None) - - def test_detail_lookup_returns_401(self): - url = reverse('bot:user-detail', args=('whatever',), host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_list_returns_401(self): - url = reverse('bot:user-list', host='api') - response = self.client.get(url) - - self.assertEqual(response.status_code, 401) - - def test_create_returns_401(self): - url = reverse('bot:user-list', host='api') - response = self.client.post(url, data={'hi': 'there'}) - - self.assertEqual(response.status_code, 401) - - def test_delete_returns_401(self): - url = reverse('bot:user-detail', args=('whatever',), host='api') - response = self.client.delete(url) - - self.assertEqual(response.status_code, 401) - - -class CreationTests(APISubdomainTestCase): - @classmethod - def setUpTestData(cls): # noqa - cls.role = Role.objects.create( - id=5, - name="Test role pls ignore", - colour=2, - permissions=0b01010010101 - ) - - def test_accepts_valid_data(self): - url = reverse('bot:user-list', host='api') - data = { - 'id': 42, - 'avatar_hash': "validavatarhashiswear", - 'name': "Test", - 'discriminator': 42, - 'roles': [ - self.role.id - ], - 'in_guild': True - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 201) - self.assertEqual(response.json(), data) - - user = User.objects.get(id=42) - self.assertEqual(user.avatar_hash, data['avatar_hash']) - self.assertEqual(user.name, data['name']) - self.assertEqual(user.discriminator, data['discriminator']) - self.assertEqual(user.in_guild, data['in_guild']) - - def test_supports_multi_creation(self): - url = reverse('bot:user-list', host='api') - data = [ - { - 'id': 5, - 'avatar_hash': "hahayes", - 'name': "test man", - 'discriminator': 42, - 'roles': [ - self.role.id - ], - 'in_guild': True - }, - { - 'id': 8, - 'avatar_hash': "maybenot", - 'name': "another test man", - 'discriminator': 555, - 'roles': [], - 'in_guild': False - } - ] - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 201) - self.assertEqual(response.json(), data) - - def test_returns_400_for_unknown_role_id(self): - url = reverse('bot:user-list', host='api') - data = { - 'id': 5, - 'avatar_hash': "hahayes", - 'name': "test man", - 'discriminator': 42, - 'roles': [ - 190810291 - ] - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - - def test_returns_400_for_bad_data(self): - url = reverse('bot:user-list', host='api') - data = { - 'id': True, - 'avatar_hash': 1902831, - 'discriminator': "totally!" - } - - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) diff --git a/api/tests/test_validators.py b/api/tests/test_validators.py deleted file mode 100644 index d2c0a136..00000000 --- a/api/tests/test_validators.py +++ /dev/null @@ -1,213 +0,0 @@ -from django.core.exceptions import ValidationError -from django.test import TestCase - -from ..validators import ( - validate_bot_setting_name, - validate_tag_embed -) - - -REQUIRED_KEYS = ( - 'content', 'fields', 'image', 'title', 'video' -) - - -class BotSettingValidatorTests(TestCase): - def test_accepts_valid_names(self): - validate_bot_setting_name('defcon') - - def test_rejects_bad_names(self): - with self.assertRaises(ValidationError): - validate_bot_setting_name('bad name') - -class TagEmbedValidatorTests(TestCase): - def test_rejects_non_mapping(self): - with self.assertRaises(ValidationError): - validate_tag_embed('non-empty non-mapping') - - def test_rejects_missing_required_keys(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'unknown': "key" - }) - - def test_rejects_one_correct_one_incorrect(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'provider': "??", - 'title': "" - }) - - def test_rejects_empty_required_key(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': '' - }) - - def test_rejects_list_as_embed(self): - with self.assertRaises(ValidationError): - validate_tag_embed([]) - - def test_rejects_required_keys_and_unknown_keys(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "the duck walked up to the lemonade stand", - 'and': "he said to the man running the stand" - }) - - def test_rejects_too_long_title(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': 'a' * 257 - }) - - def test_rejects_too_many_fields(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'fields': [{} for _ in range(26)] - }) - - def test_rejects_too_long_description(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'description': 'd' * 2049 - }) - - def test_allows_valid_embed(self): - validate_tag_embed({ - 'title': "My embed", - 'description': "look at my embed, my embed is amazing" - }) - - def test_allows_unvalidated_fields(self): - validate_tag_embed({ - 'title': "My embed", - 'provider': "what am I??" - }) - - def test_rejects_fields_as_list_of_non_mappings(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'fields': ['abc'] - }) - - def test_rejects_fields_with_unknown_fields(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'fields': [ - { - 'what': "is this field" - } - ] - }) - - def test_rejects_fields_with_too_long_name(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'fields': [ - { - 'name': "a" * 257 - } - ] - }) - - def test_rejects_one_correct_one_incorrect_field(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'fields': [ - { - 'name': "Totally valid", - 'value': "LOOK AT ME" - }, - { - 'oh': "what is this key?" - } - ] - }) - - def test_allows_valid_fields(self): - validate_tag_embed({ - 'fields': [ - { - 'name': "valid", - 'value': "field" - } - ] - }) - - def test_rejects_footer_as_non_mapping(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'footer': [] - }) - - def test_rejects_footer_with_unknown_fields(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'footer': { - 'duck': "quack" - } - }) - - def test_rejects_footer_with_empty_text(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'footer': { - 'text': "" - } - }) - - def test_allows_footer_with_proper_values(self): - validate_tag_embed({ - 'title': "whatever", - 'footer': { - 'text': "django good" - } - }) - - def test_rejects_author_as_non_mapping(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'author': [] - }) - - def test_rejects_author_with_unknown_field(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'author': { - 'field': "that is unknown" - } - }) - - def test_rejects_author_with_empty_name(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'author': { - 'name': "" - } - }) - - def test_rejects_author_with_one_correct_one_incorrect(self): - with self.assertRaises(ValidationError): - validate_tag_embed({ - 'title': "whatever", - 'author': { - # Relies on "dictionary insertion order remembering" (D.I.O.R.) behaviour - 'url': "bobswebsite.com", - 'name': "" - } - }) - - def test_allows_author_with_proper_values(self): - validate_tag_embed({ - 'title': "whatever", - 'author': { - 'name': "Bob" - } - }) |