aboutsummaryrefslogtreecommitdiffstats
path: root/pydis_site/apps/api/tests/base.py
blob: 0290fa69df779e9a65d3887f238f7ce9d3d2eebc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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 pydis_site.apps.api 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 pydis_site.apps.api 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 pydis_site.apps.api 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)