# HG changeset patch # User Brian Neal # Date 1410126785 18000 # Node ID 42436d674ba87a13fbf45cf1ae9b2dbc2669da2e # Parent 56b30c79f10e36076364c2dac9f141f3d4cde9a6 Private message refactor: add unit tests for message cycle. diff -r 56b30c79f10e -r 42436d674ba8 messages/fixtures/messages_test_users.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messages/fixtures/messages_test_users.json Sun Sep 07 16:53:05 2014 -0500 @@ -0,0 +1,56 @@ +[ +{ + "pk": 1, + "model": "auth.user", + "fields": { + "username": "pj", + "first_name": "", + "last_name": "", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2014-09-06T15:15:04", + "groups": [], + "user_permissions": [], + "password": "", + "email": "pj@example.com", + "date_joined": "2006-02-25T00:00:00" + } +}, +{ + "pk": 2, + "model": "auth.user", + "fields": { + "username": "eddie", + "first_name": "", + "last_name": "", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2014-09-01T16:33:54", + "groups": [], + "user_permissions": [], + "password": "", + "email": "eddie@example.com", + "date_joined": "2006-02-28T00:00:00" + } +}, +{ + "pk": 3, + "model": "auth.user", + "fields": { + "username": "richard", + "first_name": "", + "last_name": "", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2014-09-06T15:15:04", + "groups": [], + "user_permissions": [], + "password": "", + "email": "richard@example.com", + "date_joined": "2006-02-25T00:00:00" + } +} +] diff -r 56b30c79f10e -r 42436d674ba8 messages/tests/test_views.py --- a/messages/tests/test_views.py Sun Sep 07 13:12:19 2014 -0500 +++ b/messages/tests/test_views.py Sun Sep 07 16:53:05 2014 -0500 @@ -2,23 +2,24 @@ Unit tests for the messages application views. """ +import datetime + from django.test import TestCase from django.core.urlresolvers import reverse +from django.contrib.auth.models import User from messages.models import Message, Options, Flag - -VIEW_NAMES = [ - 'messages-inbox', - 'messages-compose', - 'messages-outbox', - 'messages-trash', - 'messages-options', - 'messages-delete', - 'messages-undelete', - 'messages-view', - 'messages-report', -] +# TODO TODO TODO TODO +# TODO TODO TODO TODO +# TODO TODO TODO TODO +# +# 1) Test report functionality; ensure email sent to admin +# 2) Test email sent when PM sent if options allow it +# +# TODO TODO TODO TODO +# TODO TODO TODO TODO +# TODO TODO TODO TODO class NotLoggedInTestCase(TestCase): @@ -72,3 +73,409 @@ url_name = 'messages-report' self._test_get(url_name, args=[123]) self._test_post(url_name, args=[123]) + + +class BasicTestCase(TestCase): + """Testing a logged in user visiting all the views with no messages.""" + fixtures = ['messages_test_users.json'] + + def setUp(self): + self.users = {} + self.users['pj'] = User.objects.get(username='pj') + self.users['pj'].set_password('12345') + self.users['pj'].save() + self.assertTrue(self.client.login(username='pj', password='12345')) + + self.users['eddie'] = User.objects.get(username='eddie') + self.users['eddie'].set_password('12345') + self.users['eddie'].save() + + self.users['richard'] = User.objects.get(username='richard') + + def test_simple_gets(self): + view_names = [ + 'messages-inbox', + 'messages-compose', + 'messages-outbox', + 'messages-trash', + 'messages-options', + ] + for view_name in view_names: + response = self.client.get(reverse(view_name)) + self.assertEqual(response.status_code, 200) + + def test_wrong_method(self): + view_names = [ + 'messages-delete', + 'messages-undelete', + ] + for view_name in view_names: + response = self.client.get(reverse(view_name)) + self.assertEqual(response.status_code, 405) + + def test_nonexistent_pms(self): + view_names = [ + 'messages-view', + 'messages-report', + ] + for view_name in view_names: + response = self.client.get(reverse(view_name, args=[42])) + self.assertEqual(response.status_code, 404) + + response = self.client.post(reverse(view_name, args=[42])) + self.assertEqual(response.status_code, 404) + + def test_options(self): + view_name = 'messages-options' + url = reverse(view_name) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + post_data = { + 'opts-attach_signature': 'on', + 'opts-notify_email': 'on', + } + response = self.client.post(url, data=post_data, follow=True) + self.assertRedirects(response, url) + + opts = Options.objects.for_user(self.users['pj']) + self.assertTrue(opts.attach_signature) + self.assertTrue(opts.notify_email) + + post_data = {} + response = self.client.post(url, data=post_data, follow=True) + self.assertRedirects(response, url) + + opts = Options.objects.for_user(self.users['pj']) + self.assertFalse(opts.attach_signature) + self.assertFalse(opts.notify_email) + + def test_send_bogus_user(self): + post_data = { + 'receiver': 'unknown_user', + 'subject': 'hi', + 'message': 'test', + } + view_name = 'messages-compose' + url = reverse(view_name) + response = self.client.post(url, data=post_data) + self.assertContains(response, 'username does not exist', status_code=200) + + qs = Message.objects.filter(sender=self.users['pj']) + self.assertEqual(qs.count(), 0) + + def test_send_to_self(self): + post_data = { + 'receiver': 'pj', + 'subject': 'hi', + 'message': 'test', + } + view_name = 'messages-compose' + url = reverse(view_name) + response = self.client.post(url, data=post_data) + self.assertContains(response, "You can't send a message to yourself", status_code=200) + + qs = Message.objects.filter(sender=self.users['pj']) + self.assertEqual(qs.count(), 0) + + def test_message_cycle(self): + # pj sends message to eddie + now = datetime.datetime.now() + post_data = { + 'receiver': 'eddie', + 'subject': 'Mr. Moto Demo', + 'message': 'Gig at Newport High School', + } + view_name = 'messages-compose' + url = reverse(view_name) + response = self.client.post(url, data=post_data) + self.assertContains(response, "Message sent", status_code=200) + + # see if message got created in database + msg = Message.objects.get(sender=self.users['pj']) + + self.assertEqual(msg.sender, self.users['pj']) + self.assertEqual(msg.receiver, self.users['eddie']) + self.assertTrue(now - msg.send_date < datetime.timedelta(seconds=5)) + self.assertIsNone(msg.read_date) + self.assertIsNone(msg.reply_date) + self.assertEqual(msg.subject, post_data['subject']) + self.assertEqual(msg.message, post_data['message']) + self.assertIsNone(msg.sender_delete_date) + self.assertIsNone(msg.receiver_delete_date) + + # see if shows up in outbox view + view_name = 'messages-outbox' + url = reverse(view_name) + response = self.client.get(url) + self.assertContains(response, post_data['subject'], status_code=200) + + # see if we can view it + view_name = 'messages-view' + url = reverse(view_name, args=[msg.pk]) + response = self.client.get(url) + self.assertContains(response, post_data['subject'], status_code=200) + self.assertContains(response, post_data['message'], status_code=200) + + # eddie logs in and checks various views + self.assertTrue(self.client.login(username='eddie', password='12345')) + view_name = 'messages-inbox' + url = reverse(view_name) + response = self.client.get(url) + self.assertContains(response, post_data['subject'], status_code=200) + view_name = 'messages-outbox' + url = reverse(view_name) + response = self.client.get(url) + self.assertNotContains(response, post_data['subject'], status_code=200) + view_name = 'messages-trash' + url = reverse(view_name) + response = self.client.get(url) + self.assertNotContains(response, post_data['subject'], status_code=200) + + # eddie reads it + view_name = 'messages-view' + url = reverse(view_name, args=[msg.pk]) + response = self.client.get(url) + self.assertContains(response, post_data['subject'], status_code=200) + self.assertContains(response, post_data['message'], status_code=200) + + # see if message got updated in database + msg = Message.objects.get(receiver=self.users['eddie']) + + self.assertEqual(msg.sender, self.users['pj']) + self.assertEqual(msg.receiver, self.users['eddie']) + self.assertTrue(now - msg.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg.read_date < datetime.timedelta(seconds=5)) + self.assertIsNone(msg.reply_date) + self.assertEqual(msg.subject, post_data['subject']) + self.assertEqual(msg.message, post_data['message']) + self.assertIsNone(msg.sender_delete_date) + self.assertIsNone(msg.receiver_delete_date) + + # eddie replies + post_data2 = { + 'receiver': 'pj', + 'subject': 'Re: Mr. Moto Demo', + 'message': 'South Bay Sound', + 'parent_id': msg.pk, + } + view_name = 'messages-compose' + url = reverse(view_name) + response = self.client.post(url, data=post_data2) + self.assertContains(response, "Message sent", status_code=200) + + self.assertEqual(Message.objects.all().count(), 2) + + msg1 = Message.objects.get(receiver=self.users['eddie']) + + self.assertEqual(msg1.sender, self.users['pj']) + self.assertEqual(msg1.receiver, self.users['eddie']) + self.assertTrue(now - msg1.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg1.read_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg1.reply_date < datetime.timedelta(seconds=5)) + self.assertEqual(msg1.subject, post_data['subject']) + self.assertEqual(msg1.message, post_data['message']) + self.assertIsNone(msg1.sender_delete_date) + self.assertIsNone(msg1.receiver_delete_date) + + msg2 = Message.objects.get(receiver=self.users['pj']) + + self.assertEqual(msg2.sender, self.users['eddie']) + self.assertEqual(msg2.receiver, self.users['pj']) + self.assertTrue(now - msg2.send_date < datetime.timedelta(seconds=5)) + self.assertIsNone(msg2.read_date) + self.assertIsNone(msg2.reply_date) + self.assertEqual(msg2.subject, post_data2['subject']) + self.assertEqual(msg2.message, post_data2['message']) + self.assertIsNone(msg2.sender_delete_date) + self.assertIsNone(msg2.receiver_delete_date) + + # pj logs in and checks various views + self.assertTrue(self.client.login(username='pj', password='12345')) + view_name = 'messages-inbox' + url = reverse(view_name) + response = self.client.get(url) + self.assertContains(response, post_data2['subject'], status_code=200) + view_name = 'messages-outbox' + url = reverse(view_name) + response = self.client.get(url) + self.assertContains(response, post_data['subject'], status_code=200) + view_name = 'messages-trash' + url = reverse(view_name) + response = self.client.get(url) + self.assertNotContains(response, post_data['subject'], status_code=200) + self.assertNotContains(response, post_data2['subject'], status_code=200) + + # pj reads reply + view_name = 'messages-view' + url = reverse(view_name, args=[msg2.pk]) + response = self.client.get(url) + self.assertContains(response, post_data2['subject'], status_code=200) + self.assertContains(response, post_data2['message'], status_code=200) + + msg = Message.objects.get(receiver=self.users['eddie']) + + self.assertEqual(msg.sender, self.users['pj']) + self.assertEqual(msg.receiver, self.users['eddie']) + self.assertTrue(now - msg.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg.read_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg.reply_date < datetime.timedelta(seconds=5)) + self.assertEqual(msg.subject, post_data['subject']) + self.assertEqual(msg.message, post_data['message']) + self.assertIsNone(msg.sender_delete_date) + self.assertIsNone(msg.receiver_delete_date) + + msg2 = Message.objects.get(receiver=self.users['pj']) + + self.assertEqual(msg2.sender, self.users['eddie']) + self.assertEqual(msg2.receiver, self.users['pj']) + self.assertTrue(now - msg2.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg2.read_date < datetime.timedelta(seconds=5)) + self.assertIsNone(msg2.reply_date) + self.assertEqual(msg2.subject, post_data2['subject']) + self.assertEqual(msg2.message, post_data2['message']) + self.assertIsNone(msg2.sender_delete_date) + self.assertIsNone(msg2.receiver_delete_date) + + # pj deletes message 2 + self.assertEqual(Message.objects.all().count(), 2) + + delete_post_data = { + 'pm_ids': [msg2.pk], + } + view_name = 'messages-delete' + url = reverse(view_name) + response = self.client.post(url, data=delete_post_data, follow=True) + self.assertContains(response, "1 message deleted", status_code=200) + + self.assertEqual(Message.objects.all().count(), 2) + + msg2 = Message.objects.get(receiver=self.users['pj']) + + self.assertEqual(msg2.sender, self.users['eddie']) + self.assertEqual(msg2.receiver, self.users['pj']) + self.assertTrue(now - msg2.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg2.read_date < datetime.timedelta(seconds=5)) + self.assertIsNone(msg2.reply_date) + self.assertEqual(msg2.subject, post_data2['subject']) + self.assertEqual(msg2.message, post_data2['message']) + self.assertIsNone(msg2.sender_delete_date) + self.assertTrue(now - msg2.receiver_delete_date < datetime.timedelta(seconds=5)) + + # should be in pj's trash now + view_name = 'messages-trash' + url = reverse(view_name) + response = self.client.get(url) + self.assertContains(response, post_data2['subject'], status_code=200) + + # eddie logs in and deletes his copy of message 2 + self.assertTrue(self.client.login(username='eddie', password='12345')) + delete_post_data = { + 'pm_ids': [msg2.pk], + } + view_name = 'messages-delete' + url = reverse(view_name) + response = self.client.post(url, data=delete_post_data, follow=True) + self.assertContains(response, "1 message deleted", status_code=200) + + # should be really deleted now + self.assertEqual(Message.objects.all().count(), 1) + view_name = 'messages-trash' + url = reverse(view_name) + response = self.client.get(url) + self.assertNotContains(response, post_data2['subject'], status_code=200) + + # eddie deletes then undeletes message 1 + delete_post_data = { + 'pm_ids': [msg1.pk], + } + view_name = 'messages-delete' + url = reverse(view_name) + response = self.client.post(url, data=delete_post_data, follow=True) + self.assertContains(response, "1 message deleted", status_code=200) + + # should not be really deleted now + self.assertEqual(Message.objects.all().count(), 1) + view_name = 'messages-trash' + url = reverse(view_name) + response = self.client.get(url) + self.assertContains(response, post_data['subject'], status_code=200) + + msg1 = Message.objects.get(receiver=self.users['eddie']) + + self.assertEqual(msg1.sender, self.users['pj']) + self.assertEqual(msg1.receiver, self.users['eddie']) + self.assertTrue(now - msg1.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg1.read_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg1.reply_date < datetime.timedelta(seconds=5)) + self.assertEqual(msg1.subject, post_data['subject']) + self.assertEqual(msg1.message, post_data['message']) + self.assertIsNone(msg1.sender_delete_date) + self.assertTrue(now - msg1.receiver_delete_date < datetime.timedelta(seconds=5)) + + delete_post_data = { + 'pm_ids': [msg1.pk], + } + view_name = 'messages-undelete' + url = reverse(view_name) + response = self.client.post(url, data=delete_post_data, follow=True) + self.assertContains(response, "1 message undeleted", status_code=200) + + # should not be really deleted now + self.assertEqual(Message.objects.all().count(), 1) + view_name = 'messages-trash' + url = reverse(view_name) + response = self.client.get(url) + self.assertNotContains(response, post_data['subject'], status_code=200) + + msg1 = Message.objects.get(receiver=self.users['eddie']) + + self.assertEqual(msg1.sender, self.users['pj']) + self.assertEqual(msg1.receiver, self.users['eddie']) + self.assertTrue(now - msg1.send_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg1.read_date < datetime.timedelta(seconds=5)) + self.assertTrue(now - msg1.reply_date < datetime.timedelta(seconds=5)) + self.assertEqual(msg1.subject, post_data['subject']) + self.assertEqual(msg1.message, post_data['message']) + self.assertIsNone(msg1.sender_delete_date) + self.assertIsNone(msg1.receiver_delete_date) + + def test_read_permission(self): + + now = datetime.datetime.now() + # pj sends a PM to richard + post_data = { + 'receiver': 'richard', + 'subject': 'Mr. Moto Demo', + 'message': 'Gig at Newport High School', + } + view_name = 'messages-compose' + url = reverse(view_name) + response = self.client.post(url, data=post_data) + self.assertContains(response, "Message sent", status_code=200) + + msg = Message.objects.get(sender=self.users['pj']) + + # eddie should not be able to read it + self.assertTrue(self.client.login(username='eddie', password='12345')) + view_name = 'messages-view' + url = reverse(view_name, args=[msg.pk]) + response = self.client.get(url) + self.assertNotContains(response, post_data['subject'], status_code=302) + self.assertNotContains(response, post_data['message'], status_code=302) + + response = self.client.get(url, follow=True) + self.assertNotContains(response, post_data['subject'], status_code=200) + self.assertNotContains(response, post_data['message'], status_code=200) + + msg = Message.objects.get(sender=self.users['pj']) + + self.assertEqual(msg.sender, self.users['pj']) + self.assertEqual(msg.receiver, self.users['richard']) + self.assertTrue(now - msg.send_date < datetime.timedelta(seconds=5)) + self.assertIsNone(msg.read_date) + self.assertIsNone(msg.reply_date) + self.assertEqual(msg.subject, post_data['subject']) + self.assertEqual(msg.message, post_data['message']) + self.assertIsNone(msg.sender_delete_date) + self.assertIsNone(msg.receiver_delete_date) diff -r 56b30c79f10e -r 42436d674ba8 messages/views.py --- a/messages/views.py Sun Sep 07 13:12:19 2014 -0500 +++ b/messages/views.py Sun Sep 07 16:53:05 2014 -0500 @@ -110,6 +110,7 @@ if form.is_valid(): form.save() django_messages.success(request, 'Options saved.') + return redirect('messages-options') else: options = Options.objects.for_user(request.user) form = OptionsForm(instance=options, prefix='opts') @@ -155,6 +156,8 @@ the user is a recipient of the message, a reply can be composed and sent. """ + msg = get_object_or_404(Message.objects.select_related(), pk=msg_id) + if request.method == 'POST': form = ComposeForm(request.user, request.POST) if form.is_valid(): @@ -162,7 +165,6 @@ django_messages.success(request, 'Reply sent.') return redirect('messages-inbox') else: - msg = get_object_or_404(Message.objects.select_related(), pk=msg_id) if msg.sender != request.user and msg.receiver != request.user: django_messages.error(request, "You don't have permission to read that message.")