コード例 #1
0
ファイル: test_ace.py プロジェクト: ratanasoth/edx-ace
    def test_ace_send_happy_path(self, _mock_get_template):
        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(
            name=u'test_channel',
            channel_type=ChannelType.EMAIL
        )
        patch_channels(self, [mock_channel])

        recipient = Recipient(username=u'testuser')
        msg = Message(
            app_label=u'testapp',
            name=u'testmessage',
            recipient=recipient,
        )
        ace.send(msg)
        mock_channel.deliver.assert_called_once_with(
            msg,
            RenderedEmail(
                from_name=TEMPLATES[u'testapp/edx_ace/testmessage/email/from_name.txt'].render(),
                subject=TEMPLATES[u'testapp/edx_ace/testmessage/email/subject.txt'].render(),
                body_html=TEMPLATES[u'testapp/edx_ace/testmessage/email/body.html'].render(),
                head_html=TEMPLATES[u'testapp/edx_ace/testmessage/email/head.html'].render(),
                body=TEMPLATES[u'testapp/edx_ace/testmessage/email/body.txt'].render(),
            ),
        )
コード例 #2
0
    def test_ace_send_happy_path(self):
        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(
            channel_type=ChannelType.EMAIL,
            action_links=[],
            tracker_image_sources=[],
        )

        recipient = Recipient(username=u'testuser')
        msg = Message(
            app_label=u'testapp',
            name=u'testmessage',
            recipient=recipient,
        )

        channel_map = ChannelMap([
            [u'sailthru_email', mock_channel],
        ])

        with patch(u'edx_ace.channel.channels', return_value=channel_map):
            ace.send(msg)

        mock_channel.deliver.assert_called_once_with(
            msg,
            RenderedEmail(
                from_name=u'template from_name.txt',
                subject=u'template subject.txt',
                # The new lines are needed because the template has some tags, which means leftover newlines
                body_html=u'template body.html\n\n\n\n\n',
                head_html=u'template head.html\n',
                body=u'template body.txt',
            ),
        )
コード例 #3
0
    def _assert_template_for_offset(self, offset, message_count):
        current_day, offset, target_day, upgrade_deadline = self._get_dates(offset)

        user = UserFactory.create()
        for course_index in range(message_count):
            self._schedule_factory(
                offset=offset,
                enrollment__user=user,
                enrollment__course__id=CourseKey.from_string('edX/toy/course{}'.format(course_index))
            )

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])

        mock_channel = Mock(
            channel_type=ChannelType.EMAIL,
            action_links=[],
            tracker_image_sources=[],
        )

        channel_map = ChannelMap([
            ['sailthru', mock_channel],
        ])

        sent_messages = []
        with self.settings(TEMPLATES=self._get_template_overrides()):
            with patch.object(self.task, 'async_send_task') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)

                num_expected_queries = NUM_QUERIES_FIRST_MATCH
                if self.queries_deadline_for_each_course:
                    # one query per course for opt-out and one for course modes
                    num_expected_queries += (message_count * 2) - 1
                else:
                    num_expected_queries += 1

                with self.assertNumQueries(num_expected_queries, table_blacklist=WAFFLE_TABLES):
                    self.task().apply(kwargs=dict(
                        site_id=self.site_config.site.id, target_day_str=serialize(target_day), day_offset=offset,
                        bin_num=self._calculate_bin_for_user(user),
                    ))
            num_expected_messages = 1 if self.consolidates_emails_for_learner else message_count
            self.assertEqual(len(sent_messages), num_expected_messages)

            with self.assertNumQueries(NUM_QUERIES_PER_MESSAGE_DELIVERY):
                with patch('openedx.core.djangoapps.schedules.tasks.segment.track') as mock_segment_track:
                    with patch('edx_ace.channel.channels', return_value=channel_map):
                        self.deliver_task(*sent_messages[0])
                        self.assertEqual(mock_segment_track.call_count, 1)

            self.assertEqual(mock_channel.deliver.call_count, 1)
            for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
                    self.assertNotIn("{{", template)
                    self.assertNotIn("}}", template)

            return mock_channel.deliver.mock_calls
