tcms.kiwi_auth.tests.test_views   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 408
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 34
eloc 265
dl 0
loc 408
rs 9.68
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A TestSetRandomKey.test_set_random_key() 0 12 1
A TestSetRandomKey.setUpTestData() 0 3 1
A TestLogout.test_logout_redirects_to_login_page() 0 6 1
A TestRegistration.setUp() 0 3 1
A TestForceToSetRandomKey.test_set_random_key_forcely() 0 7 1
A TestForceToSetRandomKey.setUpTestData() 0 5 1
A TestLogout.setUpTestData() 0 8 1
A TestLogout.test_logout_then_goto_next() 0 7 1
A TestConfirm.setUpTestData() 0 3 1
A TestConfirm.test_fail_if_activation_key_expired() 0 17 2
A TestConfirm.test_confirm() 0 17 2
A TestRegistration.test_register_user_by_email_confirmation() 0 41 1
A TestRegistration.test_register_user_and_activate_by_admin() 0 17 2
A TestConfirm.setUp() 0 3 1
A TestRegistration.test_first_user_is_superuser() 0 5 1
A TestRegistration.test_register_user_sends_signal() 0 5 1
A TestRegistration.test_signal_handler_notifies_admins() 0 40 1
A TestConfirm.test_fail_if_activation_key_does_not_exist() 0 11 1
A TestRegistration.test_only_one_superuser() 0 11 1
A TestRegistration.test_register_user_already_registered() 0 17 1
A TestRegistration.test_open_registration_page() 0 4 1
A TestRegistration.test_invalid_form() 0 15 1
A TestPasswordResetView.setUp() 0 2 1
A TestPasswordResetView.test_send_mail_for_password_reset() 0 12 1
A TestPasswordResetView.test_form_class() 0 5 1
A TestPasswordResetView.test_open_password_reset_page() 0 5 1
A TestLoginViewWithCustomTemplate.test_get_template_names() 0 6 1
A TestRegistration.assert_user_registration() 0 37 4
1
# -*- coding: utf-8 -*-
2
# pylint: disable=invalid-name
3
4
import datetime
5
6
from django.conf import settings
7
from django.contrib.auth import get_user_model
8
from django.contrib.sites.models import Site
9
from django.test import TestCase, override_settings
10
from django.urls import reverse
11
from django.utils import timezone
12
from django.utils.translation import gettext_lazy as _
13
from mock import patch
14
15
from tcms import signals
16
from tcms.kiwi_auth import forms
17
from tcms.kiwi_auth.models import UserActivationKey
18
from tcms.tests.factories import UserFactory
19
20
User = get_user_model()  # pylint: disable=invalid-name
21
22
23
class TestSetRandomKey(TestCase):
24
    """Test case for UserActivationKey.set_random_key_for_user"""
25
26
    @classmethod
27
    def setUpTestData(cls):
28
        cls.new_user = UserFactory()
29
30
    @patch("tcms.kiwi_auth.models.datetime")
31
    def test_set_random_key(self, mock_datetime):
32
        now = timezone.now()
33
        in_7_days = datetime.timedelta(7)
34
35
        mock_datetime.datetime.today.return_value = now
36
        mock_datetime.timedelta.return_value = in_7_days
37
38
        activation_key = UserActivationKey.set_random_key_for_user(self.new_user)
39
        self.assertEqual(self.new_user, activation_key.user)
40
        self.assertNotEqual("", activation_key.activation_key)
41
        self.assertEqual(now + in_7_days, activation_key.key_expires)
42
43
44
class TestForceToSetRandomKey(TestCase):
45
    """Test case for UserActivationKey.set_random_key_for_user forcely"""
46
47
    @classmethod
48
    def setUpTestData(cls):
49
        cls.new_user = UserFactory()
50
        cls.origin_activation_key = UserActivationKey.set_random_key_for_user(
51
            cls.new_user
52
        )
53
54
    def test_set_random_key_forcely(self):
55
        new_activation_key = UserActivationKey.set_random_key_for_user(
56
            self.new_user, force=True
57
        )
58
        self.assertEqual(self.origin_activation_key.user, new_activation_key.user)
