Example #1
0
    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)
Example #2
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)
Example #3
0
    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)
Example #4
0
    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_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.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)
Example #9
0
    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)
Example #11
0
    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)
Example #12
0
    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)
Example #15
0
    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)
Example #17
0
    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
Example #19
0
    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'])