コード例 #4
0
    def _assert_template_for_offset(self, offset, message_count):
        current_day, offset, target_day, upgrade_deadline = self._get_dates(offset)

        user = UserFactory.create()
        for course_index in range(message_count):
            self._schedule_factory(
                offset=offset,
                enrollment__user=user,
                enrollment__course__id=CourseKey.from_string('edX/toy/course{}'.format(course_index))
            )

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])

        mock_channel = Mock(
            channel_type=ChannelType.EMAIL,
            action_links=[],
            tracker_image_sources=[],
        )

        channel_map = ChannelMap([
            ['sailthru', mock_channel],
        ])

        sent_messages = []
        with self.settings(TEMPLATES=self._get_template_overrides()):
            with patch.object(self.task, 'async_send_task') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)

                num_expected_queries = NUM_QUERIES_FIRST_MATCH
                if self.queries_deadline_for_each_course:
                    # one query per course for opt-out and one for course modes
                    num_expected_queries += (message_count * 2) - 1
                else:
                    num_expected_queries += 1

                with self.assertNumQueries(num_expected_queries, table_blacklist=WAFFLE_TABLES):
                    self.task().apply(kwargs=dict(
                        site_id=self.site_config.site.id, target_day_str=serialize(target_day), day_offset=offset,
                        bin_num=self._calculate_bin_for_user(user),
                    ))
            num_expected_messages = 1 if self.consolidates_emails_for_learner else message_count
            self.assertEqual(len(sent_messages), num_expected_messages)

            with self.assertNumQueries(NUM_QUERIES_PER_MESSAGE_DELIVERY):
                with patch('openedx.core.djangoapps.schedules.tasks.segment.track') as mock_segment_track:
                    with patch('edx_ace.channel.channels', return_value=channel_map):
                        self.deliver_task(*sent_messages[0])
                        self.assertEqual(mock_segment_track.call_count, 1)

            self.assertEqual(mock_channel.deliver.call_count, 1)
            for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
                    self.assertNotIn("{{", template)
                    self.assertNotIn("}}", template)

            return mock_channel.deliver.mock_calls