59
        self.assertNotEqual(
60
            self.origin_activation_key.activation_key, new_activation_key.activation_key
61
        )
62
63
64
# ### Test cases for view methods ###
65
66
67
class TestLogout(TestCase):
68
    """Test for logout view method"""
69
70
    @classmethod
71
    def setUpTestData(cls):
72
        super(TestLogout, cls).setUpTestData()
73
74
        cls.tester = UserFactory()
75
        cls.tester.set_password("password")
76
        cls.tester.save()
77
        cls.logout_url = reverse("tcms-logout")
78
79
    def test_logout_redirects_to_login_page(self):
80
        self.client.login(  # nosec:B106:hardcoded_password_funcarg
81
            username=self.tester.username, password="password"
82
        )
83
        response = self.client.get(self.logout_url, follow=True)
84
        self.assertRedirects(response, reverse("tcms-login"))
85
86
    def test_logout_then_goto_next(self):
87
        self.client.login(  # nosec:B106:hardcoded_password_funcarg
88
            username=self.tester.username, password="password"
89
        )
90
        next_url = reverse("tcms-login") + "?next=" + reverse("plans-search")
91
        response = self.client.get(self.logout_url, {"next": next_url}, follow=True)
92
        self.assertRedirects(response, next_url)
93
94
95
class TestRegistration(TestCase):
96
    def setUp(self):
97
        self.register_url = reverse("tcms-register")
98
        self.fake_activate_key = "secret-activate-key"
99
100
    def test_open_registration_page(self):
101
        response = self.client.get(self.register_url)
102
        _register = _("Register")
103
        self.assertContains(response, f">{_register}</button>")
104
105
    def assert_user_registration(self, username, follow=False):
106
        with patch("tcms.kiwi_auth.models.secrets") as _secrets:
107
            _secrets.token_hex.return_value = self.fake_activate_key
108
109
            try:
110
                # https://github.com/mbi/django-simple-captcha/issues/84
111
                # pylint: disable=import-outside-toplevel
112
                from captcha.conf import settings as captcha_settings
113
114
                captcha_settings.CAPTCHA_TEST_MODE = True
115
116
                response = self.client.post(
117
                    self.register_url,
118
                    {
119
                        "username": username,
120
                        "password1": "password",
121
                        "password2": "password",
122
                        "email": "[email protected]",
123
                        "captcha_0": "PASSED",
124
                        "captcha_1": "PASSED",
125
                    },
126
                    follow=follow,
127
                )
128
            finally:
129
                captcha_settings.CAPTCHA_TEST_MODE = False
130
131
        user = User.objects.get(username=username)
132
        self.assertEqual("[email protected]", user.email)
133
        if User.objects.filter(is_superuser=True).count() == 1 and user.is_superuser:
134
            self.assertTrue(user.is_active)
135
        else:
136
            self.assertFalse(user.is_active)
137
138
        key = UserActivationKey.objects.get(user=user)
139
        self.assertEqual(self.fake_activate_key, key.activation_key)
140
141
        return response, user
142
143
    @patch("tcms.signals.USER_REGISTERED_SIGNAL.send")
144
    def test_register_user_sends_signal(self, signal_mock):
145
        self.assert_user_registration("new-signal-tester")
146
        self.assertTrue(signal_mock.called)
147
        self.assertEqual(1, signal_mock.call_count)
148
149
    @override_settings(ADMINS=[("Test Admin", "[email protected]")])
150
    @patch("tcms.core.utils.mailto.send_mail")
151
    def test_signal_handler_notifies_admins(self, send_mail):
152
        # connect the handler b/c it is not connected by default
153
        signals.USER_REGISTERED_SIGNAL.connect(signals.notify_admins)
154
155
        try:
156
            response, user = self.assert_user_registration("signal-handler")
157
            self.assertRedirects(
158
                response, reverse("core-views-index"), target_status_code=302
159
            )
160
161
            # 1 - verification mail, 2 - email to admin
162
            self.assertTrue(send_mail.called)
163
            self.assertEqual(2, send_mail.call_count)
164
165
            # verify we've actually sent the admin email
166
            self.assertIn(
167
                str(_("New user awaiting approval")), send_mail.call_args_list[0][0][0]
168
            )
