def test_delete_activated_workflow(self, mock_mail): with freeze_time("2015-02-01 13:39:20"): _, workflow = self.wf_generator.generate_workflow(self.quarterly_wf_1) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) user = Person.query.get(self.user.id) with freeze_time("2015-01-01 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data) with freeze_time("2015-01-29 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_starts_in", notif_data[user.email]) workflow = Workflow.query.get(workflow.id) response = self.wf_generator.api.delete(workflow) self.assert200(response) _, notif_data = common.get_daily_notifications() user = Person.query.get(self.user.id) self.assertNotIn(user.email, notif_data)
def test_start_failed(self, mock_mail): wf_admin = "*****@*****.**" with freeze_time("2015-02-01 13:39:20"): _, wf = self.wf_generator.generate_workflow(self.quarterly_wf) response, wf = self.wf_generator.activate_workflow(wf) print wf.next_cycle_start_date self.assert200(response) with freeze_time("2015-01-01 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertNotIn(wf_admin, notif_data) with freeze_time("2015-01-29 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(wf_admin, notif_data) self.assertIn("cycle_starts_in", notif_data[wf_admin]) with freeze_time("2015-03-05 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(wf_admin, notif_data) self.assertNotIn("cycle_started", notif_data[wf_admin]) self.assertIn(wf_admin, notif_data) self.assertIn("cycle_start_failed", notif_data[wf_admin]) common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertNotIn(wf_admin, notif_data)
def test_one_time_wf(self): # setup with freeze_time("2015-04-07 03:21:34"): wf_response, wf = self.wf_generator.generate_workflow(data={ # admin will be the current user "notify_on_change": True, # force real time updates "title": "One-time WF", "notify_custom_message": textwrap.dedent("""\ Hi all. Did you know that Irelnd city namd Newtownmountkennedy has 19 letters? But it's not the longest one. The recordsman is the city in New Zealand that contains 97 letter."""), }) _, tg = self.wf_generator.generate_task_group(wf, data={ "title": "TG #1 for the One-time WF", "contact": self.short_dict(self.tgassignee1, "people"), }) self.wf_generator.generate_task_group_task(tg, { "title": "task #1 for one-time workflow", "contact": self.short_dict(self.member1, "people"), "start_date": "04/07/2015", "end_date": "04/15/2015", }) self.wf_generator.generate_task_group_object(tg, self.random_objects[0]) self.wf_generator.generate_task_group_object(tg, self.random_objects[1]) # test with freeze_time("2015-04-07 03:21:34"): cycle_response, cycle = self.wf_generator.generate_cycle(wf) self.wf_generator.activate_workflow(wf) common.get_daily_notifications()
def test_force_one_wf_notifications(self, mock_mail): with freeze_time("2015-02-01 13:39:20"): _, wf_forced = self.wf_generator.generate_workflow( self.quarterly_wf_forced) response, wf_forced = self.wf_generator.activate_workflow(wf_forced) _, wf = self.wf_generator.generate_workflow(self.quarterly_wf) response, wf = self.wf_generator.activate_workflow(wf) self.assert200(response) user = models.Person.query.get(self.user.id) with freeze_time("2015-01-29 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_starts_in", notif_data[user.email]) self.assertIn(wf_forced.id, notif_data[user.email]["cycle_starts_in"]) self.assertIn(wf.id, notif_data[user.email]["cycle_starts_in"]) self.object_generator.generate_notification_setting( self.user.id, "Email_Digest", False) user = models.Person.query.get(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_starts_in", notif_data[user.email]) self.assertIn(wf_forced.id, notif_data[user.email]["cycle_starts_in"]) self.assertNotIn(wf.id, notif_data[user.email]["cycle_starts_in"])
def test_one_time_wf_activate(self): def get_person(person_id): return db.session.query(Person).filter(Person.id == person_id).one() with freeze_time("2015-04-10"): _, wf = self.wf_generator.generate_workflow(self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(wf) self.wf_generator.activate_workflow(wf) person_2 = get_person(self.random_people[2].id) with freeze_time("2015-04-11"): _, notif_data = common.get_daily_notifications() self.assertIn(person_2.email, notif_data) self.assertIn("cycle_started", notif_data[person_2.email]) self.assertIn(cycle.id, notif_data[person_2.email]["cycle_started"]) self.assertIn("my_tasks", notif_data[person_2.email]["cycle_data"][cycle.id]) person_1 = get_person(self.random_people[0].id) with freeze_time("2015-05-03"): # two days befor due date _, notif_data = common.get_daily_notifications() self.assertIn(person_1.email, notif_data) self.assertNotIn("due_in", notif_data[person_1.email]) self.assertNotIn("due_today", notif_data[person_1.email]) with freeze_time("2015-05-04"): # one day befor due date _, notif_data = common.get_daily_notifications() self.assertEqual(len(notif_data[person_1.email]["due_in"]), 1) with freeze_time("2015-05-05"): # due date _, notif_data = common.get_daily_notifications() self.assertEqual(len(notif_data[person_1.email]["due_today"]), 1)
def test_multiply_mapping(self): """Test notification for multiply mapping""" controls = [factories.ControlFactory() for _ in xrange(5)] snapshots = self._create_snapshots(self.assessment.audit, controls) def get_relation_dict(destination_obj): return { "relationship": { "context": {"id": self.assessment.audit.context.id, "type": self.assessment.audit.context.type}, "source": {"id": self.assessment.id, "type": self.assessment.type}, "destination": {"id": destination_obj.id, "type": destination_obj.type} } } notifs, _ = common.get_daily_notifications() self.assertFalse(len(notifs)) self.assessment.status = "In Progress" post_data = [get_relation_dict(s) for s in snapshots] db.session.add(self.assessment) resp = self.api.send_request( self.api.client.post, obj=all_models.Relationship, data=post_data) self.assert200(resp) notifs, _ = common.get_daily_notifications() self.assertEqual(len(notifs), 1)
def test_sending_overdue_notifications_for_tasks(self, is_vf_needed, _): """Overdue notifications should be sent for overdue tasks every day. Even if an overdue notification has already been sent, it should still be sent in every following daily digest f a task is still overdue. """ with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1_id = tasks[0].id task2_id = tasks[1].id user = models.Person.query.get(self.user.id) with freeze_time("2017-05-14 08:09:10"): _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) with freeze_time("2017-05-15 08:09:10"): # task 1 due date _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) with freeze_time("2017-05-16 08:09:10"): # task 2 due date _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) overdue_task_ids = sorted(user_notifs["task_overdue"].keys()) self.assertEqual(overdue_task_ids, [task1_id]) with freeze_time("2017-05-17 08:09:10"): # after both tasks' due dates _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) overdue_task_ids = sorted(user_notifs["task_overdue"].keys()) self.assertEqual(overdue_task_ids, [task1_id, task2_id]) common.send_daily_digest_notifications() # even after sending the overdue notifications, they are sent again the # day after, too with freeze_time("2017-05-18 08:09:10"): _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) overdue_task_ids = sorted(user_notifs["task_overdue"].keys()) self.assertEqual(overdue_task_ids, [task1_id, task2_id])
def test_move_end_date_to_today(self, mock_mail): def get_person(person_id): return db.session.query(Person).filter(Person.id == person_id).one() with freeze_time("2015-04-10 03:21:34"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-05-02 03:21:34"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to owner and one to assigne self.assertEqual(mock_mail.call_count, 2) with freeze_time("2015-05-03 03:21:34"): cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) task2 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[1].id) self.wf_generator.modify_object( task1, data={"end_date": date(2015, 5, 3)}) self.wf_generator.modify_object( task2, data={"end_date": date(2015, 5, 4)}) with freeze_time("2015-05-03 03:21:34"): # one day befor due date user = get_person(self.user.id) _, notif_data = common.get_daily_notifications() self.assertNotEquals(notif_data, {}) self.assertIn(user.email, notif_data) self.assertIn("due_today", notif_data[user.email]) self.assertIn("due_in", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_today"]), 1) common.send_daily_digest_notifications() with freeze_time("2015-05-04 03:21:34"): # due date user = get_person(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("due_today", notif_data[user.email]) self.assertNotIn("due_in", notif_data[user.email]) common.send_daily_digest_notifications() with freeze_time("2015-05-05 03:21:34"): # due date _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {})
def test_adjust_overdue_notifications_on_task_status_change(self, is_vf_needed, _): """Sending overdue notifications should take task status into account.""" with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1, task2 = tasks self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)}) user = models.Person.query.get(self.user.id) user_email = user.email if is_vf_needed: non_final_states = [CycleTaskGroupObjectTask.ASSIGNED, CycleTaskGroupObjectTask.IN_PROGRESS, CycleTaskGroupObjectTask.FINISHED, CycleTaskGroupObjectTask.DECLINED] final_state = CycleTaskGroupObjectTask.VERIFIED else: non_final_states = [CycleTaskGroupObjectTask.ASSIGNED, CycleTaskGroupObjectTask.IN_PROGRESS] final_state = CycleTaskGroupObjectTask.FINISHED with freeze_time("2017-05-16 08:09:10"): # a day after task1 due date for state in non_final_states: # clear all notifications before before changing the task status models.Notification.query.delete() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) self.wf_generator.modify_object(task1, {"status": state}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) # WITHOUT clearing the overdue notifications, move the task to "verified" # state, and the overdue notification should disappear. self.wf_generator.modify_object(task1, {"status": final_state}) common.generate_cycle_tasks_notifs() _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertNotIn("task_overdue", user_notifs)
def test_assessment_inprogress_reminder_finish_afterwards(self): """Tests that notifications don't get sent if Finished already. Tests that notifications don't get sent out if assessment has been moved to `Finished` state since reminder was activated. """ # pylint: disable=invalid-name with freeze_time("2015-04-01 17:13:15"): assessment = self.create_assessment() assessment = self.change_status(assessment, models.Assessment.PROGRESS_STATE) self.send_reminder(assessment) notifications = self._get_notifications( False, "assessment_assignees_reminder", ).all() self.assertEqual(len(notifications), 1) notif = notifications[0] revisions = models.Revision.query.filter_by(resource_type='Notification', resource_id=notif.id).count() self.assertEqual(revisions, 1) self.change_status(assessment, models.Assessment.DONE_STATE) _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {})
def test_ca_change_by_import(self): """Test notification when custom attribute value is changed by import""" with factories.single_commit(): assessment = factories.AssessmentFactory(status="Completed") factories.CustomAttributeDefinitionFactory( definition_type="assessment", title="Test GCAD", ) assessment_slug = assessment.slug assessment_id = assessment.id user = all_models.Person.query.filter_by( email="*****@*****.**").first() assessment.add_person_with_role_name(user, "Assignees") from flask import g setattr(g, '_current_user', user) import_data = OrderedDict([ ("object_type", "Assessment"), ("Code*", assessment_slug), ("Test GCAD", "test value"), ]) response = self.import_data(import_data) self._check_csv_response(response, {}) notifs, _ = common.get_daily_notifications() self.assertEqual(len(notifs), 2) assessment = all_models.Assessment.query.get(assessment_id) cad = assessment.get_custom_attribute_definitions().filter_by( title="Test GCAD").first() self.assertEqual( [i.attribute_value for i in cad.attribute_values], ["test value"])
def test_default_notifications_settings(self, mock_mail): with freeze_time("2015-02-01 13:39:20"): _, wf = self.wf_generator.generate_workflow(self.quarterly_wf) response, wf = self.wf_generator.activate_workflow(wf) self.assert200(response) user = models.Person.query.get(self.user.id) with freeze_time("2015-01-01 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data) with freeze_time("2015-01-29 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data)
def test_one_time_wf_activate_single_person(self, mock_mail): with freeze_time("2015-04-10"): user = "******" _, wf = self.wf_generator.generate_workflow( self.one_time_workflow_single_person) _, cycle = self.wf_generator.generate_cycle(wf) self.wf_generator.activate_workflow(wf) with freeze_time("2015-04-11"): _, notif_data = common.get_daily_notifications() self.assertIn("cycle_started", notif_data[user]) self.assertIn(cycle.id, notif_data[user]["cycle_started"]) self.assertIn("my_tasks", notif_data[user]["cycle_data"][cycle.id]) self.assertIn("cycle_tasks", notif_data[user]["cycle_data"][cycle.id]) self.assertIn( "my_task_groups", notif_data[user]["cycle_data"][cycle.id]) self.assertIn("cycle_url", notif_data[user]["cycle_started"][cycle.id]) cycle = Cycle.query.get(cycle.id) cycle_data = notif_data[user]["cycle_data"][cycle.id] for task in cycle.cycle_task_group_object_tasks: self.assertIn(task.id, cycle_data["my_tasks"]) self.assertIn(task.id, cycle_data["cycle_tasks"]) self.assertIn("title", cycle_data["my_tasks"][task.id]) self.assertIn("title", cycle_data["cycle_tasks"][task.id]) self.assertIn("cycle_task_url", cycle_data["cycle_tasks"][task.id]) with freeze_time("2015-05-03"): # two days before due date _, notif_data = common.get_daily_notifications() self.assertIn(user, notif_data) self.assertNotIn("due_in", notif_data[user]) self.assertNotIn("due_today", notif_data[user]) with freeze_time("2015-05-04"): # one day before due date _, notif_data = common.get_daily_notifications() self.assertEqual(len(notif_data[user]["due_in"]), 2) with freeze_time("2015-05-05"): # due date _, notif_data = common.get_daily_notifications() self.assertEqual(len(notif_data[user]["due_today"]), 2) common.send_daily_digest_notifications() self.assertEqual(mock_mail.call_count, 1)
def test_enabled_notifications(self, mock_mail): with freeze_time("2015-02-01 13:39:20"): _, wf = self.wf_generator.generate_workflow(self.quarterly_wf) response, wf = self.wf_generator.activate_workflow(wf) self.assert200(response) with freeze_time("2015-01-29 13:39:20"): user = models.Person.query.get(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.object_generator.generate_notification_setting( self.user.id, "Email_Digest", True) user = models.Person.query.get(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data)
def test_common_attr_change(self): """Test notification when common attribute value is changed""" response = self.api.put(self.assessment, {"test_plan": "steps"}) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_fields"], ["ASSESSMENT PROCEDURE"])
def test_end_cycle(self, mock_mail): """Manually ending cycle should stop all notifications for that cycle.""" with freeze_time("2015-05-01"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-05-03"): _, notif_data = common.get_daily_notifications() cycle = Cycle.query.get(cycle.id) user = Person.query.get(self.user.id) self.assertIn(user.email, notif_data) self.wf_generator.modify_object(cycle, data={"is_current": False}) cycle = Cycle.query.get(cycle.id) self.assertFalse(cycle.is_current) _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data)
def test_delete_activated_workflow(self, mock_mail): with freeze_time("2015-02-01 13:39:20"): _, workflow = self.wf_generator.generate_workflow(self.quarterly_wf_1) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) user = Person.query.get(self.user.id) with freeze_time("2015-01-01 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data) with freeze_time("2015-01-29 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_starts_in", notif_data[user.email]) workflow = Workflow.query.get(workflow.id) # After workflow deletion its notifications object_ids updated to 0 # value, this is the error, them should be deleted # so this query checks existence of notifications with object_id # equal to workflow id or 0 id before and # after deletion workflow instance exists_qs = db.session.query( Notification.query.filter( Notification.object_type == workflow.__class__.__name__, Notification.object_id.in_((workflow.id, 0)) ).exists() ) self.assertTrue(exists_qs.one()[0]) response = self.wf_generator.api.delete(workflow) self.assert200(response) self.assertFalse(exists_qs.one()[0]) _, notif_data = common.get_daily_notifications() user = Person.query.get(self.user.id) self.assertNotIn(user.email, notif_data)
def test_manual_generate_cycle(self, mock_mail): with freeze_time("2015-04-01"): _, wf = self.wf_generator.generate_workflow(self.monthly_workflow_1) self.wf_generator.activate_workflow(wf) person_1 = Person.query.get(self.person_1.id) with freeze_time("2015-04-03"): _, notif_data = common.get_daily_notifications() with freeze_time("2015-04-03"): _, cycle = self.wf_generator.generate_cycle(wf) _, notif_data = common.get_daily_notifications() person_1 = Person.query.get(self.person_1.id) self.assertIn("cycle_started", notif_data[person_1.email]) with freeze_time("2015-05-03"): # two days befor due date _, notif_data = common.get_daily_notifications() person_1 = Person.query.get(self.person_1.id) self.assertIn(person_1.email, notif_data)
def test_cycle_starts_in_less_than_X_days(self): with freeze_time("2015-02-01"): _, wf = self.generator.generate_workflow(self.quarterly_wf_1) response, wf = self.generator.activate_workflow(wf) self.assert200(response) assignee = Person.query.get(self.assignee.id) with freeze_time("2015-01-01"): _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data) with freeze_time("2015-01-29"): _, notif_data = common.get_daily_notifications() self.assertIn(assignee.email, notif_data) with freeze_time("2015-02-01"): _, notif_data = common.get_daily_notifications() self.assertIn(assignee.email, notif_data)
def test_auto_generate_cycle(self, mock_mail): person_1_email = Person.query.get(self.person_1.id).email with freeze_time("2015-04-01"): _, wf = self.wf_generator.generate_workflow(self.monthly_workflow_1) self.wf_generator.activate_workflow(wf) _, notif_data = common.get_daily_notifications() self.assertNotIn(person_1_email, notif_data) with freeze_time("2015-04-02"): self.api.client.get("nightly_cron_endpoint") _, notif_data = common.get_daily_notifications() self.assertNotIn(person_1_email, notif_data) start_recurring_cycles() _, notif_data = common.get_daily_notifications() self.assertNotIn(person_1_email, notif_data) # cycle starts on monday - 6th, and not on 5th with freeze_time("2015-04-03"): start_recurring_cycles() _, notif_data = common.get_daily_notifications() self.assertIn(person_1_email, notif_data) self.assertIn("cycle_started", notif_data[person_1_email]) with freeze_time("2015-04-15"): # one day befor due date _, notif_data = common.get_daily_notifications() self.assertIn(person_1_email, notif_data) with freeze_time("2015-04-25"): # due date _, notif_data = common.get_daily_notifications() self.assertIn(person_1_email, notif_data)
def test_overdue_notifications_when_task_due_date_is_changed(self, _): """Overdue notifications should adjust to task due date changes.""" Workflow.query.delete() models.Notification.query.delete() db.session.commit() filename = join(self.CSV_DIR, "workflow_small_sheet.csv") response = self.import_file(filename) self._check_csv_response(response, expected_messages={}) workflow = Workflow.query.one() self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) user = models.Person.query.filter( models.Person.email == '*****@*****.**').one() with freeze_time("2015-01-01 00:00:00"): # before all tasks' due dates _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) # now modify task's due date and check if overdue notification appears task = CycleTaskGroupObjectTask.query.filter( CycleTaskGroupObjectTask.title == "task for wf-2").one() task_id, task_code = task.id, task.slug response = self.import_data(OrderedDict(( ("object_type", "CycleTask"), ("Code*", task_code), ("Start Date", "12/15/2014"), ("Due Date", "12/31/2014"), ))) self._check_csv_response(response, expected_messages={}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) self.assertIn(task_id, user_notifs["task_overdue"])
def test_single_task_declined(self, mock_mail): """ test moving the end date to the future, befor due_in and due_today notifications have been sent """ with freeze_time("2015-05-01"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-05-02"): common.send_daily_digest_notifications() cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) self.task_change_status(task1, "Finished") _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) with freeze_time("2015-05-02"): common.send_daily_digest_notifications() cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) self.task_change_status(task1, "Declined") user = Person.query.get(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("task_declined", notif_data[user.email])
def test_multiply_updates(self): """Test notification for multiply updates""" response = self.api.put(self.assessment, {"test_plan": "steps"}) self.assert200(response) response = self.api.put(self.assessment, {"title": "new title"}) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(sorted(updated[self.assessment.id]["updated_fields"]), ["ASSESSMENT PROCEDURE", "TITLE"])
def test_stop_sending_overdue_notification_if_task_gets_deleted(self, is_vf_needed, _): """Overdue notifications should not be sent for deleted tasks.""" with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1, task2 = tasks user = models.Person.query.get(self.user.id) user_email = user.email with freeze_time("2017-10-16 08:09:10"): # long after both task due dates _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 2) db.session.delete(task2) db.session.commit() _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) db.session.delete(task1) db.session.commit() _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs)
def test_adjust_overdue_notifications_on_task_due_date_change( self, is_vf_needed, _): """Sending overdue notifications should adjust to task due date changes.""" with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1, task2 = tasks self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)}) user = models.Person.query.get(self.user.id) with freeze_time("2017-05-16 08:09:10"): # a day after task1 due date _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) # change task1 due date, there should be no overdue notification anymore self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 16)}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) # change task1 due date to the past there should a notification again self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 14)}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1)
def test_stop_sending_overdue_notification_if_task_gets_deleted( self, is_vf_needed, _): """Overdue notifications should not be sent for deleted tasks.""" with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1, task2 = tasks user = models.Person.query.get(self.user.id) user_email = user.email with freeze_time( "2017-10-16 08:09:10"): # long after both task due dates _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 2) db.session.delete(task2) db.session.commit() _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) db.session.delete(task1) db.session.commit() _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs)
def test_marking_sent_notifications(self, mail_mock): mail_mock.return_value = True with freeze_time("2015-02-01"): _, wf = self.generator.generate_workflow(self.quarterly_wf_1) response, wf = self.generator.activate_workflow(wf) self.assert200(response) assignee = Person.query.get(self.assignee.id) with freeze_time("2015-01-01"): _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data) with freeze_time("2015-01-29"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data) with freeze_time("2015-02-01"): _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data)
def test_grouping_comments(self, _): """Test that comments are grouped by parent object in daily digest data.""" factories.AuditFactory(slug="Audit") self.import_file("assessment_template_no_warnings.csv") self.import_file("assessment_with_templates.csv") asmt1 = Assessment.query.filter_by(slug="A 1").first() asmt4 = Assessment.query.filter_by(slug="A 4").first() asmt6 = Assessment.query.filter_by(slug="A 6").first() asmt_ids = (asmt1.id, asmt4.id, asmt6.id) self.generator.generate_comment(asmt1, "Verifiers", "comment X on asmt " + str(asmt1.id), send_notification="true") self.generator.generate_comment(asmt6, "Verifiers", "comment A on asmt " + str(asmt6.id), send_notification="true") self.generator.generate_comment(asmt4, "Verifiers", "comment FOO on asmt " + str(asmt4.id), send_notification="true") self.generator.generate_comment(asmt4, "Verifiers", "comment BAR on asmt " + str(asmt4.id), send_notification="true") self.generator.generate_comment(asmt1, "Verifiers", "comment Y on asmt " + str(asmt1.id), send_notification="true") _, notif_data = common.get_daily_notifications() assignee_notifs = notif_data.get("*****@*****.**", {}) common.sort_comments(assignee_notifs) comment_notifs = assignee_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 3) # for 3 different Assessments # for each group of comment notifications, check that it contains comments # for that particular Assessment for parent_obj_key, comments_info in comment_notifs.iteritems(): self.assertIn(parent_obj_key.id, asmt_ids) for comment in comments_info: self.assertEqual(comment["parent_id"], parent_obj_key.id) self.assertEqual(comment["parent_type"], "Assessment") expected_suffix = "asmt " + str(parent_obj_key.id) self.assertTrue( comment["description"].endswith(expected_suffix))
def test_marking_sent_notifications(self, mail_mock): mail_mock.return_value = True with freeze_time("2015-02-01"): _, wf = self.generator.generate_workflow(self.quarterly_wf_1) response, wf = self.generator.activate_workflow(wf) self.assert200(response) assignee = Person.query.get(self.assignee.id) with freeze_time("2015-01-01"): _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data) with freeze_time("2015-01-29"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data) with freeze_time("2015-02-01"): _, notif_data = common.get_daily_notifications() self.assertNotIn(assignee.email, notif_data)
def test_single_task_accepted(self, mock_mail): """ test moving the end date to the future, befor due_in and due_today notifications have been sent """ with freeze_time("2015-05-01"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-05-02"): common.send_daily_digest_notifications() cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) self.task_change_status(task1, "Finished") _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) with freeze_time("2015-05-03"): cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) self.task_change_status(task1) user = Person.query.get(self.user.id) _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data) self.assertIn("all_tasks_completed", notif_data["*****@*****.**"])
def test_adjust_overdue_notifications_on_task_status_change(self, _): """Sending overdue notifications should take task status into account.""" with freeze_time("2017-05-15 14:25:36"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1, task2 = tasks self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)}) user = models.Person.query.get(self.user.id) user_email = user.email with freeze_time("2017-05-16 08:09:10"): # a day after task1 due date for state in CycleTaskGroupObjectTask.ACTIVE_STATES: # clear all notifications before before changing the task status models.Notification.query.delete() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) self.wf_generator.modify_object(task1, {"status": state}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) # WITHOUT clearing the overdue notifications, move the task to "verified" # state, and the overdue notification should disappear. self.wf_generator.modify_object(task1, {"status": "Verified"}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user_email, {}) self.assertNotIn("task_overdue", user_notifs)
def test_single_task_accepted(self, mock_mail): """Test moving the end date to the future on accepted task. It is done before due_in and due_today notifications have been sent. """ with freeze_time("2015-05-01"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-05-02"): common.send_daily_digest_notifications() cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) self.task_change_status(task1, "Finished") _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) with freeze_time("2015-05-03 13:20:34"): cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) self.task_change_status(task1) generate_cycle_tasks_notifs() user = Person.query.get(self.user.id) _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data) self.assertIn("all_tasks_completed", notif_data["*****@*****.**"])
def test_auto_generate_cycle(self, mock_mail): with freeze_time("2015-04-01"): _, wf = self.wf_generator.generate_workflow( self.monthly_workflow_1) self.wf_generator.activate_workflow(wf) person_1 = Person.query.get(self.person_1.id) with freeze_time("2015-04-02"): _, notif_data = common.get_daily_notifications() self.assertIn(person_1.email, notif_data) self.assertIn("cycle_starts_in", notif_data[person_1.email]) with freeze_time("2015-04-02"): self.api.tc.get("nightly_cron_endpoint") _, notif_data = common.get_daily_notifications() self.assertNotIn(person_1.email, notif_data) with freeze_time("2015-04-02"): start_recurring_cycles() _, notif_data = common.get_daily_notifications() self.assertNotIn(person_1.email, notif_data) # cycle starts on monday - 6th, and not on 5th with freeze_time("2015-04-03"): start_recurring_cycles() with freeze_time("2015-04-15"): # one day befor due date _, notif_data = common.get_daily_notifications() person_1 = Person.query.get(self.person_1.id) self.assertIn(person_1.email, notif_data) with freeze_time("2015-04-25"): # due date _, notif_data = common.get_daily_notifications() person_1 = Person.query.get(self.person_1.id) self.assertIn(person_1.email, notif_data)
def test_models_comments(self, obj_factory, _): """Test setting notification entries for model comments. Check if the correct notification entries are created when a comment gets posted. """ if obj_factory in self.SCOPING_OBJECT_FACTORIES: recipient_types = ["Admin", "Primary Contacts", "Secondary Contacts", "Product Managers", "Technical / Program Managers", "Technical Leads", "System Owners", "Legal Counsels"] else: recipient_types = ["Admin", "Primary Contacts", "Secondary Contacts"] person = all_models.Person.query.first() person_email = person.email with factories.single_commit(): obj = obj_factory( recipients=",".join(recipient_types), send_by_default=False, ) ac_roles = get_custom_roles_for(obj.type) for acr_id, acr_name in ac_roles.items(): if acr_name in recipient_types: factories.AccessControlListFactory( ac_role_id=acr_id, object=obj, person=person ) self.generator.generate_comment( obj, "", "some comment", send_notification="true") notifications, notif_data = common.get_daily_notifications() self.assertEqual(len(notifications), 1, "Missing comment notification entry.") recip_notifs = notif_data.get(person_email, {}) comment_notifs = recip_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 1) # Check if correct revisions count is created revisions = Revision.query.filter( Revision.resource_type == 'Notification', Revision.resource_id.in_([n.id for n in notifications]) ) self.assertEqual(revisions.count(), 1) self.client.get("/_notifications/send_daily_digest") notifications = self._get_notifications(notif_type="comment_created").all() self.assertEqual(len(notifications), 0, "Found a comment notification that was not sent.")
def test_one_time_wf_activate(self): def get_person(person_id): return db.session.query(Person).filter( Person.id == person_id).one() with freeze_time("2015-04-10"): _, wf = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(wf) self.wf_generator.activate_workflow(wf) person_1 = get_person(self.random_people[0].id) with freeze_time("2015-04-11"): _, notif_data = common.get_daily_notifications() self.assertIn("cycle_started", notif_data[person_1.email]) self.assertIn(cycle.id, notif_data[person_1.email]["cycle_started"]) self.assertIn( "my_tasks", notif_data[person_1.email]["cycle_started"][cycle.id]) with freeze_time("2015-05-03"): # two days befor due date _, notif_data = common.get_daily_notifications() self.assertIn(person_1.email, notif_data) self.assertNotIn("due_in", notif_data[person_1.email]) self.assertNotIn("due_today", notif_data[person_1.email]) with freeze_time("2015-05-04"): # one day befor due date _, notif_data = common.get_daily_notifications() self.assertEqual(len(notif_data[person_1.email]["due_in"]), 1) with freeze_time("2015-05-05"): # due date _, notif_data = common.get_daily_notifications() self.assertEqual(len(notif_data[person_1.email]["due_today"]), 1)
def test_custom_attr_change(self): """Test notification when custom attribute value is changed""" custom_attribute_values = [{ "custom_attribute_id": self.cad1.id, "attribute_value": "test value", }] response = self.api.put(self.assessment, { "custom_attribute_values": custom_attribute_values }) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_fields"], ["CA1"])
def test_delete_activated_workflow(self, mock_mail): with freeze_time("2015-02-01 13:39:20"): _, workflow = self.wf_generator.generate_workflow( self.quarterly_wf_1) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) user = Person.query.get(self.user.id) with freeze_time("2015-01-01 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertNotIn(user.email, notif_data) with freeze_time("2015-01-29 13:39:20"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_starts_in", notif_data[user.email]) workflow = Workflow.query.get(workflow.id) exists_qs = db.session.query( Notification.query.filter( Notification.object_id == workflow.id, Notification.object_type == workflow.__class__.__name__).exists()) self.assertTrue(exists_qs.one()[0]) response = self.wf_generator.api.delete(workflow) self.assert200(response) self.assertFalse(exists_qs.one()[0]) _, notif_data = common.get_daily_notifications() user = Person.query.get(self.user.id) self.assertNotIn(user.email, notif_data)
def test_adjust_overdue_notifications_on_task_due_date_change(self, is_vf_needed, _): """Sending overdue notifications should adjust to task due date changes.""" with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1, task2 = tasks self.wf_generator.modify_object(task2, {"end_date": date(2099, 12, 31)}) user = models.Person.query.get(self.user.id) with freeze_time("2017-05-16 08:09:10"): # a day after task1 due date _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1) # change task1 due date, there should be no overdue notification anymore self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 16)}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) # change task1 due date to the past there should a notification again self.wf_generator.modify_object(task1, {"end_date": date(2017, 5, 14)}) _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 1)
def test_custom_attr_change(self): """Test notification when custom attribute value is changed""" custom_attribute_values = [{ "custom_attribute_id": self.cad1.id, "attribute_value": "test value", }] response = self.api.put(self.assessment, { "custom_attribute_values": custom_attribute_values }) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_fields"], ["CA1"])
def test_multiply_updates(self): """Test notification for multiply updates""" response = self.api.put(self.assessment, {"test_plan": "steps"}) self.assert200(response) response = self.api.put(self.assessment, {"title": "new title"}) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_data"]["TITLE"], ("new title", "Assessment1")) self.assertEqual( updated[self.assessment.id]["updated_data"] ["ASSESSMENT PROCEDURE"], ("steps", ""))
def test_get_daily_notification_huge_data(self): """Test that we do not loose any notifications during merging chunks""" notif_list = mock.MagicMock(return_value=None) content = [(notif_list, {"*****@*****.**": {"notif": {"id": 1}}}), (notif_list, {"*****@*****.**": {"notif 2": {"id": 1}}}), (notif_list, {"*****@*****.**": {"notif": {"id": 1}}})] expected_data = {"*****@*****.**": {"notif": {"id": 1}}, "*****@*****.**": {"notif": {"id": 1}, "notif 2": {"id": 1}}} with mock.patch("ggrc.notifications.common.generate_daily_notifications", return_value=content): _, notif_data = common.get_daily_notifications() self.assertEqual(expected_data, notif_data)
def test_description_custom_change(self): """Test notification updated data when custom attribute value is changed""" response = self.api.put(self.assessment, { "title": "test_title", "description": "test_description" }) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_data"]["TITLE"], ("test_title", "Assessment1")) self.assertEqual( updated[self.assessment.id]["updated_data"]["DESCRIPTION"], ("test_description", ""))
def test_no_date_change(self, mock_mail): """Test a basic case with no moving end date""" with freeze_time("2015-04-10 03:21:34"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) assignee = self.user task_assignees = [assignee, self.secondary_assignee] with freeze_time("2015-04-11 03:21:34"): _, notif_data = common.get_daily_notifications() # cycle started notifs available only for contact self.assertIn("cycle_started", notif_data[assignee.email]) with freeze_time("2015-05-02 03:21:34"): _, notif_data = common.get_daily_notifications() self.assertIn(assignee.email, notif_data) # cycle started notifs available only for contact self.assertIn("cycle_started", notif_data[assignee.email]) for user in task_assignees: self.assertNotIn("due_in", notif_data[user.email]) self.assertNotIn("due_today", notif_data[user.email]) with freeze_time("2015-05-02 03:21:34"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to admin, one to assigne and one to secondary assignee self.assertEqual(mock_mail.call_count, 3) with freeze_time("2015-05-04 03:21:34"): # one day before due date _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data) self.assertIn("due_in", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_in"]), 2) with freeze_time("2015-05-04 03:21:34"): # one day before due date common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to admin and two each to assigne and secondary assignee self.assertEqual(mock_mail.call_count, 5) with freeze_time("2015-05-05 03:21:34"): # due date _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn("due_today", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_today"]), 2)
def test_labels_change(self): """Test notification updated data when labels are changed""" label_new = factories.LabelFactory(name="test_label", object_type='Assessment') response = self.api.put( self.assessment, {'labels': [{ "name": label_new.name, "id": label_new.id }]}) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_data"]["LABELS"], ("test_label", ""))
def test_models_comments(self, obj_factory, _): """Test setting notification entries for model comments. Check if the correct notification entries are created when a comment gets posted. """ recipient_types = ["Admin", "Primary Contacts", "Secondary Contacts"] person = all_models.Person.query.first() person_email = person.email with factories.single_commit(): obj = obj_factory( recipients=",".join(recipient_types), send_by_default=False, ) ac_roles = get_custom_roles_for(obj.type) for acr_id, acr_name in ac_roles.items(): if acr_name in recipient_types: factories.AccessControlListFactory(ac_role_id=acr_id, object=obj, person=person) self.generator.generate_comment(obj, "", "some comment", send_notification="true") notifications, notif_data = common.get_daily_notifications() self.assertEqual(len(notifications), 1, "Missing comment notification entry.") recip_notifs = notif_data.get(person_email, {}) comment_notifs = recip_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 1) # Check if correct revisions count is created revisions = Revision.query.filter( Revision.resource_type == 'Notification', Revision.resource_id.in_([n.id for n in notifications])) self.assertEqual(revisions.count(), 1) self.client.get("/_notifications/send_daily_digest") notifications = self._get_notifications( notif_type="comment_created").all() self.assertEqual(len(notifications), 0, "Found a comment notification that was not sent.")
def test_models_comments(self, model, _): """Test setting notification entries for model comments. Check if the correct notification entries are created when a comment gets posted. """ recipient_types = model.VALID_RECIPIENTS person = all_models.Person.query.first() person_email = person.email with factories.single_commit(): obj = factories.get_model_factory(model.__name__)( recipients=",".join(recipient_types), send_by_default=False, ) for acl in obj._access_control_list: # pylint: disable=protected-access if acl.ac_role.name in recipient_types: factories.AccessControlPersonFactory( ac_list=acl, person=person, ) self.generator.generate_comment(obj, "", "some comment", send_notification="true") notifications, notif_data = common.get_daily_notifications() self.assertEqual(len(notifications), 1, "Missing comment notification entry.") recip_notifs = notif_data.get(person_email, {}) comment_notifs = recip_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 1) # Check if correct revisions count is created revisions = Revision.query.filter( Revision.resource_type == 'Notification', Revision.resource_id.in_([n.id for n in notifications])) self.assertEqual(revisions.count(), 1) self.client.get("/_notifications/send_daily_digest") notifications = self._get_notifications( notif_type="comment_created").all() self.assertEqual(len(notifications), 0, "Found a comment notification that was not sent.")
def test_creating_obsolete_notifications(self, fake_now, expected_overdue, expected_due_today, expected_due_in, _): """Notifications already obsolete on creation date should not be created. """ # pylint: disable=invalid-name with freeze_time("2017-06-12 09:39:32"): tmp = self.one_time_workflow.copy() _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) task_assignees = [self.user, self.secondary_assignee] with freeze_time(fake_now): # mark all yeasterday notifications as sent all_models.Notification.query.filter( sa.func.DATE(all_models.Notification.send_on) < date.today() ).update( { all_models.Notification.sent_at: datetime.now() - timedelta(1) }, synchronize_session="fetch") _, notif_data = common.get_daily_notifications() for user in task_assignees: user_notifs = notif_data.get(user.email, {}) actual_overdue = [ n['title'] for n in user_notifs.get("task_overdue", {}).itervalues() ] actual_overdue.sort() self.assertEqual(actual_overdue, expected_overdue) self.assertEqual([ n['title'] for n in user_notifs.get("due_today", {}).itervalues() ], expected_due_today) self.assertEqual([ n['title'] for n in user_notifs.get("due_in", {}).itervalues() ], expected_due_in)
def test_grouping_comments(self, _): """Test that comments are grouped by parent object in daily digest data.""" factories.AuditFactory(slug="Audit") self.import_file("assessment_template_no_warnings.csv") self.import_file("assessment_with_templates.csv") asmt1 = Assessment.query.filter_by(slug="A 1").first() asmt4 = Assessment.query.filter_by(slug="A 4").first() asmt6 = Assessment.query.filter_by(slug="A 6").first() asmt_ids = (asmt1.id, asmt4.id, asmt6.id) self.generator.generate_comment( asmt1, "Verifiers", "comment X on asmt " + str(asmt1.id), send_notification="true") self.generator.generate_comment( asmt6, "Verifiers", "comment A on asmt " + str(asmt6.id), send_notification="true") self.generator.generate_comment( asmt4, "Verifiers", "comment FOO on asmt " + str(asmt4.id), send_notification="true") self.generator.generate_comment( asmt4, "Verifiers", "comment BAR on asmt " + str(asmt4.id), send_notification="true") self.generator.generate_comment( asmt1, "Verifiers", "comment Y on asmt " + str(asmt1.id), send_notification="true") _, notif_data = common.get_daily_notifications() assignee_notifs = notif_data.get("*****@*****.**", {}) common.sort_comments(assignee_notifs) comment_notifs = assignee_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 3) # for 3 different Assessments # for each group of comment notifications, check that it contains comments # for that particular Assessment for parent_obj_key, comments_info in comment_notifs.iteritems(): self.assertIn(parent_obj_key.id, asmt_ids) for comment in comments_info: self.assertEqual(comment["parent_id"], parent_obj_key.id) self.assertEqual(comment["parent_type"], "Assessment") expected_suffix = "asmt " + str(parent_obj_key.id) self.assertTrue(comment["description"].endswith(expected_suffix))
def test_ctgot_comments(self, _): """Test setting notification entries for ctgot comments. Check if the correct notification entries are created when a comment gets posted. """ person = all_models.Person.query.first() secondary_assignee = self.create_user_with_role(role="Reader") task_assignees_emails = [person.email, secondary_assignee.email] recipients = { "Task Assignees": person, "Task Secondary Assignees": secondary_assignee, } with factories.single_commit(): obj = wf_factories.CycleTaskGroupObjectTaskFactory( recipients=",".join(recipients), send_by_default=False, ) # pylint: disable=protected-access for acl in obj._access_control_list: if acl.ac_role.name in recipients: recipient = recipients.get(acl.ac_role.name) if recipient: factories.AccessControlPersonFactory( ac_list=acl, person=recipient, ) self.generator.generate_comment( obj, "", "some comment", send_notification="true") notifications, notif_data = common.get_daily_notifications() for email in task_assignees_emails: self.assertEqual(len(notifications), 1, "Missing comment notification entry.") recip_notifs = notif_data.get(email, {}) comment_notifs = recip_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 1) self.client.get("/_notifications/send_daily_digest") notifications = self._get_notifications(notif_type="comment_created").all() self.assertEqual(len(notifications), 0, "Found a comment notification that was not sent.")
def test_no_date_change(self, mock_mail): def get_person(person_id): return db.session.query(Person).filter( Person.id == person_id).one() with freeze_time("2015-04-10 03:21:34"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-04-11 03:21:34"): user = get_person(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn("cycle_started", notif_data[user.email]) with freeze_time("2015-05-02 03:21:34"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_started", notif_data[user.email]) self.assertNotIn("due_in", notif_data[user.email]) self.assertNotIn("due_today", notif_data[user.email]) with freeze_time("2015-05-02 03:21:34"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to admin and one to assigne self.assertEqual(mock_mail.call_count, 2) with freeze_time("2015-05-04 03:21:34"): # one day before due date _, notif_data = common.get_daily_notifications() user = get_person(self.user.id) self.assertIn(user.email, notif_data) self.assertIn("due_in", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_in"]), 2) with freeze_time("2015-05-04 03:21:34"): # one day before due date common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to admin and one to assigne self.assertEqual(mock_mail.call_count, 3) with freeze_time("2015-05-05 03:21:34"): # due date _, notif_data = common.get_daily_notifications() self.assertIn("due_today", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_today"]), 2)
def test_access_conrol_list(self): """Test notification when access conrol list is changed""" response = self.api.put( self.assessment, { "access_control_list": [{ "person": { "id": self.auditor.id, "type": "Person", }, "ac_role_id": self.secondary_role_id, "context": None }], }) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_fields"], ["PRIMARY CONTACTS", "SECONDARY CONTACTS"])
def test_access_conrol_list(self): """Test notification when access conrol list is changed""" assignee_acr = all_models.AccessControlRole.query.filter_by( object_type="Assessment", name="Assignees", ).first() response = self.api.put( self.assessment, { "access_control_list": [ acl_helper.get_acl_json(self.secondary_role_id, self.auditor.id), acl_helper.get_acl_json(assignee_acr.id, self.auditor.id) ], }) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual(updated[self.assessment.id]["updated_fields"], ["PRIMARY CONTACTS", "SECONDARY CONTACTS"])
def test_creating_overdue_notifications_for_new_tasks(self, _): """Overdue notifications should be created for tasks created with imports. """ Workflow.query.delete() models.Notification.query.delete() db.session.commit() filename = join(self.CSV_DIR, "workflow_small_sheet.csv") self.import_file(filename) workflow = Workflow.query.one() self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) user = models.Person.query.filter( models.Person.email == '*****@*****.**').one() with freeze_time("2020-01-01 00:00:00"): # afer all tasks' due dates _, notif_data = common.get_daily_notifications() user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 4)
def test_auto_generate_cycle(self, mock_mail): """Test auto recurring cycles""" with freeze_time("2015-04-01"): _, wf = self.wf_generator.generate_workflow( self.monthly_workflow_1) self.wf_generator.activate_workflow(wf) _, notif_data = common.get_daily_notifications() contact = self.person_1 task_assignees = [contact, self.secondary_assignee] for user in task_assignees: self.assertNotIn(user.email, notif_data) with freeze_time("2015-04-02"): self.api.client.get("nightly_cron_endpoint") _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertNotIn(user.email, notif_data) start_recurring_cycles() _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertNotIn(user.email, notif_data) # cycle starts on monday - 6th, and not on 5th with freeze_time("2015-04-03"): from ggrc.login import noop noop.login() start_recurring_cycles() _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data) # cycle started notifs available only for contact self.assertIn("cycle_started", notif_data[contact.email]) with freeze_time("2015-04-15"): # one day before due date _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data) with freeze_time("2015-04-25"): # due date _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data)
def test_move_end_date_to_today(self, mock_mail): def get_person(person_id): return db.session.query(Person).filter( Person.id == person_id).one() with freeze_time("2015-04-10 03:21:34"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-05-02 03:21:34"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to owner and one to assigne self.assertEqual(mock_mail.call_count, 2) with freeze_time("2015-05-03 03:21:34"): cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) task2 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[1].id) self.wf_generator.modify_object( task1, data={"end_date": date(2015, 5, 3)}) self.wf_generator.modify_object( task2, data={"end_date": date(2015, 5, 4)}) with freeze_time("2015-05-03 03:21:34"): # one day before due date user = get_person(self.user.id) _, notif_data = common.get_daily_notifications() self.assertNotEqual(notif_data, {}) self.assertIn(user.email, notif_data) self.assertIn("due_today", notif_data[user.email]) self.assertIn("due_in", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_today"]), 1) common.send_daily_digest_notifications() with freeze_time("2015-05-04 03:21:34"): # due date (of task2) user = get_person(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("due_today", notif_data[user.email]) self.assertNotIn("due_in", notif_data[user.email]) common.send_daily_digest_notifications() # check that overdue notifications are sent even on days after the day a # task has become due, unlike the "due_today" and "due_in" notifications with freeze_time("2015-05-05 03:21:34"): # 1+ days after due date(s) _, notif_data = common.get_daily_notifications() self.assertNotEqual(notif_data, {}) self.assertIn(user.email, notif_data) user_notifs = notif_data[user.email] self.assertNotIn("due_today", user_notifs) self.assertNotIn("due_in", user_notifs) self.assertIn("task_overdue", user_notifs) self.assertEqual(len(user_notifs["task_overdue"]), 2)
def test_move_end_date_to_future(self, mock_mail): """ test moving the end date to the future, befor due_in and due_today notifications have been sent """ def get_person(person_id): return db.session.query(Person).filter(Person.id == person_id).one() with freeze_time("2015-04-10 03:21:34"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) with freeze_time("2015-04-11 03:21:34"): user = get_person(self.user.id) _, notif_data = common.get_daily_notifications() self.assertIn("cycle_started", notif_data[user.email]) with freeze_time("2015-05-02 03:21:34"): _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("cycle_started", notif_data[user.email]) self.assertNotIn("due_in", notif_data[user.email]) self.assertNotIn("due_today", notif_data[user.email]) with freeze_time("2015-05-02 03:21:34"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to owner and one to assigne self.assertEqual(mock_mail.call_count, 2) with freeze_time("2015-05-03 03:21:34"): cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) task2 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[1].id) self.wf_generator.modify_object( task1, data={"end_date": date(2015, 5, 15)}) self.wf_generator.modify_object( task2, data={"end_date": date(2015, 5, 15)}) with freeze_time("2015-05-04 03:21:34"): # one day befor due date _, notif_data = common.get_daily_notifications() user = get_person(self.user.id) self.assertEqual(notif_data, {}) with freeze_time("2015-05-05 03:21:34"): # due date _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) with freeze_time("2015-05-14 03:21:34"): # due date _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) self.assertIn("due_in", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_in"]), len(self.random_objects)) with freeze_time("2015-05-15 03:21:34"): # due date _, notif_data = common.get_daily_notifications() self.assertIn(user.email, notif_data) # yesterdays mail has not been sent self.assertIn("due_in", notif_data[user.email]) self.assertIn("due_today", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_today"]), len(self.random_objects))
def test_sending_overdue_notifications_for_tasks(self, is_vf_needed, _): """Overdue notifications should be sent for overdue tasks every day. Even if an overdue notification has already been sent, it should still be sent in every following daily digest f a task is still overdue. """ with freeze_time("2017-05-15 14:25:36"): tmp = self.one_time_workflow.copy() tmp['is_verification_needed'] = is_vf_needed _, workflow = self.wf_generator.generate_workflow(tmp) self.wf_generator.generate_cycle(workflow) response, workflow = self.wf_generator.activate_workflow(workflow) self.assert200(response) tasks = workflow.cycles[0].cycle_task_group_object_tasks task1_id = tasks[0].id task2_id = tasks[1].id task_assignees = [self.user, self.secondary_assignee] with freeze_time("2017-05-14 08:09:10"): _, notif_data = common.get_daily_notifications() for user in task_assignees: user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) with freeze_time("2017-05-15 08:09:10"): # task 1 due date _, notif_data = common.get_daily_notifications() for user in task_assignees: user_notifs = notif_data.get(user.email, {}) self.assertNotIn("task_overdue", user_notifs) with freeze_time("2017-05-16 08:09:10"): # task 2 due date _, notif_data = common.get_daily_notifications() for user in task_assignees: user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) overdue_task_ids = sorted(user_notifs["task_overdue"].keys()) self.assertEqual(overdue_task_ids, [task1_id]) with freeze_time("2017-05-17 08:09:10"): # after both tasks' due dates _, notif_data = common.get_daily_notifications() for user in task_assignees: user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) overdue_task_ids = sorted(user_notifs["task_overdue"].keys()) self.assertEqual(overdue_task_ids, [task1_id, task2_id]) common.send_daily_digest_notifications() # even after sending the overdue notifications, they are sent again the # day after, too with freeze_time("2017-05-18 08:09:10"): _, notif_data = common.get_daily_notifications() for user in task_assignees: user_notifs = notif_data.get(user.email, {}) self.assertIn("task_overdue", user_notifs) overdue_task_ids = sorted(user_notifs["task_overdue"].keys()) self.assertEqual(overdue_task_ids, [task1_id, task2_id])
def test_move_end_date_to_future(self, mock_mail): """Test moving the end date to the future. It is done before due_in and due_today notifications have been sent. """ with freeze_time("2015-04-10 03:21:34"): _, workflow = self.wf_generator.generate_workflow( self.one_time_workflow_1) _, cycle = self.wf_generator.generate_cycle(workflow) self.wf_generator.activate_workflow(workflow) assignee = self.user task_assignees = [assignee, self.secondary_assignee] with freeze_time("2015-04-11 03:21:34"): _, notif_data = common.get_daily_notifications() # cycle started notifs available only for contact self.assertIn("cycle_started", notif_data[assignee.email]) with freeze_time("2015-05-02 03:21:34"): _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data) self.assertNotIn("due_in", notif_data[user.email]) self.assertNotIn("due_today", notif_data[user.email]) # cycle started notifs available only for contact self.assertIn("cycle_started", notif_data[assignee.email]) with freeze_time("2015-05-02 03:21:34"): common.send_daily_digest_notifications() _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) # one email to admin and one each to assigne and secondary assignee self.assertEqual(mock_mail.call_count, 3) with freeze_time("2015-05-03 03:21:34"): cycle = Cycle.query.get(cycle.id) task1 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[0].id) task2 = CycleTaskGroupObjectTask.query.get( cycle.cycle_task_group_object_tasks[1].id) self.wf_generator.modify_object( task1, data={"end_date": date(2015, 5, 15)}) self.wf_generator.modify_object( task2, data={"end_date": date(2015, 5, 15)}) with freeze_time("2015-05-04 03:21:34"): # one day before due date _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) with freeze_time("2015-05-05 03:21:34"): # due date _, notif_data = common.get_daily_notifications() self.assertEqual(notif_data, {}) with freeze_time("2015-05-14 03:21:34"): # due date _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data) self.assertIn("due_in", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_in"]), len(self.random_objects)) with freeze_time("2015-05-15 03:21:34"): # due date _, notif_data = common.get_daily_notifications() for user in task_assignees: self.assertIn(user.email, notif_data) self.assertIn("due_in", notif_data[user.email]) self.assertIn("due_today", notif_data[user.email]) self.assertEqual(len(notif_data[user.email]["due_today"]), len(self.random_objects))
def test_models_comments(self, obj_factory, _): """Test setting notification entries for model comments. Check if the correct notification entries are created when a comment gets posted. """ if obj_factory in self.SCOPING_OBJECT_FACTORIES: recipient_types = [ "Admin", "Primary Contacts", "Secondary Contacts", "Assignee", "Compliance Contacts", "Verifier", "Product Managers", "Technical / Program Managers", "Technical Leads", "System Owners", "Legal Counsels", "Line of Defense One Contacts", "Vice Presidents", ] elif obj_factory == factories.ControlFactory: recipient_types = ["Admin", "Control Operators", "Control Owners"] else: recipient_types = [ "Admin", "Primary Contacts", "Secondary Contacts" ] person = all_models.Person.query.first() person_email = person.email with factories.single_commit(): obj = obj_factory( recipients=",".join(recipient_types), send_by_default=False, ) for acl in obj._access_control_list: # pylint: disable=protected-access if acl.ac_role.name in recipient_types: factories.AccessControlPersonFactory( ac_list=acl, person=person, ) self.generator.generate_comment(obj, "", "some comment", send_notification="true") notifications, notif_data = common.get_daily_notifications() self.assertEqual(len(notifications), 1, "Missing comment notification entry.") recip_notifs = notif_data.get(person_email, {}) comment_notifs = recip_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 1) # Check if correct revisions count is created revisions = Revision.query.filter( Revision.resource_type == 'Notification', Revision.resource_id.in_([n.id for n in notifications])) self.assertEqual(revisions.count(), 1) self.client.get("/_notifications/send_daily_digest") notifications = self._get_notifications( notif_type="comment_created").all() self.assertEqual(len(notifications), 0, "Found a comment notification that was not sent.")
def test_grouping_comments(self, _): # pylint: disable=too-many-locals """Test that comments are grouped by parent object in daily digest data.""" with factories.single_commit(): audit = factories.AuditFactory() audit_slug = audit.slug asmt_templ = factories.AssessmentTemplateFactory(audit=audit) asmt_templ_slug = asmt_templ.slug assessments_data = [ collections.OrderedDict([ ("object_type", "Assessment"), ("Code*", ""), ("Audit*", audit_slug), ("Assignees*", "*****@*****.**"), ("Creators", "*****@*****.**"), ("Template", ""), ("Title", "A1"), ]), collections.OrderedDict([ ("object_type", "Assessment"), ("Code*", ""), ("Audit*", audit_slug), ("Assignees*", "*****@*****.**"), ("Creators", "*****@*****.**"), ("Template", asmt_templ_slug), ("Title", "A2"), ]), collections.OrderedDict([ ("object_type", "Assessment"), ("Code*", ""), ("Audit*", audit_slug), ("Assignees*", "*****@*****.**"), ("Creators", "*****@*****.**"), ("Template", asmt_templ_slug), ("Title", "A3"), ]), ] self.import_data(*assessments_data) asmt_with_no_templ = Assessment.query.filter_by(title="A1").first() asmt_with_templ_1 = Assessment.query.filter_by(title="A2").first() asmt_with_templ_2 = Assessment.query.filter_by(title="A3").first() asmt_ids = (asmt_with_no_templ.id, asmt_with_templ_1.id, asmt_with_templ_2.id) self.generator.generate_comment(asmt_with_no_templ, "Verifiers", "comment X on asmt " + str(asmt_with_no_templ.id), send_notification="true") self.generator.generate_comment(asmt_with_templ_2, "Verifiers", "comment A on asmt " + str(asmt_with_templ_2.id), send_notification="true") self.generator.generate_comment(asmt_with_templ_1, "Verifiers", "comment FOO on asmt " + str(asmt_with_templ_1.id), send_notification="true") self.generator.generate_comment(asmt_with_templ_1, "Verifiers", "comment BAR on asmt " + str(asmt_with_templ_1.id), send_notification="true") self.generator.generate_comment(asmt_with_no_templ, "Verifiers", "comment Y on asmt " + str(asmt_with_no_templ.id), send_notification="true") _, notif_data = common.get_daily_notifications() assignee_notifs = notif_data.get("*****@*****.**", {}) common.sort_comments(assignee_notifs) comment_notifs = assignee_notifs.get("comment_created", {}) self.assertEqual(len(comment_notifs), 3) # for 3 different Assessments # for each group of comment notifications, check that it contains comments # for that particular Assessment for parent_obj_key, comments_info in comment_notifs.iteritems(): self.assertIn(parent_obj_key.id, asmt_ids) for comment in comments_info: self.assertEqual(comment["parent_id"], parent_obj_key.id) self.assertEqual(comment["parent_type"], "Assessment") expected_suffix = "asmt " + str(parent_obj_key.id) self.assertTrue( comment["description"].endswith(expected_suffix))