コード例 #5
0
    def test_templates(self, message_count, day):

        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(
                upgrade_deadline=datetime.datetime(2017,
                                                   8,
                                                   3,
                                                   19,
                                                   44,
                                                   30,
                                                   tzinfo=pytz.UTC),
                enrollment__user=user,
                enrollment__course__id=CourseLocator(
                    'edX', 'toy', 'Course{}'.format(course_num)))
            for course_num in range(message_count)
        ]

        test_time = datetime.datetime(2017, 8, 3, 19, tzinfo=pytz.UTC)
        test_time_str = serialize(test_time)

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(name='test_channel',
                            channel_type=ChannelType.EMAIL)
        patch_channels(self, [mock_channel])

        sent_messages = []

        templates_override = deepcopy(settings.TEMPLATES)
        templates_override[0]['OPTIONS'][
            'string_if_invalid'] = "TEMPLATE WARNING - MISSING VARIABLE [%s]"
        with self.settings(TEMPLATES=templates_override):
            with patch.object(
                    tasks,
                    '_upgrade_reminder_schedule_send') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(
                    args)

                with self.assertNumQueries(3):
                    tasks.upgrade_reminder_schedule_bin(
                        self.site_config.site.id,
                        target_day_str=test_time_str,
                        day_offset=day,
                        bin_num=user.id % tasks.UPGRADE_REMINDER_NUM_BINS,
                        org_list=[schedules[0].enrollment.course.org],
                    )

            self.assertEqual(len(sent_messages), message_count)

            for args in sent_messages:
                tasks._upgrade_reminder_schedule_send(*args)

            self.assertEqual(mock_channel.deliver.call_count, message_count)
            for (_name, (_msg, email),
                 _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
コード例 #6
0
    def test_templates(self, message_count, day):

        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(start=datetime.datetime(2017,
                                                           8,
                                                           1,
                                                           19,
                                                           44,
                                                           30,
                                                           tzinfo=pytz.UTC),
                                   enrollment__user=user,
                                   enrollment__course__id=CourseLocator(
                                       'edX', 'toy', 'Hour{}'.format(idx)))
            for idx in range(message_count)
        ]

        test_time_str = serialize(
            datetime.datetime(2017, 8, 1, 19, tzinfo=pytz.UTC))

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(name='test_channel',
                            channel_type=ChannelType.EMAIL)
        patch_channels(self, [mock_channel])

        sent_messages = []

        templates_override = deepcopy(settings.TEMPLATES)
        templates_override[0]['OPTIONS'][
            'string_if_invalid'] = "TEMPLATE WARNING - MISSING VARIABLE [%s]"
        with self.settings(TEMPLATES=templates_override):
            with patch.object(
                    tasks,
                    '_recurring_nudge_schedule_send') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(
                    args)

                with self.assertNumQueries(2):
                    tasks.recurring_nudge_schedule_hour(
                        self.site_config.site.id,
                        day,
                        test_time_str,
                        [schedules[0].enrollment.course.org],
                    )

            self.assertEqual(len(sent_messages), 1)

            for args in sent_messages:
                tasks._recurring_nudge_schedule_send(*args)

            self.assertEqual(mock_channel.deliver.call_count, 1)
            for (_name, (_msg, email),
                 _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
コード例 #7
0
    def _assert_template_for_offset(self, offset, message_count):
        current_day, offset, target_day, upgrade_deadline = self._get_dates(
            offset)

        user = UserFactory.create()
        for course_index in range(message_count):
            ScheduleFactory.create(
                start=target_day,
                upgrade_deadline=upgrade_deadline,
                enrollment__course__self_paced=True,
                enrollment__user=user,
                enrollment__course__id=CourseKey.from_string(
                    'edX/toy/course{}'.format(course_index)))

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(name='test_channel',
                            channel_type=ChannelType.EMAIL)
        patch_channels(self, [mock_channel])

        sent_messages = []
        with self.settings(TEMPLATES=self._get_template_overrides()):
            with patch.object(self.task,
                              'async_send_task') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(
                    args)

                num_expected_queries = NUM_QUERIES_FIRST_MATCH
                if self.queries_deadline_for_each_course:
                    num_expected_queries += (message_count - 1)

                with self.assertNumQueries(num_expected_queries,
                                           table_blacklist=WAFFLE_TABLES):
                    self.task.apply(kwargs=dict(
                        site_id=self.site_config.site.id,
                        target_day_str=serialize(target_day),
                        day_offset=offset,
                        bin_num=self._calculate_bin_for_user(user),
                    ))
            num_expected_messages = 1 if self.consolidates_emails_for_learner else message_count
            self.assertEqual(len(sent_messages), num_expected_messages)

            with self.assertNumQueries(2):
                self.deliver_task(*sent_messages[0])

            self.assertEqual(mock_channel.deliver.call_count, 1)
            for (_name, (_msg, email),
                 _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
                    self.assertNotIn("{{", template)
                    self.assertNotIn("}}", template)
コード例 #8
0
    def test_templates(self, message_count, day):

        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(
                start=datetime.datetime(2017, 8, 3, 19, 44, 30, tzinfo=pytz.UTC),
                enrollment__user=user,
                enrollment__course__id=CourseLocator('edX', 'toy', 'Course{}'.format(course_num))
            )
            for course_num in range(message_count)
        ]

        test_time = datetime.datetime(2017, 8, 3, 19, tzinfo=pytz.UTC)
        test_time_str = serialize(test_time)

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(
            name='test_channel',
            channel_type=ChannelType.EMAIL
        )
        patch_channels(self, [mock_channel])

        sent_messages = []

        with self.settings(TEMPLATES=self._get_template_overrides()):
            with patch.object(tasks, '_recurring_nudge_schedule_send') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)

                with self.assertNumQueries(NUM_QUERIES_WITH_MATCHES, table_blacklist=WAFFLE_TABLES):
                    tasks.recurring_nudge_schedule_bin(
                        self.site_config.site.id, target_day_str=test_time_str, day_offset=day,
                        bin_num=self._calculate_bin_for_user(user), org_list=[schedules[0].enrollment.course.org],
                    )

            self.assertEqual(len(sent_messages), 1)

            # Load the site
            # Check the schedule config
            with self.assertNumQueries(2):
                for args in sent_messages:
                    tasks._recurring_nudge_schedule_send(*args)

            self.assertEqual(mock_channel.deliver.call_count, 1)
            for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