169
            values = {
170
                "username": "signal-handler",
171
                "user_url": f"http://testserver/admin/auth/user/{user.pk}/change/",
172
            }
173
            expected = (
174
                _(
175
                    """Dear Administrator,
176
somebody just registered an account with username %(username)s at your
177
Kiwi TCMS instance and is awaiting your approval!
178
179
Go to %(user_url)s to activate the account!"""
180
                )
181
                % values
182
            )
183
            self.assertEqual(
184
                expected.strip(), send_mail.call_args_list[0][0][1].strip()
185
            )
186
            self.assertIn("[email protected]", send_mail.call_args_list[0][0][-1])
187
        finally:
188
            signals.USER_REGISTERED_SIGNAL.disconnect(signals.notify_admins)
189
190
    @patch("tcms.core.utils.mailto.send_mail")
191
    def test_register_user_by_email_confirmation(self, send_mail):
192
        response, user = self.assert_user_registration("new-tester", follow=True)
193
        self.assertContains(
194
            response,
195
            _(
196
                "Your account has been created, please check your mailbox for confirmation"
197
            ),
198
        )
199
200
        site = Site.objects.get(pk=settings.SITE_ID)
201
        _confirm_url = reverse("tcms-confirm", args=[self.fake_activate_key])
202
        confirm_url = f"http://{site.domain}{_confirm_url}"
203
204
        # Verify notification mail
205
        values = {
206
            "user": user.username,
207
            "site_domain": site.domain,
208
            "confirm_url": confirm_url,
209
        }
210
        expected_subject = (
211
            settings.EMAIL_SUBJECT_PREFIX
212
            + _("Your new %s account confirmation") % site.domain
213
        )
214
        expected_body = (
215
            _(
216
                """Welcome %(user)s,
217
thank you for signing up for an %(site_domain)s account!
218
219
To activate your account, click this link:
220
%(confirm_url)s"""
221
            )
222
            % values
223
            + "\n"
224
        )
225
        send_mail.assert_called_once_with(
226
            expected_subject,
227
            expected_body,
228
            settings.DEFAULT_FROM_EMAIL,
229
            ["[email protected]"],
230
            fail_silently=False,
231
        )
232
233
    @override_settings(
234
        AUTO_APPROVE_NEW_USERS=False,
235
        ADMINS=[("admin1", "[email protected]"), ("admin2", "[email protected]")],
236
    )
237
    def test_register_user_and_activate_by_admin(self):
238
        response, _user = self.assert_user_registration("plan-tester", follow=True)
239
240
        self.assertContains(
241
            response,
242
            _(
243
                "Your account has been created, but you need an administrator to activate it"
244
            ),
245
        )
246
247
        for (name, email) in settings.ADMINS:
248
            self.assertContains(
249
                response, f'<a href="mailto:{email}">{name}</a>', html=True
250
            )
251
252
    def test_invalid_form(self):
253
        response = self.client.post(
254
            self.register_url,
255
            {
256
                "username": "kiwi-tester",
257
                "password1": "password-1",
258
                "password2": "password-2",
259
                "email": "[email protected]",
260
            },
261
            follow=False,
262
        )
263
264
        self.assertContains(response, _("The two password fields didn’t match."))
265
        self.assertEqual(response.status_code, 200)
266
        self.assertTemplateUsed(response, "registration/registration_form.html")
267
268
    def test_register_user_already_registered(self):
269
        User.objects.create_user("kiwi-tester", "[email protected]", "password")
270
271
        response = self.client.post(
272
            self.register_url,
273
            {
274
                "username": "test_user",
275
                "password1": "password",
276
                "password2": "password",
277
                "email": "[email protected]",
278
            },
279
            follow=False,
280
        )
281
        self.assertContains(response, _("A user with that email already exists."))
282
283
        user = User.objects.filter(username="test_user")
284
        self.assertEqual(user.count(), 0)
285
286
    def test_first_user_is_superuser(self):
287
        _response, user = self.assert_user_registration("tester_1")
288
289
        self.assertTrue(user.is_superuser)
290
        self.assertTrue(user.is_active)
291
292
    def test_only_one_superuser(self):
293
        user1 = User.objects.create_user(
294
            "kiwi-tester", "[email protected]", "password"
295
        )
