Merge pull request 'Upgrade to 3.12' (#630) from python-3.12 into main
[inboxen.git] / inboxen / test.py
blob707ad188ffe2e39a58e0365c75501a98b0bc94f2
1 ##
2 # Copyright (C) 2014, 2015, 2018 Jessica Tallon & Matt Molyneaux
4 # This file is part of Inboxen.
6 # Inboxen is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # Inboxen is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
16 # You should have received a copy of the GNU Affero General Public License
17 # along with Inboxen. If not, see <http://www.gnu.org/licenses/>.
20 import logging
21 import os
22 import warnings
24 from django import test
25 from django.contrib.auth.models import AnonymousUser
26 from django.contrib.messages.storage.session import SessionStorage
27 from django.contrib.sessions.middleware import SessionMiddleware
28 from django.http import HttpRequest, HttpResponse
29 from django.test.runner import DiscoverRunner
30 from django.utils.crypto import get_random_string
31 from django_otp import DEVICE_ID_SESSION_KEY
32 from django_otp.middleware import OTPMiddleware
33 from django_otp.plugins.otp_static.models import StaticDevice
34 from elevate import settings as elevate_settings
35 from elevate.middleware import ElevateMiddleware
37 _log = logging.getLogger(__name__)
40 class MockRequest(HttpRequest):
41 """Mock up a request object"""
43 def __init__(self, user=None, session_id=None, has_otp=False, has_sudo=False):
44 super(MockRequest, self).__init__()
45 self.method = "GET"
47 if user is None:
48 self.user = AnonymousUser()
49 else:
50 self.user = user
52 session = SessionMiddleware(lambda x: x)
53 self.session = session.SessionStore(session_id)
54 self._messages = SessionStorage(self)
55 self.META = {"REMOTE_ADDR": "127.0.0.1"}
57 # sudo
58 ElevateMiddleware(lambda x: x)(self)
59 if has_sudo:
60 grant_sudo(self)
62 # otp
63 if has_otp:
64 grant_otp(self, self.user)
65 OTPMiddleware(lambda x: x)(self)
68 # TODO: submit to django-elevate?
69 def grant_sudo(client_or_request):
70 """Sets a cookie on the test client or request that django-elevate will use"""
71 response = HttpResponse()
72 token = get_random_string(elevate_settings.TOKEN_LENGTH)
74 response.set_signed_cookie(
75 elevate_settings.COOKIE_NAME,
76 token,
77 salt=elevate_settings.COOKIE_SALT,
78 max_age=elevate_settings.COOKIE_AGE,
79 secure=False,
80 httponly=True,
81 path=elevate_settings.COOKIE_PATH,
82 domain=elevate_settings.COOKIE_DOMAIN,
85 if hasattr(client_or_request, "cookies"):
86 client_or_request.cookies[elevate_settings.COOKIE_NAME] = response.cookies[elevate_settings.COOKIE_NAME]
87 elif hasattr(client_or_request, "COOKIES"):
88 client_or_request.COOKIES[elevate_settings.COOKIE_NAME] = response.cookies[elevate_settings.COOKIE_NAME].value
89 else:
90 raise TypeError("%r has neither cookies nor COOKIES" % client_or_request)
92 # client.session is a property that returns new objects
93 session = client_or_request.session
94 session[elevate_settings.COOKIE_NAME] = token
95 session.save()
98 def grant_otp(client_or_request, user):
99 """Sets session data for OTP"""
100 device = StaticDevice.objects.get_or_create(user=user)[0]
102 # client.session is a property that returns new objects
103 session = client_or_request.session
104 session[DEVICE_ID_SESSION_KEY] = device.persistent_id
105 session.save()
108 class InboxenTestRunner(DiscoverRunner):
109 """Test runner for Inboxen"""
110 def setup_test_environment(self, **kwargs):
111 self.is_testing_var_set = int(os.getenv('INBOXEN_TESTING', '0')) > 0
112 super(InboxenTestRunner, self).setup_test_environment(**kwargs)
114 def teardown_test_environment(self, **kwargs):
115 super(InboxenTestRunner, self).teardown_test_environment(**kwargs)
116 if not self.is_testing_var_set:
117 warnings.warn("You did not set 'INBOXEN_TESTING' in your environment. Test results will be unreliable!")
120 CLIENT_METHODS_TO_MAKE_SECURE = [
121 'get',
122 'post',
123 'head',
124 'trace',
125 'options',
126 'put',
127 'patch',
128 'delete',
132 class SecureClient(test.Client):
133 """Like Client, but changes the deafult "secure" kwargs to True on certain methods"""
134 def __getattribute__(self, name):
135 attr = super(SecureClient, self).__getattribute__(name)
136 if name in CLIENT_METHODS_TO_MAKE_SECURE:
138 def be_secure(*args, **kwargs):
139 kwargs.setdefault("secure", True)
140 return attr(*args, **kwargs)
142 return be_secure
143 else:
144 return attr
147 class InboxenTestCase(test.TestCase):
148 client_class = SecureClient