コード例 #9
0
    def test_templates(self, message_count, day):

        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(
                start=datetime.datetime(2017, 8, 3, 19, 44, 30, tzinfo=pytz.UTC),
                enrollment__user=user,
                enrollment__course__id=CourseLocator('edX', 'toy', 'Course{}'.format(course_num))
            )
            for course_num in range(message_count)
        ]

        test_datetime = datetime.datetime(2017, 8, 3, 19, tzinfo=pytz.UTC)
        test_datetime_str = serialize(test_datetime)

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(
            name='test_channel',
            channel_type=ChannelType.EMAIL
        )
        patch_channels(self, [mock_channel])

        sent_messages = []

        with self.settings(TEMPLATES=self._get_template_overrides()):
            with patch.object(tasks, '_recurring_nudge_schedule_send') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)

                with self.assertNumQueries(NUM_QUERIES_WITH_MATCHES, table_blacklist=WAFFLE_TABLES):
                    tasks.recurring_nudge_schedule_bin(
                        self.site_config.site.id, target_day_str=test_datetime_str, day_offset=day,
                        bin_num=self._calculate_bin_for_user(user), org_list=[schedules[0].enrollment.course.org],
                    )

            self.assertEqual(len(sent_messages), 1)

            # Load the site
            # Check the schedule config
            with self.assertNumQueries(2):
                for args in sent_messages:
                    tasks._recurring_nudge_schedule_send(*args)

            self.assertEqual(mock_channel.deliver.call_count, 1)
            for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
コード例 #10
0
    def test_templates(self, message_count, day):

        settings.TEMPLATES[0]['OPTIONS']['string_if_invalid'] = "TEMPLATE WARNING - MISSING VARIABLE [%s]"
        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(
                start=datetime.datetime(2017, 8, 1, 19, 44, 30, tzinfo=pytz.UTC),
                enrollment__user=user,
                enrollment__course__id=CourseLocator('edX', 'toy', 'Hour{}'.format(idx))
            )
            for idx in range(message_count)
        ]

        test_time_str = serialize(datetime.datetime(2017, 8, 1, 19, tzinfo=pytz.UTC))

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(
            name='test_channel',
            channel_type=ChannelType.EMAIL
        )
        patch_channels(self, [mock_channel])

        sent_messages = []

        with patch.object(tasks, '_recurring_nudge_schedule_send') as mock_schedule_send:
            mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)

            with self.assertNumQueries(2):
                tasks.recurring_nudge_schedule_hour(
                    self.site_config.site.id, day, test_time_str, [schedules[0].enrollment.course.org],
                )

        self.assertEqual(len(sent_messages), 1)

        for args in sent_messages:
            tasks._recurring_nudge_schedule_send(*args)

        self.assertEqual(mock_channel.deliver.call_count, 1)
        for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:
            for template in attr.astuple(email):
                self.assertNotIn("TEMPLATE WARNING", template)
