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', ), )
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(), ), )
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
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)
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)
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)
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)
def test_policies(self, deny_values, expected_channels): policies = [StubPolicy(deny_value) for deny_value in deny_values] with mock.patch.object(policy, 'policies', return_value=policies): channels = policy.channels_for(message=mock.Mock()) self.assertEqual(channels, expected_channels)
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)