class PatchNotificationEmailTest(TestCase): def setUp(self): self.project = defaults.project self.project.send_notifications = True self.project.save() self.submitter = defaults.patch_author_person self.submitter.save() self.patch = Patch(project = self.project, msgid = 'testpatch', name = 'testpatch', content = '', submitter = self.submitter) self.patch.save() def tearDown(self): self.patch.delete() self.submitter.delete() self.project.delete() def _expireNotifications(self, **kwargs): timestamp = datetime.datetime.now() - \ datetime.timedelta(minutes = settings.NOTIFICATION_DELAY_MINUTES + 1) qs = PatchChangeNotification.objects.all() if kwargs: qs = qs.filter(**kwargs) qs.update(last_modified = timestamp) def testNoNotifications(self): self.assertEquals(send_notifications(), []) def testNoReadyNotifications(self): """ We shouldn't see immediate notifications""" PatchChangeNotification(patch = self.patch, orig_state = self.patch.state).save() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) def testNotifications(self): PatchChangeNotification(patch = self.patch, orig_state = self.patch.state).save() self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertEquals(msg.to, [self.submitter.email]) self.assertTrue(self.patch.get_absolute_url() in msg.body) def testNotificationEscaping(self): self.patch.name = 'Patch name with " character' self.patch.save() PatchChangeNotification(patch = self.patch, orig_state = self.patch.state).save() self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertEquals(msg.to, [self.submitter.email]) self.assertFalse('"' in msg.body) def testNotificationOptout(self): """ensure opt-out addresses don't get notifications""" PatchChangeNotification(patch = self.patch, orig_state = self.patch.state).save() self._expireNotifications() EmailOptout(email = self.submitter.email).save() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) def testNotificationMerge(self): patches = [self.patch, Patch(project = self.project, msgid = 'testpatch-2', name = 'testpatch 2', content = '', submitter = self.submitter)] for patch in patches: patch.save() PatchChangeNotification(patch = patch, orig_state = patch.state).save() self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertTrue(patches[0].get_absolute_url() in msg.body) self.assertTrue(patches[1].get_absolute_url() in msg.body) def testUnexpiredNotificationMerge(self): """Test that when there are multiple pending notifications, with at least one within the notification delay, that other notifications are held""" patches = [self.patch, Patch(project = self.project, msgid = 'testpatch-2', name = 'testpatch 2', content = '', submitter = self.submitter)] for patch in patches: patch.save() PatchChangeNotification(patch = patch, orig_state = patch.state).save() self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) self._expireNotifications() # update one notification, to bring it out of the notification delay patches[0].state = State.objects.exclude(pk = patches[0].state.pk)[0] patches[0].save() # the updated notification should prevent the other from being sent errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) # expire the updated notification self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertTrue(patches[0].get_absolute_url() in msg.body) self.assertTrue(patches[1].get_absolute_url() in msg.body)
class PatchNotificationEmailTest(TestCase): fixtures = ['default_states', 'default_events'] def setUp(self): self.project = defaults.project self.project.send_notifications = True self.project.save() self.submitter = defaults.patch_author_person self.submitter.save() self.patch = Patch(project=self.project, msgid='testpatch', name='testpatch', content='', submitter=self.submitter) self.patch.save() def tearDown(self): self.patch.delete() self.submitter.delete() self.project.delete() def _expireNotifications(self, **kwargs): timestamp = datetime.datetime.now() - \ datetime.timedelta(minutes = settings.NOTIFICATION_DELAY_MINUTES + 1) qs = PatchChangeNotification.objects.all() if kwargs: qs = qs.filter(**kwargs) qs.update(last_modified=timestamp) def testNoNotifications(self): self.assertEquals(send_notifications(), []) def testNoReadyNotifications(self): """ We shouldn't see immediate notifications""" PatchChangeNotification(patch=self.patch, orig_state=self.patch.state).save() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) def testNotifications(self): PatchChangeNotification(patch=self.patch, orig_state=self.patch.state).save() self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertEquals(msg.to, [self.submitter.email]) self.assertTrue(self.patch.get_absolute_url() in msg.body) def testNotificationEscaping(self): self.patch.name = 'Patch name with " character' self.patch.save() PatchChangeNotification(patch=self.patch, orig_state=self.patch.state).save() self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertEquals(msg.to, [self.submitter.email]) self.assertFalse('"' in msg.body) def testNotificationOptout(self): """ensure opt-out addresses don't get notifications""" PatchChangeNotification(patch=self.patch, orig_state=self.patch.state).save() self._expireNotifications() EmailOptout(email=self.submitter.email).save() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) def testNotificationMerge(self): patches = [ self.patch, Patch(project=self.project, msgid='testpatch-2', name='testpatch 2', content='', submitter=self.submitter) ] for patch in patches: patch.save() PatchChangeNotification(patch=patch, orig_state=patch.state).save() self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertTrue(patches[0].get_absolute_url() in msg.body) self.assertTrue(patches[1].get_absolute_url() in msg.body) def testUnexpiredNotificationMerge(self): """Test that when there are multiple pending notifications, with at least one within the notification delay, that other notifications are held""" patches = [ self.patch, Patch(project=self.project, msgid='testpatch-2', name='testpatch 2', content='', submitter=self.submitter) ] for patch in patches: patch.save() PatchChangeNotification(patch=patch, orig_state=patch.state).save() self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) self._expireNotifications() # update one notification, to bring it out of the notification delay patches[0].state = State.objects.exclude(pk=patches[0].state.pk)[0] patches[0].save() # the updated notification should prevent the other from being sent errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) # expire the updated notification self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertTrue(patches[0].get_absolute_url() in msg.body) self.assertTrue(patches[1].get_absolute_url() in msg.body)