296
        user1.is_superuser = True
297
        user1.save()
298
299
        self.assertTrue(user1.is_superuser)
300
301
        _response, user2 = self.assert_user_registration("plan-tester")
302
        self.assertFalse(user2.is_superuser)
303
304
305
class TestConfirm(TestCase):
306
    """Test for activation key confirmation"""
307
308
    @classmethod
309
    def setUpTestData(cls):
310
        cls.new_user = UserFactory()
311
312
    def setUp(self):
313
        self.new_user.is_active = False
314
        self.new_user.save()
315
316
    def test_fail_if_activation_key_does_not_exist(self):
317
        confirm_url = reverse("tcms-confirm", args=["nonexisting-activation-key"])
318
        response = self.client.get(confirm_url, follow=True)
319
320
        self.assertContains(
321
            response, _("This activation key no longer exists in the database")
322
        )
323
324
        # user account not activated
325
        user = User.objects.get(username=self.new_user.username)
326
        self.assertFalse(user.is_active)
327
328
    def test_fail_if_activation_key_expired(self):
329
        fake_activation_key = "secret-activation-key"
330
331
        with patch("tcms.kiwi_auth.models.secrets") as _secrets:
332
            _secrets.token_hex.return_value = fake_activation_key
333
            key = UserActivationKey.set_random_key_for_user(self.new_user)
334
            key.key_expires = timezone.now() - datetime.timedelta(days=10)
335
            key.save()
336
337
        confirm_url = reverse("tcms-confirm", args=[fake_activation_key])
338
        response = self.client.get(confirm_url, follow=True)
339
340
        self.assertContains(response, _("This activation key has expired"))
341
342
        # user account not activated
343
        user = User.objects.get(username=self.new_user.username)
344
        self.assertFalse(user.is_active)
345
346
    def test_confirm(self):
347
        fake_activate_key = "secret-activate-key"
348
349
        with patch("tcms.kiwi_auth.models.secrets") as _secrets:
350
            _secrets.token_hex.return_value = fake_activate_key
351
            UserActivationKey.set_random_key_for_user(self.new_user)
352
353
        confirm_url = reverse("tcms-confirm", args=[fake_activate_key])
354
        response = self.client.get(confirm_url, follow=True)
355
356
        self.assertContains(response, _("Your account has been activated successfully"))
357
358
        # user account activated
359
        user = User.objects.get(username=self.new_user.username)
360
        self.assertTrue(user.is_active)
361
        activate_key_deleted = not UserActivationKey.objects.filter(user=user).exists()
362
        self.assertTrue(activate_key_deleted)
363
364
365
class TestLoginViewWithCustomTemplate(TestCase):
366
    """Test for login view with custom template"""
367
368
    def test_get_template_names(self):
369
        response = self.client.get(reverse("tcms-login"))
370
        self.assertIsNotNone(response.template_name)
371
        self.assertEqual(
372
            response.template_name,
373
            ["registration/custom_login.html", "registration/login.html"],
374
        )
375
376
377
class TestPasswordResetView(TestCase):
378
    """Test for password reset view"""
379
380
    def setUp(self):
381
        self.password_reset_url = reverse("tcms-password_reset")
382
383
    def test_form_class(self):
384
        response = self.client.get(self.password_reset_url)
385
        self.assertEqual(
386
            str(type(response.context["form"])),
387
            str(forms.PasswordResetForm),
388
        )
389
390
    def test_open_password_reset_page(self):
391
        response = self.client.get(self.password_reset_url)
392
393
        _password_reset = _("Password reset")
394
        self.assertContains(response, f">{_password_reset}</button>")
395
396
    @patch("tcms.kiwi_auth.forms.DjangoPasswordResetForm.send_mail")
397
    def test_send_mail_for_password_reset(self, mail_sent):
398
        user = User.objects.create_user("kiwi-tester", "[email protected]", "password")
399
        user.is_active = True
400
        user.save()
401
        data = {"email": "[email protected]"}
402
        response = self.client.post(self.password_reset_url, data, follow=True)
403
404
        self.assertContains(response, _("Password reset email was sent"))
405
406
        # Verify mail is sent
407
        mail_sent.assert_called_once()
408