bgneal@565: """ bgneal@565: View tests for the accounts application. bgneal@565: bgneal@565: """ bgneal@565: import datetime bgneal@762: import re bgneal@565: bgneal@565: from django.test import TestCase bgneal@565: from django.core.urlresolvers import reverse bgneal@659: from django.core import mail bgneal@576: from django.contrib.auth.models import User bgneal@576: from django.contrib.auth.hashers import check_password bgneal@565: bgneal@565: from accounts.models import PendingUser bgneal@565: from accounts.models import IllegalUsername bgneal@565: from accounts.models import IllegalEmail bgneal@565: bgneal@565: bgneal@565: class RegistrationTest(TestCase): bgneal@565: bgneal@565: def setUp(self): bgneal@565: u = User.objects.create_user('existing_user', 'existing_user@example.com', 'pw') bgneal@565: u.save() bgneal@565: bgneal@565: # a 2nd user has the same email as another bgneal@565: u = User.objects.create_user('existing_user2', 'existing_user@example.com', 'pw') bgneal@565: u.save() bgneal@565: bgneal@565: PendingUser.objects.create(username='pending_user', bgneal@565: email='pending_user@example.com', bgneal@565: password='pw', bgneal@565: date_joined=datetime.datetime.now(), bgneal@565: key='key') bgneal@565: bgneal@565: IllegalUsername.objects.create(username='illegalusername') bgneal@565: IllegalEmail.objects.create(email='illegal@example.com') bgneal@565: bgneal@782: self.post_vals = { bgneal@782: 'username': 'a_new_user', bgneal@782: 'email': 'test@example.com', bgneal@782: 'password1': 'my_password', bgneal@782: 'password2': 'my_password', bgneal@782: 'agree_age': 'on', bgneal@782: 'agree_tos': 'on', bgneal@782: 'agree_privacy': 'on', bgneal@782: 'question1': '101', bgneal@782: 'question2': '', bgneal@782: 'question3': '', bgneal@782: } bgneal@782: bgneal@565: def test_get_view(self): bgneal@565: """ bgneal@565: Test a simple get of the registration view bgneal@565: bgneal@565: """ bgneal@565: response = self.client.get(reverse('accounts-register')) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: bgneal@565: def test_existing_user(self): bgneal@565: """ bgneal@565: Ensure we can't register with an existing username. bgneal@565: bgneal@565: """ bgneal@565: response = self.client.post(reverse('accounts-register'), { bgneal@565: 'username': 'existing_user', bgneal@565: 'email': 'test@example.com', bgneal@565: 'password1': 'my_password', bgneal@565: 'password2': 'my_password', bgneal@565: 'agree_age': 'on', bgneal@565: 'agree_tos': 'on', bgneal@565: 'agree_privacy': 'on', bgneal@565: 'question1': '101', bgneal@565: 'question2': '', bgneal@905: 'question3': '', bgneal@565: }) bgneal@565: bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, 'A user with that username already exists') bgneal@565: bgneal@565: def test_pending_user(self): bgneal@565: """ bgneal@565: Ensure we can't register with a pending username. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['username'] = 'pending_user' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, 'A pending user with that username already exists') bgneal@565: bgneal@565: def test_illegal_username(self): bgneal@565: """ bgneal@565: Ensure we can't register with a banned username. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['username'] = 'illegalusername' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, 'That username is not allowed') bgneal@565: bgneal@565: def test_duplicate_existing_email(self): bgneal@565: """ bgneal@565: Ensure we can't register with a duplicate email address. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['email'] = 'existing_user@example.com' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, 'A user with that email address already exists') bgneal@565: bgneal@565: def test_duplicate_pending_email(self): bgneal@565: """ bgneal@565: Ensure we can't register with a duplicate email address. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['email'] = 'pending_user@example.com' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, 'A pending user with that email address already exists') bgneal@565: bgneal@565: def test_illegal_email(self): bgneal@565: """ bgneal@565: Ensure we can't register with a banned email address. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['email'] = 'illegal@example.com' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, 'That email address is not allowed') bgneal@565: bgneal@565: def test_password_match(self): bgneal@565: """ bgneal@565: Ensure the passwords match. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['password2'] = "doesn't match" bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, "The two password fields didn't match") bgneal@565: bgneal@565: def test_question1(self): bgneal@565: """ bgneal@565: Ensure our anti-spam question is answered. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['question1'] = 'huh' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@565: self.assertEqual(response.status_code, 200) bgneal@565: self.assertContains(response, "Incorrect answer to our anti-spam question") bgneal@565: bgneal@565: def test_question2(self): bgneal@565: """ bgneal@565: Ensure our honeypot question check works. bgneal@565: bgneal@565: """ bgneal@782: self.post_vals['question2'] = 'non blank' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@782: self.assertEqual(response.status_code, 200) bgneal@565: bgneal@782: def test_question3(self): bgneal@782: """ bgneal@782: Ensure our non-hidden honeypot question check works. bgneal@782: bgneal@782: """ bgneal@782: self.post_vals['question3'] = 'non blank' bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@782: self.assertEqual(response.status_code, 200) bgneal@782: bgneal@565: def test_success(self): bgneal@565: """ bgneal@565: Ensure we can successfully register. bgneal@565: bgneal@565: """ bgneal@782: response = self.client.post(reverse('accounts-register'), bgneal@782: self.post_vals) bgneal@905: self.assertRedirects(response, reverse('accounts-register1')) bgneal@905: bgneal@905: # No pending user should exist yet bgneal@905: try: bgneal@905: pending = PendingUser.objects.get(username='a_new_user') bgneal@905: except PendingUser.DoesNotExist: bgneal@905: pass bgneal@905: else: bgneal@905: self.fail("PendingUser was created early") bgneal@905: bgneal@905: # Should have created a reg_info dict in the session bgneal@905: reg_info = self.client.session.get('reg_info') bgneal@905: self.assertEqual(reg_info, { bgneal@905: 'username': self.post_vals['username'], bgneal@905: 'email': self.post_vals['email'], bgneal@905: 'password': self.post_vals['password1'], bgneal@905: 'code': reg_info['code'], bgneal@905: }) bgneal@905: code = reg_info['code'] bgneal@905: match = re.match(r'\w+-\d{3}', code) bgneal@905: self.assertIsNotNone(match) bgneal@905: bgneal@905: # Get the next page bgneal@905: response = self.client.get(reverse('accounts-register2')) bgneal@905: self.assertEqual(response.status_code, 200) bgneal@905: bgneal@905: # No pending user should exist yet bgneal@905: try: bgneal@905: pending = PendingUser.objects.get(username='a_new_user') bgneal@905: except PendingUser.DoesNotExist: bgneal@905: pass bgneal@905: else: bgneal@905: self.fail("PendingUser was created early") bgneal@905: bgneal@905: # Try bad code bgneal@905: response = self.client.post(reverse('accounts-register2'), bgneal@905: {'code': code + code }) bgneal@905: self.assertEqual(response.status_code, 200) bgneal@905: self.assertContains(response, "The registration code does not match") bgneal@905: bgneal@905: # No pending user should exist yet bgneal@905: try: bgneal@905: pending = PendingUser.objects.get(username='a_new_user') bgneal@905: except PendingUser.DoesNotExist: bgneal@905: pass bgneal@905: else: bgneal@905: self.fail("PendingUser was created early") bgneal@905: bgneal@905: # Try good code bgneal@905: response = self.client.post(reverse('accounts-register2'), bgneal@905: {'code': code }) bgneal@905: self.assertRedirects(response, reverse('accounts-register_thanks')) bgneal@905: self.assertIsNone(self.client.session.get('reg_info')) bgneal@565: bgneal@565: try: bgneal@565: pending = PendingUser.objects.get(username='a_new_user') bgneal@565: except PendingUser.DoesNotExist: bgneal@565: self.fail("PendingUser was not created") bgneal@565: bgneal@565: self.assertEqual(pending.email, 'test@example.com') bgneal@565: self.assertTrue(datetime.datetime.now() - pending.date_joined < bgneal@565: datetime.timedelta(minutes=1)) bgneal@565: self.assertTrue(check_password('my_password', pending.password)) bgneal@659: bgneal@905: self.assertEqual(len(mail.outbox), 1) bgneal@905: msg = mail.outbox[0] bgneal@905: self.assertTrue(msg.subject.startswith('Registration Confirmation')) bgneal@905: self.assertTrue(len(msg.to) == 1 and msg.to[0] == pending.email) bgneal@905: msg_text = msg.message().as_string() bgneal@905: bgneal@905: activation_link = 'http://example.com%s' % ( bgneal@905: reverse('accounts-register_confirm', bgneal@905: kwargs={'username': pending.username, bgneal@905: 'key': pending.key})) bgneal@905: self.assertTrue(activation_link in msg_text) bgneal@905: bgneal@905: # Vist confirm link bgneal@905: response = self.client.get(reverse('accounts-register_confirm', bgneal@905: kwargs={'username': pending.username, bgneal@905: 'key': pending.key})) bgneal@905: self.assertEqual(response.status_code, 200) bgneal@905: bgneal@905: try: bgneal@905: pending = PendingUser.objects.get(username='a_new_user') bgneal@905: except PendingUser.DoesNotExist: bgneal@905: pass bgneal@905: else: bgneal@905: self.fail("PendingUser was not deleted upon confirmation") bgneal@905: bgneal@905: user = User.objects.get(username=pending.username) bgneal@905: self.assertEqual(user.email, pending.email) bgneal@905: now = datetime.datetime.now() bgneal@905: delta = datetime.timedelta(seconds=10) bgneal@905: self.assertTrue(now - user.last_login < delta) bgneal@905: self.assertTrue(now - user.date_joined < delta) bgneal@905: self.assertEqual(user.password, pending.password) bgneal@905: self.assertEqual(user.first_name, '') bgneal@905: self.assertEqual(user.last_name, '') bgneal@905: self.assertFalse(user.is_staff) bgneal@905: self.assertTrue(user.is_active) bgneal@905: self.assertFalse(user.is_superuser) bgneal@905: bgneal@659: bgneal@659: class ForgotUsernameTest(TestCase): bgneal@659: bgneal@659: def setUp(self): bgneal@659: u = User.objects.create_user('existing_user', 'existing_user@example.com', 'pw') bgneal@659: u.save() bgneal@659: bgneal@659: def test_get_query_view(self): bgneal@659: """Test a simple get of the username query view""" bgneal@659: response = self.client.get(reverse('accounts-username_query')) bgneal@659: self.assertEqual(response.status_code, 200) bgneal@659: bgneal@659: def test_get_username_sent_view(self): bgneal@659: """Test a simple get of the username sent view""" bgneal@659: response = self.client.get(reverse('accounts-username_sent')) bgneal@659: self.assertEqual(response.status_code, 200) bgneal@659: bgneal@659: def test_invalid_email(self): bgneal@659: """Test form submittal of unknown email address.""" bgneal@659: response = self.client.post(reverse('accounts-username_query'), { bgneal@659: 'email': 'bad_address@example.com', bgneal@659: }, bgneal@659: follow=True) bgneal@659: bgneal@659: self.assertRedirects(response, reverse('accounts-username_sent')) bgneal@659: bgneal@659: self.assertEqual(len(mail.outbox), 0) bgneal@659: bgneal@659: def test_valid_email(self): bgneal@659: """Test form submittal of valid email address.""" bgneal@659: response = self.client.post(reverse('accounts-username_query'), { bgneal@659: 'email': 'existing_user@example.com', bgneal@659: }, bgneal@659: follow=True) bgneal@659: bgneal@659: self.assertRedirects(response, reverse('accounts-username_sent')) bgneal@659: bgneal@659: self.assertEqual(len(mail.outbox), 1) bgneal@659: if len(mail.outbox): bgneal@659: self.assertTrue(mail.outbox[0].subject.startswith('Forgotten username')) bgneal@762: bgneal@762: bgneal@762: class ForgotEmailTest(TestCase): bgneal@762: """Because we use a custom URL its important to test this. This got broken bgneal@762: in Django 1.6 when the URL pattern changed. bgneal@762: bgneal@762: """ bgneal@762: bgneal@762: def setUp(self): bgneal@762: u = User.objects.create_user('user1', 'user1@example.com', 'pw') bgneal@762: u.save() bgneal@762: bgneal@762: def test_nominal_case(self): bgneal@762: """Test a full forgot password scenario.""" bgneal@762: bgneal@762: # GET password reset page bgneal@762: response = self.client.get(reverse('accounts-password_reset')) bgneal@762: self.assertEqual(response.status_code, 200) bgneal@762: bgneal@762: # POST email address bgneal@762: args = {'email': 'user1@example.com'} bgneal@762: response = self.client.post(reverse('accounts-password_reset'), args, bgneal@762: follow=True) bgneal@762: self.assertRedirects(response, reverse('accounts-password_reset_sent')) bgneal@762: bgneal@762: # Ensure the email was sent bgneal@762: self.assertEqual(len(mail.outbox), 1) bgneal@762: if (len(mail.outbox)): bgneal@762: msg = mail.outbox[0] bgneal@762: self.assertTrue(msg.subject.startswith('Password reset')) bgneal@762: self.assertTrue(len(msg.to) == 1 and msg.to[0] == 'user1@example.com') bgneal@762: msg_text = msg.message().as_string() bgneal@762: m = re.search(r'http://example.com/accounts/password/reset/confirm/' bgneal@762: r'(?P[0-9A-Za-z_\-]+)/(?P[0-9a-z]+-\w+)/', bgneal@762: msg_text) bgneal@762: self.assertTrue(m is not None) bgneal@762: if m: bgneal@762: uidb64, token = m.group('uidb64'), m.group('token') bgneal@762: bgneal@762: # visit the password reset page bgneal@762: response = self.client.get( bgneal@762: reverse('accounts-password_reset_confirm', bgneal@762: kwargs={'uidb64': uidb64, 'token': token})) bgneal@762: self.assertEqual(response.status_code, 200) bgneal@762: bgneal@762: # POST new password bgneal@762: args = {'new_password1': 'pw2', 'new_password2': 'pw2'} bgneal@762: response = self.client.post( bgneal@762: reverse('accounts-password_reset_confirm', bgneal@762: kwargs={'uidb64': uidb64, 'token': token}), bgneal@762: args, follow=True) bgneal@762: self.assertRedirects(response, bgneal@762: reverse('accounts-password_reset_success')) bgneal@762: self.assertEqual(response.status_code, 200) bgneal@762: bgneal@762: # Check new password bgneal@762: u = User.objects.get(username='user1') bgneal@762: self.assertTrue(check_password('pw2', u.password))