def test_site_config(self, org_list, exclude_orgs, expected_message_count, mock_schedule_send, mock_ace): filtered_org = 'filtered_org' unfiltered_org = 'unfiltered_org' site1 = SiteFactory.create(domain='foo1.bar', name='foo1.bar') limited_config = SiteConfigurationFactory.create(values={'course_org_filter': [filtered_org]}, site=site1) site2 = SiteFactory.create(domain='foo2.bar', name='foo2.bar') unlimited_config = SiteConfigurationFactory.create(values={'course_org_filter': []}, site=site2) for config in (limited_config, unlimited_config): ScheduleConfigFactory.create(site=config.site) ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=filtered_org, ) for _ in range(2): ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=unfiltered_org, ) test_time_str = serialize(datetime.datetime(2017, 8, 2, 17, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( limited_config.site.id, 3, test_time_str, org_list=org_list, exclude_orgs=exclude_orgs, ) self.assertEqual(mock_schedule_send.apply_async.call_count, expected_message_count) self.assertFalse(mock_ace.send.called)
def test_multiple_enrollments(self, test_hour, messages_sent, mock_schedule_send, mock_ace): user = UserFactory.create() schedules = [ ScheduleFactory.create(start=datetime.datetime(2017, 8, 1, hour, 44, 30, tzinfo=pytz.UTC), enrollment__user=user, enrollment__course__id=CourseLocator( 'edX', 'toy', 'Hour{}'.format(hour))) for hour in (19, 20, 21) ] test_time_str = serialize( datetime.datetime(2017, 8, 1, test_hour, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( self.site_config.site.id, 3, test_time_str, [schedules[0].enrollment.course.org], ) self.assertEqual(mock_schedule_send.apply_async.call_count, messages_sent) self.assertFalse(mock_ace.send.called)
def test_no_course_overview(self, mock_schedule_send): schedule = ScheduleFactory.create(start=datetime.datetime( 2017, 8, 1, 20, 34, 30, tzinfo=pytz.UTC), ) schedule.enrollment.course_id = CourseKey.from_string( 'edX/toy/Not_2012_Fall') schedule.enrollment.save() test_time_str = serialize( datetime.datetime(2017, 8, 1, 20, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( self.site_config.site.id, 3, test_time_str, [schedule.enrollment.course.org], ) # There is no database constraint that enforces that enrollment.course_id points # to a valid CourseOverview object. However, in that case, schedules isn't going # to attempt to address it, and will instead simply skip those users. # This happens 'transparently' because django generates an inner-join between # enrollment and course_overview, and thus will skip any rows where course_overview # is null. self.assertEqual(mock_schedule_send.apply_async.call_count, 0)
def test_site_config(self, org_list, exclude_orgs, expected_message_count, mock_schedule_send, mock_ace): filtered_org = 'filtered_org' unfiltered_org = 'unfiltered_org' site1 = SiteFactory.create(domain='foo1.bar', name='foo1.bar') limited_config = SiteConfigurationFactory.create( values={'course_org_filter': [filtered_org]}, site=site1) site2 = SiteFactory.create(domain='foo2.bar', name='foo2.bar') unlimited_config = SiteConfigurationFactory.create( values={'course_org_filter': []}, site=site2) for config in (limited_config, unlimited_config): ScheduleConfigFactory.create(site=config.site) filtered_sched = ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=filtered_org, ) unfiltered_scheds = [ ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=unfiltered_org, ) for _ in range(2) ] print(filtered_sched.enrollment) print(filtered_sched.enrollment.course) print(filtered_sched.enrollment.course.org) print(unfiltered_scheds[0].enrollment) print(unfiltered_scheds[0].enrollment.course) print(unfiltered_scheds[0].enrollment.course.org) print(unfiltered_scheds[1].enrollment) print(unfiltered_scheds[1].enrollment.course) print(unfiltered_scheds[1].enrollment.course.org) test_time_str = serialize( datetime.datetime(2017, 8, 2, 17, tzinfo=pytz.UTC)) with self.assertNumQueries(1): tasks.recurring_nudge_schedule_hour( limited_config.site.id, 3, test_time_str, org_list=org_list, exclude_orgs=exclude_orgs, ) print(mock_schedule_send.mock_calls) self.assertEqual(mock_schedule_send.apply_async.call_count, expected_message_count) self.assertFalse(mock_ace.send.called)
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 test_schedule_hour(self, schedule_count, mock_schedule_send, mock_ace): schedules = [ ScheduleFactory.create(start=datetime.datetime(2017, 8, 1, 18, 34, 30, tzinfo=pytz.UTC)) for _ in range(schedule_count) ] test_time_str = serialize(datetime.datetime(2017, 8, 1, 18, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( self.site_config.site.id, 3, test_time_str, [schedules[0].enrollment.course.org], ) self.assertEqual(mock_schedule_send.apply_async.call_count, schedule_count) self.assertFalse(mock_ace.send.called)
def test_site_config(self, org_list, exclude_orgs, expected_message_count, mock_schedule_send, mock_ace): filtered_org = 'filtered_org' unfiltered_org = 'unfiltered_org' site1 = SiteFactory.create(domain='foo1.bar', name='foo1.bar') limited_config = SiteConfigurationFactory.create( values={'course_org_filter': [filtered_org]}, site=site1) site2 = SiteFactory.create(domain='foo2.bar', name='foo2.bar') unlimited_config = SiteConfigurationFactory.create( values={'course_org_filter': []}, site=site2) for config in (limited_config, unlimited_config): ScheduleConfigFactory.create(site=config.site) user1 = UserFactory.create() user2 = UserFactory.create() ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=filtered_org, enrollment__user=user1, ) ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=unfiltered_org, enrollment__user=user1, ) ScheduleFactory.create( start=datetime.datetime(2017, 8, 2, 17, 44, 30, tzinfo=pytz.UTC), enrollment__course__org=unfiltered_org, enrollment__user=user2, ) test_time_str = serialize( datetime.datetime(2017, 8, 2, 17, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( limited_config.site.id, day=3, target_hour_str=test_time_str, org_list=org_list, exclude_orgs=exclude_orgs, ) self.assertEqual(mock_schedule_send.apply_async.call_count, expected_message_count) self.assertFalse(mock_ace.send.called)
def test_multiple_enrollments(self, test_hour, messages_sent, mock_schedule_send, mock_ace): user = UserFactory.create() schedules = [ ScheduleFactory.create( start=datetime.datetime(2017, 8, 1, hour, 44, 30, tzinfo=pytz.UTC), enrollment__user=user, enrollment__course__id=CourseLocator('edX', 'toy', 'Hour{}'.format(hour)) ) for hour in (19, 20, 21) ] test_time_str = serialize(datetime.datetime(2017, 8, 1, test_hour, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( self.site_config.site.id, 3, test_time_str, [schedules[0].enrollment.course.org], ) self.assertEqual(mock_schedule_send.apply_async.call_count, messages_sent) self.assertFalse(mock_ace.send.called)
def test_schedule_hour(self, schedule_count, mock_schedule_send, mock_ace): schedules = [ ScheduleFactory.create(start=datetime.datetime( 2017, 8, 1, 18, 34, 30, tzinfo=pytz.UTC)) for _ in range(schedule_count) ] test_time_str = serialize( datetime.datetime(2017, 8, 1, 18, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( self.site_config.site.id, 3, test_time_str, [schedules[0].enrollment.course.org], ) self.assertEqual(mock_schedule_send.apply_async.call_count, schedule_count) self.assertFalse(mock_ace.send.called)
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)
def test_no_course_overview(self, mock_schedule_send): schedule = ScheduleFactory.create( start=datetime.datetime(2017, 8, 1, 20, 34, 30, tzinfo=pytz.UTC), ) schedule.enrollment.course_id = CourseKey.from_string('edX/toy/Not_2012_Fall') schedule.enrollment.save() test_time_str = serialize(datetime.datetime(2017, 8, 1, 20, tzinfo=pytz.UTC)) with self.assertNumQueries(2): tasks.recurring_nudge_schedule_hour( self.site_config.site.id, 3, test_time_str, [schedule.enrollment.course.org], ) # There is no database constraint that enforces that enrollment.course_id points # to a valid CourseOverview object. However, in that case, schedules isn't going # to attempt to address it, and will instead simply skip those users. # This happens 'transparently' because django generates an inner-join between # enrollment and course_overview, and thus will skip any rows where course_overview # is null. self.assertEqual(mock_schedule_send.apply_async.call_count, 0)