コード例 #11
0
    def test_templates(self, message_count, day):
        DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)
        now = datetime.datetime.now(pytz.UTC)
        future_date = now + datetime.timedelta(days=21)

        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(upgrade_deadline=future_date,
                                   enrollment__user=user,
                                   enrollment__course__id=CourseLocator(
                                       'edX', 'toy',
                                       'Course{}'.format(course_num)))
            for course_num in range(message_count)
        ]

        for schedule in schedules:
            schedule.enrollment.course.self_paced = True
            schedule.enrollment.course.save()

            CourseModeFactory(course_id=schedule.enrollment.course.id,
                              mode_slug=CourseMode.VERIFIED,
                              expiration_datetime=future_date)

        test_time = future_date
        test_time_str = serialize(test_time)

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(name='test_channel',
                            channel_type=ChannelType.EMAIL)
        patch_channels(self, [mock_channel])

        sent_messages = []

        templates_override = deepcopy(settings.TEMPLATES)
        templates_override[0]['OPTIONS'][
            'string_if_invalid'] = "TEMPLATE WARNING - MISSING VARIABLE [%s]"
        with self.settings(TEMPLATES=templates_override):
            with patch.object(
                    tasks,
                    '_upgrade_reminder_schedule_send') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(
                    args)

                # we execute one query per course to see if it's opted out of dynamic upgrade deadlines, however,
                # since we create a new course for each schedule in this test, we expect there to be one per message
                num_expected_queries = NUM_QUERIES_WITH_MATCHES + NUM_QUERIES_WITH_DEADLINE + message_count
                with self.assertNumQueries(num_expected_queries,
                                           table_blacklist=WAFFLE_TABLES):
                    tasks.upgrade_reminder_schedule_bin(
                        self.site_config.site.id,
                        target_day_str=test_time_str,
                        day_offset=day,
                        bin_num=user.id % tasks.UPGRADE_REMINDER_NUM_BINS,
                        org_list=[schedules[0].enrollment.course.org],
                    )

            self.assertEqual(len(sent_messages), message_count)

            for args in sent_messages:
                tasks._upgrade_reminder_schedule_send(*args)

            self.assertEqual(mock_channel.deliver.call_count, message_count)
            for (_name, (_msg, email),
                 _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)
コード例 #12
0
    def test_templates(self, message_count, day):
        now = datetime.datetime.now(pytz.UTC)
        future_datetime = now + datetime.timedelta(days=21)

        user = UserFactory.create()
        schedules = [
            ScheduleFactory.create(
                upgrade_deadline=future_datetime,
                enrollment__user=user,
                enrollment__course__id=CourseLocator('edX', 'toy', 'Course{}'.format(course_num))
            )
            for course_num in range(message_count)
        ]

        for schedule in schedules:
            schedule.enrollment.course.self_paced = True
            schedule.enrollment.course.end = future_datetime + datetime.timedelta(days=30)
            schedule.enrollment.course.save()

            CourseModeFactory(
                course_id=schedule.enrollment.course.id,
                mode_slug=CourseMode.VERIFIED,
                expiration_datetime=future_datetime
            )

        test_datetime = future_datetime
        test_datetime_str = serialize(test_datetime)

        patch_policies(self, [StubPolicy([ChannelType.PUSH])])
        mock_channel = Mock(
            name='test_channel',
            channel_type=ChannelType.EMAIL
        )
        patch_channels(self, [mock_channel])

        sent_messages = []

        with self.settings(TEMPLATES=self._get_template_overrides()):
            with patch.object(tasks, '_upgrade_reminder_schedule_send') as mock_schedule_send:
                mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args)

                # we execute one query per course to see if it's opted out of dynamic upgrade deadlines, however,
                # since we create a new course for each schedule in this test, we expect there to be one per message
                num_expected_queries = NUM_QUERIES_WITH_MATCHES + NUM_QUERIES_WITH_DEADLINE + message_count
                with self.assertNumQueries(num_expected_queries, table_blacklist=WAFFLE_TABLES):
                    tasks.upgrade_reminder_schedule_bin(
                        self.site_config.site.id, target_day_str=test_datetime_str, day_offset=day,
                        bin_num=self._calculate_bin_for_user(user),
                        org_list=[schedules[0].enrollment.course.org],
                    )

            self.assertEqual(len(sent_messages), message_count)

            # Load the site (which we query per message sent)
            # Check the schedule config
            with self.assertNumQueries(1 + message_count):
                for args in sent_messages:
                    tasks._upgrade_reminder_schedule_send(*args)

            self.assertEqual(mock_channel.deliver.call_count, message_count)
            for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:
                for template in attr.astuple(email):
                    self.assertNotIn("TEMPLATE WARNING", template)