diff --git a/openedx/core/djangoapps/schedules/management/commands/tests/test_send_recurring_nudge.py b/openedx/core/djangoapps/schedules/management/commands/tests/test_send_recurring_nudge.py index b3bfa73175..acab8d03f1 100644 --- a/openedx/core/djangoapps/schedules/management/commands/tests/test_send_recurring_nudge.py +++ b/openedx/core/djangoapps/schedules/management/commands/tests/test_send_recurring_nudge.py @@ -1,30 +1,20 @@ -import datetime from unittest import skipUnless -import ddt from django.conf import settings -from edx_ace.utils.date import serialize -from edx_ace.message import Message -from mock import patch -from opaque_keys.edx.locator import CourseLocator -import pytz -from course_modes.models import CourseMode -from course_modes.tests.factories import CourseModeFactory -from courseware.models import DynamicUpgradeDeadlineConfiguration from openedx.core.djangoapps.schedules import tasks from openedx.core.djangoapps.schedules.management.commands import send_recurring_nudge as nudge from openedx.core.djangoapps.schedules.management.commands.tests.send_email_base import ScheduleSendEmailTestBase -from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory +from openedx.core.djangoapps.schedules.management.commands.tests.upsell_base import ScheduleUpsellTestMixin from openedx.core.djangolib.testing.utils import skip_unless_lms -from student.tests.factories import UserFactory -@ddt.ddt @skip_unless_lms -@skipUnless('openedx.core.djangoapps.schedules.apps.SchedulesConfig' in settings.INSTALLED_APPS, - "Can't test schedules if the app isn't installed") -class TestSendRecurringNudge(ScheduleSendEmailTestBase): +@skipUnless( + 'openedx.core.djangoapps.schedules.apps.SchedulesConfig' in settings.INSTALLED_APPS, + "Can't test schedules if the app isn't installed", +) +class TestSendRecurringNudge(ScheduleUpsellTestMixin, ScheduleSendEmailTestBase): __test__ = True # pylint: disable=protected-access @@ -34,132 +24,3 @@ class TestSendRecurringNudge(ScheduleSendEmailTestBase): deliver_config = 'deliver_recurring_nudge' enqueue_config = 'enqueue_recurring_nudge' expected_offsets = (-3, -10) - - def test_user_in_course_with_verified_coursemode_receives_upsell(self): - user = UserFactory.create() - course_id = CourseLocator('edX', 'toy', 'Course1') - - first_day_of_schedule = datetime.datetime.now(pytz.UTC) - verification_deadline = first_day_of_schedule + datetime.timedelta(days=21) - target_day = first_day_of_schedule - target_hour_as_string = serialize(target_day) - nudge_day = 3 - - schedule = ScheduleFactory.create(start=first_day_of_schedule, - enrollment__user=user, - enrollment__course__id=course_id) - schedule.enrollment.course.self_paced = True - schedule.enrollment.course.save() - - CourseModeFactory( - course_id=course_id, - mode_slug=CourseMode.VERIFIED, - expiration_datetime=verification_deadline - ) - schedule.upgrade_deadline = verification_deadline - - bin_task_parameters = [ - target_hour_as_string, - nudge_day, - user, - schedule.enrollment.course.org - ] - sent_messages = self._stub_sender_and_collect_sent_messages(bin_task=self.tested_task, - stubbed_send_task=patch.object(self.tested_task, 'async_send_task'), - bin_task_params=bin_task_parameters) - - self.assertEqual(len(sent_messages), 1) - - message_attributes = sent_messages[0][1] - self.assertTrue(self._contains_upsell_attribute(message_attributes)) - - def test_no_upsell_button_when_DUDConfiguration_is_off(self): - DynamicUpgradeDeadlineConfiguration.objects.create(enabled=False) - - user = UserFactory.create() - course_id = CourseLocator('edX', 'toy', 'Course1') - - first_day_of_schedule = datetime.datetime.now(pytz.UTC) - target_day = first_day_of_schedule - target_hour_as_string = serialize(target_day) - nudge_day = 3 - - schedule = ScheduleFactory.create(start=first_day_of_schedule, - enrollment__user=user, - enrollment__course__id=course_id) - schedule.enrollment.course.self_paced = True - schedule.enrollment.course.save() - - bin_task_parameters = [ - target_hour_as_string, - nudge_day, - user, - schedule.enrollment.course.org - ] - sent_messages = self._stub_sender_and_collect_sent_messages(bin_task=self.tested_task, - stubbed_send_task=patch.object(self.tested_task, 'async_send_task'), - bin_task_params=bin_task_parameters) - - self.assertEqual(len(sent_messages), 1) - - message_attributes = sent_messages[0][1] - self.assertFalse(self._contains_upsell_attribute(message_attributes)) - - def test_user_with_no_upgrade_deadline_is_not_upsold(self): - user = UserFactory.create() - course_id = CourseLocator('edX', 'toy', 'Course1') - - first_day_of_schedule = datetime.datetime.now(pytz.UTC) - target_day = first_day_of_schedule - target_hour_as_string = serialize(target_day) - nudge_day = 3 - - schedule = ScheduleFactory.create(start=first_day_of_schedule, - upgrade_deadline=None, - enrollment__user=user, - enrollment__course__id=course_id) - schedule.enrollment.course.self_paced = True - schedule.enrollment.course.save() - - verification_deadline = first_day_of_schedule + datetime.timedelta(days=21) - CourseModeFactory( - course_id=course_id, - mode_slug=CourseMode.VERIFIED, - expiration_datetime=verification_deadline - ) - schedule.upgrade_deadline = verification_deadline - - bin_task_parameters = [ - target_hour_as_string, - nudge_day, - user, - schedule.enrollment.course.org - ] - sent_messages = self._stub_sender_and_collect_sent_messages(bin_task=self.tested_task, - stubbed_send_task=patch.object(self.tested_task, 'async_send_task'), - bin_task_params=bin_task_parameters) - - self.assertEqual(len(sent_messages), 1) - - message_attributes = sent_messages[0][1] - self.assertFalse(self._contains_upsell_attribute(message_attributes)) - - def _stub_sender_and_collect_sent_messages(self, bin_task, stubbed_send_task, bin_task_params): - sent_messages = [] - - with self.settings(TEMPLATES=self._get_template_overrides()), stubbed_send_task as mock_schedule_send: - - mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args) - - bin_task.apply(kwargs=dict( - site_id=self.site_config.site.id, - target_day_str=bin_task_params[0], - day_offset=bin_task_params[1], - bin_num=self._calculate_bin_for_user(bin_task_params[2]), - )) - - return sent_messages - - def _contains_upsell_attribute(self, msg_attr): - msg = Message.from_string(msg_attr) - return msg.context["show_upsell"] diff --git a/openedx/core/djangoapps/schedules/management/commands/tests/upsell_base.py b/openedx/core/djangoapps/schedules/management/commands/tests/upsell_base.py new file mode 100644 index 0000000000..725c39ade9 --- /dev/null +++ b/openedx/core/djangoapps/schedules/management/commands/tests/upsell_base.py @@ -0,0 +1,58 @@ +from collections import namedtuple +import datetime +import ddt +from mock import patch +import itertools + +from edx_ace.utils.date import serialize +from edx_ace.message import Message + +from courseware.models import DynamicUpgradeDeadlineConfiguration +from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory + + +@ddt.ddt +class ScheduleUpsellTestMixin(object): + UpsellTestCase = namedtuple('UpsellTestCase', 'set_deadline, deadline_offset, expect_upsell') + + @ddt.data( + *itertools.product( + (True, False), # enable DynamicUpgradeDeadlineConfiguration + ( + UpsellTestCase(set_deadline=False, deadline_offset=None, expect_upsell=False), # no deadline + UpsellTestCase(set_deadline=True, deadline_offset=-7, expect_upsell=False), # deadline expired + UpsellTestCase(set_deadline=True, deadline_offset=7, expect_upsell=True), # deadline in future + ) + ) + ) + @ddt.unpack + def test_upsell(self, enable_config, testcase): + DynamicUpgradeDeadlineConfiguration.objects.create(enabled=enable_config) + + current_day, offset, target_day = self._get_dates() + upgrade_deadline = None + if testcase.set_deadline: + upgrade_deadline = current_day + datetime.timedelta(days=testcase.deadline_offset) + + schedule = ScheduleFactory.create( + start=target_day, + upgrade_deadline=upgrade_deadline, + enrollment__course__self_paced=True, + ) + + sent_messages = [] + with patch.object(self.tested_task, 'async_send_task') as mock_schedule_send: + mock_schedule_send.apply_async = lambda args, *_a, **_kw: sent_messages.append(args[1]) + self.tested_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(schedule.enrollment.user), + )) + self.assertEqual(len(sent_messages), 1) + + found_upsell = self._contains_upsell(sent_messages[0]) + expect_upsell = enable_config and testcase.expect_upsell + self.assertEqual(found_upsell, expect_upsell) + + def _contains_upsell(self, message_str): + message = Message.from_string(message_str) + return message.context["show_upsell"]