def test_erred_timed_notifications(self): """ Tests that we can create a timed notification and make sure it gets executed with the timer polling """ # assert we start have with no notifications self.assertEqual(self.store.get_num_notifications_for_user(1), 0) # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(seconds=1), scope_name='user', scope_context={} # missing user_id ) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNotNone(updated_timer.err_msg) self.assertIsNotNone(updated_timer.results) self.assertIsNotNone(updated_timer.results['errors']) # should be no notifications self.assertEqual(self.store.get_num_notifications_for_user(1), 0)
def test_timed_notifications(self): """ Tests that we can create a timed notification and make sure it gets executed with the timer polling """ # assert we start have with no notifications self.assertEqual(self.store.get_num_notifications_for_user(1), 0) # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(seconds=1), scope_name='user', scope_context={'user_id': 1} ) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNone(updated_timer.err_msg) self.assertIsNotNone(updated_timer.results) # assert we now have a notification due to the timer executing self.assertEqual(self.store.get_num_notifications_for_user(1), 1) notifications = self.store.get_notifications_for_user(1) self.assertEqual(len(notifications), 1) read_user_msg = notifications[0] self.assertEqual(read_user_msg.msg.payload, self.msg.get_payload()) self.assertNotIn('extra', read_user_msg.msg.payload)
def test_cancel_timer(self): """ Make sure we a cancel a timer """ # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(days=1), scope_name='user', scope_context={'range': 1} ) cancel_timed_notification(timer.name) # fetch the timer again from DB updated_timer = self.store.get_notification_timer(timer.name) # is_active = False self.assertFalse(updated_timer.is_active) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) # should not have been executed self.assertIsNone(updated_timer.executed_at)
def test_timed_broadcast(self): """ Tests that we can create a timed notification and make sure it gets executed with the timer polling """ # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(seconds=1), scope_name='list_scope', scope_context={'range': 5} ) # assert we start have with no notifications for user_id in range(timer.context['distribution_scope']['scope_context']['range']): self.assertEqual(self.store.get_num_notifications_for_user(user_id), 0) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNone(updated_timer.err_msg) # assert we now have a notification for user_id in range(timer.context['distribution_scope']['scope_context']['range']): self.assertEqual(self.store.get_num_notifications_for_user(user_id), 1)
def test_timed_broadcast(self): """ Tests that we can create a timed notification and make sure it gets executed with the timer polling """ # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(seconds=1), scope_name='list_scope', scope_context={'range': 5} ) # assert we start have with no notifications for user_id in range(timer.context['distribution_scope']['scope_context']['range']): self.assertEquals(self.store.get_num_notifications_for_user(user_id), 0) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNone(updated_timer.err_msg) # assert we now have a notification for user_id in range(timer.context['distribution_scope']['scope_context']['range']): self.assertEquals(self.store.get_num_notifications_for_user(user_id), 1)
def test_erred_timed_notifications(self): """ Tests that we can create a timed notification and make sure it gets executed with the timer polling """ # assert we start have with no notifications self.assertEquals(self.store.get_num_notifications_for_user(1), 0) # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(seconds=1), scope_name='user', scope_context={} # missing user_id ) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNotNone(updated_timer.err_msg) self.assertIsNotNone(updated_timer.results) self.assertIsNotNone(updated_timer.results['errors']) # should be no notifications self.assertEquals(self.store.get_num_notifications_for_user(1), 0)
def test_timed_notifications(self): """ Tests that we can create a timed notification and make sure it gets executed with the timer polling """ # assert we start have with no notifications self.assertEquals(self.store.get_num_notifications_for_user(1), 0) # set up a timer that is due in the past timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(seconds=1), scope_name='user', scope_context={'user_id': 1} ) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNone(updated_timer.err_msg) self.assertIsNotNone(updated_timer.results) # assert we now have a notification due to the timer executing self.assertEquals(self.store.get_num_notifications_for_user(1), 1) notifications = self.store.get_notifications_for_user(1) self.assertEqual(len(notifications), 1) read_user_msg = notifications[0] self.assertEqual(read_user_msg.msg.payload, self.msg.get_payload()) self.assertNotIn('extra', read_user_msg.msg.payload)
def test_recurring_timer(self): """ Make sure recurring timers work """ timer = NotificationCallbackTimer( name='foo', class_name= 'edx_notifications.tests.test_timer.NullNotificationCallbackTimerHandler', callback_at=datetime.now(pytz.UTC) - timedelta(days=1), context={}, is_active=True, periodicity_min=1) self.store.save_notification_timer(timer) poll_and_execute_timers() timer1 = self.store.get_notification_timer(timer.name) self.assertIsNone( timer1.executed_at) # should be marked as still to execute self.assertIsNone(timer1.err_msg) self.assertNotEqual( timer.callback_at, timer1.callback_at) # verify the callback time is incremented
def test_update_timer_past_due(self): """ Make sure if we register a timer, update it so that it is in the past, that the original timer is cancelled """ # set up a timer that is due in the future publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) + timedelta(days=1), scope_name='user', scope_context={'range': 1}, timer_name='test-timer', ignore_if_past_due=True ) # now update it so that it is in the past publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(days=1), scope_name='user', scope_context={'range': 1}, timer_name='test-timer', ignore_if_past_due=True ) # fetch the timer from the DB timer = self.store.get_notification_timer('test-timer') # should not be active, the the update operation should # have marked it as cancelled self.assertFalse(timer.is_active) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) # should not have been executed self.assertIsNone(updated_timer.executed_at) # now, re-edit and put back to the future publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) + timedelta(days=1), scope_name='user', scope_context={'range': 1}, timer_name='test-timer', ignore_if_past_due=True ) # fetch the timer from the DB timer = self.store.get_notification_timer('test-timer') # should be active again self.assertTrue(timer.is_active)
def test_bad_handler(self): """ Make sure that a timer with a bad class_name doesn't operate """ timer = NotificationCallbackTimer( name='foo', class_name='edx_notifications.badmodule.BadHandler', callback_at=datetime.now(pytz.UTC) - timedelta(days=1), context={}, is_active=True) self.store.save_notification_timer(timer) poll_and_execute_timers() updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNotNone(updated_timer.err_msg)
def test_bad_handler(self): """ Make sure that a timer with a bad class_name doesn't operate """ timer = NotificationCallbackTimer( name='foo', class_name='edx_notifications.badmodule.BadHandler', callback_at=datetime.now(pytz.UTC) - timedelta(days=1), context={}, is_active=True ) self.store.save_notification_timer(timer) poll_and_execute_timers() updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNotNone(updated_timer.err_msg)
def test_error_in_execution(self): """ Make sure recurring timers work """ timer = NotificationCallbackTimer( name='foo', class_name='edx_notifications.tests.test_timer.ExceptionNotificationCallbackTimerHandler', callback_at=datetime.now(pytz.UTC) - timedelta(days=1), context={}, is_active=True ) self.store.save_notification_timer(timer) poll_and_execute_timers() updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNotNone(updated_timer.err_msg)
def test_wait_for_correct_time(self): """ Make sure timers don't fire too early and they can be rescheduled """ # set up a timer that is due in the future timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) + timedelta(days=1), scope_name='user', scope_context={'range': 1} ) poll_and_execute_timers() # fetch the timer again from DB updated_timer = self.store.get_notification_timer(timer.name) # should not have executed self.assertIsNone(updated_timer.executed_at) timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(days=1), scope_name='user', scope_context={'user_id': 1}, timer_name=timer.name ) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNone(updated_timer.err_msg) # assert we now have a notification due to the timer executing self.assertEquals(self.store.get_num_notifications_for_user(1), 1)
def test_wait_for_correct_time(self): """ Make sure timers don't fire too early and they can be rescheduled """ # set up a timer that is due in the future timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) + timedelta(days=1), scope_name='user', scope_context={'range': 1} ) poll_and_execute_timers() # fetch the timer again from DB updated_timer = self.store.get_notification_timer(timer.name) # should not have executed self.assertIsNone(updated_timer.executed_at) timer = publish_timed_notification( msg=self.msg, send_at=datetime.now(pytz.UTC) - timedelta(days=1), scope_name='user', scope_context={'user_id': 1}, timer_name=timer.name ) poll_and_execute_timers() # fetch the timer from the DB as it should be updated updated_timer = self.store.get_notification_timer(timer.name) self.assertIsNotNone(updated_timer.executed_at) self.assertIsNone(updated_timer.err_msg) # assert we now have a notification due to the timer executing self.assertEqual(self.store.get_num_notifications_for_user(1), 1)
def test_recurring_timer(self): """ Make sure recurring timers work """ timer = NotificationCallbackTimer( name='foo', class_name='edx_notifications.tests.test_timer.NullNotificationCallbackTimerHandler', callback_at=datetime.now(pytz.UTC) - timedelta(days=1), context={}, is_active=True, periodicity_min=1 ) self.store.save_notification_timer(timer) poll_and_execute_timers() timer1 = self.store.get_notification_timer(timer.name) self.assertIsNone(timer1.executed_at) # should be marked as still to execute self.assertIsNone(timer1.err_msg) self.assertNotEqual(timer.callback_at, timer1.callback_at) # verify the callback time is incremented
def test_publish_timed_notification(self, mock_parse_push): """ Happy path testing of a push notification that is put on a timer """ send_at = datetime.now(pytz.UTC) - timedelta(days=1) ParsePushNotificationChannelProvider.publish_notification( 'test-runner', 'test-type', { 'foo': 'bar', 'one': 'two' }, ['test_channel_id'], send_at=send_at) # force the timer to execute poll_and_execute_timers() # Parse should have been called self.assertTrue(mock_parse_push.alert.called) mock_parse_push.alert.assert_called_with(data=self.msg.payload, channels=['test_channel_id'])
def test_publish_timed_notification(self, mock_parse_push): """ Happy path testing of a push notification that is put on a timer """ send_at = datetime.now(pytz.UTC) - timedelta(days=1) ParsePushNotificationChannelProvider.publish_notification( 'test-runner', 'test-type', { 'foo': 'bar', 'one': 'two' }, ['test_channel_id'], send_at=send_at ) # force the timer to execute poll_and_execute_timers() # Parse should have been called self.assertTrue(mock_parse_push.alert.called) mock_parse_push.alert.assert_called_with(data=self.msg.payload, channels=['test_channel_id'])