diff --git a/main/tests.py b/main/tests.py index 99d58cc..5f71955 100644 --- a/main/tests.py +++ b/main/tests.py @@ -1,8 +1,10 @@ +import random from unittest.mock import patch -from urllib.parse import urlparse from django.contrib.auth.models import User from django.core import mail +from django.http import HttpResponseRedirect +from django.template.loader import render_to_string from django.test import TestCase, Client from django.urls import reverse, reverse_lazy from django.utils import translation @@ -35,39 +37,20 @@ class RegistrationTestCase(TestCase): resp = self.client.post(reverse('registration'), data={'email': '123@test.ru'}) self.assertContains(resp, 'Этот адрес электронной почты уже используется', count=1, status_code=200) - def test_registration_email_sending(self): - # TODO: Найти способ лучше проверять сообщения - email_template = [ - '', - 'Вы получили это письмо, потому что вы (или кто-то другой) запросили восстановление пароля ' - 'от учётной записи на сайте testserver, которая связана с этим адресом электронной почты.', - '', - 'Пожалуйста, перейдите на эту страницу и введите новый пароль:', - '', - 'url', - '', - f'Ваше имя пользователя (на случай, если вы его забыли): {self.any_zendesk_user_email}', - '', - 'Спасибо, что используете наш сайт!', - '', - 'Команда сайта testserver', - '', - '', - '', - ] - with self.settings(EMAIL_BACKEND=self.email_backend) and translation.override('ru'): - self.client.post(reverse('registration'), data={'email': self.any_zendesk_user_email}) - + def test_registration_send_email(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + response: HttpResponseRedirect = \ + self.client.post(reverse('registration'), data={'email': self.any_zendesk_user_email}) + self.assertEqual(response.status_code, 302) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].to, [self.zendesk_admin_email]) - self.assertEqual(mail.outbox[0].from_email, sets.DEFAULT_FROM_EMAIL) - message = mail.outbox[0].body.split('\n') - for i in range(len(message)): - if email_template[i] != 'url': - self.assertEqual(message[i], email_template[i]) - else: - self.assertTrue(urlparse(message[i]).scheme) + # context that the email template was rendered with + email_context = response.context[0].dicts[1] + correct_subject = render_to_string('registration/password_reset_subject.txt', email_context, response.request) + self.assertEqual(mail.outbox[0].subject, correct_subject.strip()) + correct_body = render_to_string('registration/password_reset_email.html', email_context, response.request) + self.assertEqual(mail.outbox[0].body, correct_body) def test_registration_user_creating(self): with self.settings(EMAIL_BACKEND=self.email_backend): @@ -148,3 +131,134 @@ class MakeEngineerTestCase(TestCase): self.assertEqual(len(call_list), 2) for obj in mock_objects: self.assertEqual(obj[0][0].custom_role_id, sets.ZENDESK_ROLES['engineer']) + + +class PasswordResetTestCase(TestCase): + fixtures = ['fixtures/test_make_engineer.json'] + + def setUp(self): + self.user = '123@test.ru' + self.email_backend = 'django.core.mail.backends.locmem.EmailBackend' + self.client = Client() + self.client.force_login(User.objects.get(email=self.user)) + + def test_redirect(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + resp = self.client.post(reverse_lazy('password_reset'), data={'email': self.user}) + self.assertRedirects(resp, reverse('password_reset_done')) + self.assertEqual(resp.status_code, 302) + + def test_send_email(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + response: HttpResponseRedirect = \ + self.client.post(reverse_lazy('password_reset'), data={'email': self.user}) + self.assertEqual(response.status_code, 302) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].to, [self.user]) + + # context that the email template was rendered with + email_context = response.context[0].dicts[1] + correct_subject = render_to_string('registration/password_reset_subject.txt', email_context, response.request) + self.assertEqual(mail.outbox[0].subject, correct_subject.strip()) + correct_body = render_to_string('registration/password_reset_email.html', email_context, response.request) + self.assertEqual(mail.outbox[0].body, correct_body) + + def test_email_invalid(self): + with self.settings(EMAIL_BACKEND=self.email_backend) and translation.override('ru'): + resp = self.client.post(reverse_lazy('password_reset'), data={'email': 1}) + self.assertContains(resp, 'Введите правильный адрес электронной почты.', count=1, status_code=200) + + def test_user_does_not_exist(self): + with self.settings(EMAIL_BACKEND=self.email_backend): + resp = self.client.post(reverse_lazy('password_reset'), data={'email': self.user + str(random.random())}) + self.assertRedirects(resp, reverse('password_reset_done')) + self.assertEqual(resp.status_code, 302) + self.assertEqual(len(mail.outbox), 0) + + +class PasswordChangeTestCase(TestCase): + fixtures = ['fixtures/test_make_engineer.json'] + + def setUp(self): + self.user = '123@test.ru' + self.client = Client() + self.client.force_login(User.objects.get(email=self.user)) + self.set_password() + + def set_password(self): + user: User = User.objects.get(email=self.user) + user.set_password('ImpossiblyHardPassword') + user.save() + self.client.force_login(User.objects.get(email=self.user)) + + def test_change_successful(self): + self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': 'EasyPassword', + 'new_password2': 'EasyPassword', + } + ) + user = User.objects.get(email=self.user) + self.assertTrue(user.check_password('EasyPassword')) + + def test_invalid_old_password(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'EasyPassword', + 'new_password1': 'EasyPassword', + 'new_password2': 'EasyPassword', + } + ) + self.assertContains(resp, 'Ваш старый пароль введен неправильно', count=1, status_code=200) + + def test_different_new_passwords(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': 'EasyPassword', + 'new_password2': 'EasyPassword1', + } + ) + self.assertContains(resp, 'Введенные пароли не совпадают', count=1, status_code=200) + + def test_invalid_new_password1(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': 'short', + 'new_password2': 'short', + } + ) + self.assertContains(resp, 'Введённый пароль слишком короткий', count=1, status_code=200) + + def test_invalid_new_password2(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': '123123123123123123132123123', + 'new_password2': '123123123123123123132123123', + } + ) + self.assertContains(resp, 'Введённый пароль состоит только из цифр', count=1, status_code=200) + + def test_invalid_new_password3(self): + with translation.override('ru'): + resp = self.client.post( + reverse_lazy('password_change'), + data={ + 'old_password': 'ImpossiblyHardPassword', + 'new_password1': self.user, + 'new_password2': self.user, + } + ) + self.assertContains(resp, 'Введённый пароль слишком похож на имя пользователя', count=1, status_code=200)