Beispiel #1
0
    def test_courses_with_honor_seats(self):
        honor_seat_type = factories.SeatTypeFactory.honor()
        honor_track = factories.TrackFactory(seat_type=honor_seat_type)
        honor_run_type = factories.CourseRunTypeFactory(
            name='Honor Only', slug=CourseRunType.HONOR, tracks=[honor_track])
        # Tests that Honor Only will not match with Verified and Honor despite being a subset of that CourseRunType
        honor_run = factories.CourseRunFactory(course=self.course,
                                               type=self.empty_run_type,
                                               key='course-v1:Org1+Course1+H')
        factories.SeatFactory(course_run=honor_run, type=honor_seat_type)

        vh_run_type = factories.CourseRunTypeFactory(
            name='Verified and Honor',
            slug=CourseRunType.VERIFIED_HONOR,
            tracks=[honor_track, self.verified_track])
        vh_run = factories.CourseRunFactory(course=self.course,
                                            type=self.empty_run_type,
                                            key='course-v1:Org1+Course1+VH')
        factories.SeatFactory(course_run=vh_run, type=honor_seat_type)
        factories.SeatFactory(course_run=vh_run, type=self.verified_seat_type)

        allow_for = [
            CourseType.VERIFIED_AUDIT + ':' + CourseRunType.HONOR,
            CourseType.VERIFIED_AUDIT + ':' + CourseRunType.VERIFIED_HONOR
        ]
        self.run_command(allow_for=allow_for)
        self.assertEqual(self.course.type, self.va_course_type)
        honor_run.refresh_from_db()
        self.assertEqual(honor_run.type, honor_run_type)
        vh_run.refresh_from_db()
        self.assertEqual(vh_run.type, vh_run_type)
Beispiel #2
0
    def test_price_ranges_multiple_course(self):
        """ Verifies the price_range property of a program with multiple courses """
        currency = Currency.objects.get(code='USD')
        test_price = 100
        for course_run in self.course_runs:
            factories.SeatFactory(type='audit',
                                  currency=currency,
                                  course_run=course_run,
                                  price=0)
            factories.SeatFactory(type='verified',
                                  currency=currency,
                                  course_run=course_run,
                                  price=test_price)
            test_price += 100

        applicable_seat_types = SeatType.objects.filter(slug__in=['verified'])
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=applicable_seat_types)

        self.program.type = program_type

        expected_price_ranges = [{
            'currency': 'USD',
            'min': Decimal(100),
            'max': Decimal(300),
            'total': Decimal(600)
        }]
        self.assertEqual(self.program.price_ranges, expected_price_ranges)
Beispiel #3
0
    def test_one_click_purchase_eligible_with_unpublished_runs(self):
        """ Verify that program with unpublished course runs is one click purchase eligible. """

        verified_seat_type, __ = SeatType.objects.get_or_create(
            name=Seat.VERIFIED)
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=[verified_seat_type])
        published_course_run = factories.CourseRunFactory(
            end=None, enrollment_end=None, status=CourseRunStatus.Published)
        unpublished_course_run = factories.CourseRunFactory(
            end=None,
            enrollment_end=None,
            status=CourseRunStatus.Unpublished,
            course=published_course_run.course)
        factories.SeatFactory(course_run=published_course_run,
                              type=Seat.VERIFIED,
                              upgrade_deadline=None)
        factories.SeatFactory(course_run=unpublished_course_run,
                              type=Seat.VERIFIED,
                              upgrade_deadline=None)
        program = factories.ProgramFactory(
            courses=[published_course_run.course],
            one_click_purchase_enabled=True,
            type=program_type,
        )
        self.assertTrue(program.is_program_eligible_for_one_click_purchase)
Beispiel #4
0
    def test_enrollable_seats(self):
        """ Verify the expected seats get returned. """
        course_run = factories.CourseRunFactory(start=None,
                                                end=None,
                                                enrollment_start=None,
                                                enrollment_end=None)
        verified_seat = factories.SeatFactory(course_run=course_run,
                                              type=Seat.VERIFIED,
                                              upgrade_deadline=None)
        professional_seat = factories.SeatFactory(course_run=course_run,
                                                  type=Seat.PROFESSIONAL,
                                                  upgrade_deadline=None)
        factories.SeatFactory(course_run=course_run,
                              type=Seat.HONOR,
                              upgrade_deadline=None)
        self.assertEqual(
            course_run.enrollable_seats([Seat.VERIFIED, Seat.PROFESSIONAL]),
            [verified_seat, professional_seat])

        # The method should not care about the course run's start date.
        course_run.start = datetime.datetime.utcnow() + datetime.timedelta(
            days=1)
        course_run.save()
        self.assertEqual(
            course_run.enrollable_seats([Seat.VERIFIED, Seat.PROFESSIONAL]),
            [verified_seat, professional_seat])
Beispiel #5
0
    def create_program_with_seats(self):
        currency = Currency.objects.get(code='USD')

        course_run = factories.CourseRunFactory()
        course_run.course.canonical_course_run = course_run
        course_run.course.save()
        factories.SeatFactory(type='audit',
                              currency=currency,
                              course_run=course_run,
                              price=0)
        factories.SeatFactory(type='credit',
                              currency=currency,
                              course_run=course_run,
                              price=600)
        factories.SeatFactory(type='verified',
                              currency=currency,
                              course_run=course_run,
                              price=100)

        applicable_seat_types = SeatType.objects.filter(
            slug__in=['credit', 'verified'])
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=applicable_seat_types)

        return factories.ProgramFactory(type=program_type,
                                        courses=[course_run.course])
Beispiel #6
0
    def create_program_with_multiple_course_runs(self, set_all_dates=True):
        currency = Currency.objects.get(code='USD')
        single_course_course_runs = factories.CourseRunFactory.create_batch(3)
        course = factories.CourseFactory()
        course_runs_same_course = factories.CourseRunFactory.create_batch(
            3, course=course)
        for course_run in single_course_course_runs:
            factories.SeatFactory(type='audit',
                                  currency=currency,
                                  course_run=course_run,
                                  price=0)
            factories.SeatFactory(type='verified',
                                  currency=currency,
                                  course_run=course_run,
                                  price=10)
            course_run.course.canonical_course_run = course_run
            course_run.course.save()

        day_separation = 1
        now = datetime.datetime.utcnow()

        for course_run in course_runs_same_course:
            if set_all_dates or day_separation < 2:
                date_delta = datetime.timedelta(days=day_separation)
                course_run.enrollment_start = now - date_delta
                course_run.end = now + datetime.timedelta(weeks=day_separation)
            else:
                course_run.enrollment_start = None
                course_run.end = None
            course_run.save()
            factories.SeatFactory(type='audit',
                                  currency=currency,
                                  course_run=course_run,
                                  price=0)
            factories.SeatFactory(type='verified',
                                  currency=currency,
                                  course_run=course_run,
                                  price=(day_separation * 100))
            day_separation += 1
        course.canonical_course_run = course_runs_same_course[2]
        course.save()
        applicable_seat_types = SeatType.objects.filter(slug__in=['verified'])
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=applicable_seat_types)

        program_courses = [
            course_run.course for course_run in single_course_course_runs
        ]
        program_courses.append(course)

        return factories.ProgramFactory(type=program_type,
                                        courses=program_courses)
Beispiel #7
0
 def test_queryset_method_returns_eligible_programs(self):
     """ Verify that one click purchase eligible programs pass the filter. """
     verified_seat_type, __ = SeatType.objects.get_or_create(
         name=Seat.VERIFIED)
     program_type = factories.ProgramTypeFactory(
         applicable_seat_types=[verified_seat_type])
     program_filter = ProgramEligibilityFilter(None,
                                               {self.parameter_name: 1},
                                               None, None)
     course_run = factories.CourseRunFactory(
         end=None,
         enrollment_end=None,
     )
     factories.SeatFactory(course_run=course_run,
                           type='verified',
                           upgrade_deadline=None)
     one_click_purchase_eligible_program = factories.ProgramFactory(
         type=program_type,
         courses=[course_run.course],
         one_click_purchase_enabled=True,
     )
     with self.assertNumQueries(12):
         self.assertEqual(
             list(program_filter.queryset({}, Program.objects.all())),
             [one_click_purchase_eligible_program])
Beispiel #8
0
    def test_one_click_purchase_eligible(self):
        """ Verify that program is one click purchase eligible. """
        verified_seat_type, __ = SeatType.objects.get_or_create(
            name=Seat.VERIFIED)
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=[verified_seat_type])

        # Program has one_click_purchase_enabled set to True,
        # all courses have one course run, all course runs have
        # verified seat types
        courses = []
        for __ in range(3):
            course_run = factories.CourseRunFactory(end=None,
                                                    enrollment_end=None)
            factories.SeatFactory(course_run=course_run,
                                  type=Seat.VERIFIED,
                                  upgrade_deadline=None)
            courses.append(course_run.course)
        program = factories.ProgramFactory(
            courses=courses,
            one_click_purchase_enabled=True,
            type=program_type,
        )
        self.assertTrue(program.is_program_eligible_for_one_click_purchase)

        # Program has one_click_purchase_enabled set to True,
        # course has all course runs excluded except one which
        # has verified seat type
        course_run = factories.CourseRunFactory(end=None, enrollment_end=None)
        factories.SeatFactory(course_run=course_run,
                              type=Seat.VERIFIED,
                              upgrade_deadline=None)
        course = course_run.course
        excluded_course_runs = [
            factories.CourseRunFactory(course=course),
            factories.CourseRunFactory(course=course)
        ]
        program = factories.ProgramFactory(
            courses=[course],
            excluded_course_runs=excluded_course_runs,
            one_click_purchase_enabled=True,
            type=program_type,
        )
        self.assertTrue(program.is_program_eligible_for_one_click_purchase)
    def setUp(self):
        super().setUp()

        # Disable marketing site password just to save us from having to mock the responses
        self.partner = factories.PartnerFactory(marketing_site_api_password=None)

        # Fill out a bunch of types and modes. Exact mode parameters don't matter, just the resulting seat types.
        self.audit_seat_type = factories.SeatTypeFactory.audit()
        self.verified_seat_type = factories.SeatTypeFactory.verified()
        self.audit_mode = Mode.objects.get(slug=Seat.AUDIT)
        self.verified_mode = Mode.objects.get(slug=Seat.VERIFIED)
        self.audit_track = Track.objects.get(seat_type=self.audit_seat_type, mode=self.audit_mode)
        self.verified_track = Track.objects.get(seat_type=self.verified_seat_type, mode=self.verified_mode)
        self.empty_run_type = CourseRunType.objects.get(slug=CourseRunType.EMPTY)
        self.audit_run_type = CourseRunType.objects.get(slug=CourseRunType.AUDIT)
        self.va_run_type = CourseRunType.objects.get(slug=CourseRunType.VERIFIED_AUDIT)
        self.empty_course_type = CourseType.objects.get(slug=CourseType.EMPTY)
        self.va_course_type = CourseType.objects.get(slug=CourseType.VERIFIED_AUDIT)
        self.audit_course_type = CourseType.objects.get(slug=CourseType.AUDIT)

        # Now create some courses and orgs that will be found to match the above, in the simple happy path case.
        self.org = factories.OrganizationFactory(partner=self.partner, key='Org1')
        self.course = factories.CourseFactory(partner=self.partner, authoring_organizations=[self.org],
                                              type=self.empty_course_type,
                                              key=f'{self.org.key}+Course1')
        self.entitlement = factories.CourseEntitlementFactory(partner=self.partner, course=self.course,
                                                              mode=self.verified_seat_type)
        self.audit_run = factories.CourseRunFactory(course=self.course, type=self.empty_run_type,
                                                    key='course-v1:Org1+Course1+A')
        self.audit_seat = factories.SeatFactory(course_run=self.audit_run, type=self.audit_seat_type)
        self.verified_run = factories.CourseRunFactory(course=self.course, type=self.empty_run_type,
                                                       key='course-v1:Org1+Course1+V')
        self.verified_seat = factories.SeatFactory(course_run=self.verified_run, type=self.verified_seat_type)
        self.verified_audit_seat = factories.SeatFactory(course_run=self.verified_run, type=self.audit_seat_type)

        # Create parallel obj / course for argument testing
        self.org2 = factories.OrganizationFactory(partner=self.partner, key='Org2')
        self.org3 = factories.OrganizationFactory(partner=self.partner, key='Org3')
        self.course2 = factories.CourseFactory(partner=self.partner, authoring_organizations=[self.org2, self.org3],
                                               type=self.empty_course_type,
                                               key=f'{self.org2.key}+Course1')
        self.c2_audit_run = factories.CourseRunFactory(course=self.course2, type=self.empty_run_type)
        self.c2_audit_seat = factories.SeatFactory(course_run=self.c2_audit_run, type=self.audit_seat_type)
    def test_courses_with_honor_seats(self):
        honor_seat_type = factories.SeatTypeFactory.honor()
        honor_run_type = CourseRunType.objects.get(slug=CourseRunType.HONOR)
        # Tests that Honor Only will not match with Verified and Honor despite being a subset of that CourseRunType
        honor_run = factories.CourseRunFactory(course=self.course, type=self.empty_run_type,
                                               key='course-v1:Org1+Course1+H')
        factories.SeatFactory(course_run=honor_run, type=honor_seat_type)

        vh_run_type = CourseRunType.objects.get(slug=CourseRunType.VERIFIED_HONOR)
        vh_run = factories.CourseRunFactory(course=self.course, type=self.empty_run_type,
                                            key='course-v1:Org1+Course1+VH')
        factories.SeatFactory(course_run=vh_run, type=honor_seat_type)
        factories.SeatFactory(course_run=vh_run, type=self.verified_seat_type)

        allow_for = [
            CourseType.VERIFIED_AUDIT + ':' + CourseRunType.HONOR,
            CourseType.VERIFIED_AUDIT + ':' + CourseRunType.VERIFIED_HONOR
        ]
        self.run_command(allow_for=allow_for)
        assert self.course.type == self.va_course_type
        honor_run.refresh_from_db()
        assert honor_run.type == honor_run_type
        vh_run.refresh_from_db()
        assert vh_run.type == vh_run_type
 def test_queryset_method_returns_all_programs(self):
     """ Verify that all programs pass the filter. """
     verified_seat_type = factories.SeatTypeFactory.verified()
     program_type = factories.ProgramTypeFactory(applicable_seat_types=[verified_seat_type])
     program_filter = ProgramEligibilityFilter(None, {}, None, None)
     course_run = factories.CourseRunFactory()
     factories.SeatFactory(course_run=course_run, type=verified_seat_type, upgrade_deadline=None)
     one_click_purchase_eligible_program = factories.ProgramFactory(
         type=program_type,
         courses=[course_run.course],
         one_click_purchase_enabled=True
     )
     one_click_purchase_ineligible_program = factories.ProgramFactory(courses=[course_run.course])
     with self.assertNumQueries(1):
         assert list(program_filter.queryset({}, Program.objects.all())) == \
                [one_click_purchase_eligible_program, one_click_purchase_ineligible_program]
Beispiel #12
0
    def test_canonical_course_seats(self):
        """ Test canonical course seats returns only canonical course run's applicable seats """
        currency = Currency.objects.get(code='USD')

        course = factories.CourseFactory()
        course_runs_same_course = factories.CourseRunFactory.create_batch(
            3, course=course)
        for course_run in course_runs_same_course:
            factories.SeatFactory(type='verified',
                                  currency=currency,
                                  course_run=course_run,
                                  price=100)
        course.canonical_course_run = course_runs_same_course[0]
        course.save()

        applicable_seat_types = SeatType.objects.filter(slug__in=['verified'])
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=applicable_seat_types)

        program = factories.ProgramFactory(type=program_type, courses=[course])

        self.assertEqual(set(course.canonical_course_run.seats.all()),
                         set(program.canonical_seats))
Beispiel #13
0
 def assert_one_click_purchase_ineligible_program(
         self,
         end=None,
         enrollment_start=None,
         enrollment_end=None,
         seat_type=Seat.VERIFIED,
         upgrade_deadline=None,
         one_click_purchase_enabled=True,
         excluded_course_runs=None,
         program_type=None):
     course_run = factories.CourseRunFactory(
         end=end,
         enrollment_start=enrollment_start,
         enrollment_end=enrollment_end)
     factories.SeatFactory(course_run=course_run,
                           type=seat_type,
                           upgrade_deadline=upgrade_deadline)
     program = factories.ProgramFactory(
         courses=[course_run.course],
         excluded_course_runs=excluded_course_runs,
         one_click_purchase_enabled=one_click_purchase_enabled,
         type=program_type,
     )
     self.assertFalse(program.is_program_eligible_for_one_click_purchase)
Beispiel #14
0
 def test_type(self, seat_types, expected_course_run_type):
     """ Verify the property returns the appropriate type string for the CourseRun. """
     for seat_type in seat_types:
         factories.SeatFactory(course_run=self.course_run, type=seat_type)
     self.assertEqual(self.course_run.type, expected_course_run_type)
Beispiel #15
0
    def test_one_click_purchase_ineligible(self):
        """ Verify that program is one click purchase ineligible. """
        yesterday = datetime.datetime.utcnow() - datetime.timedelta(days=1)
        tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1)
        verified_seat_type, __ = SeatType.objects.get_or_create(
            name=Seat.VERIFIED)
        program_type = factories.ProgramTypeFactory(
            applicable_seat_types=[verified_seat_type])

        # Program has one_click_purchase_enabled set to False and
        # every course has one course run
        self.assert_one_click_purchase_ineligible_program(
            one_click_purchase_enabled=False,
            program_type=program_type,
        )

        # Program has one_click_purchase_enabled set to True and
        # one course has two course runs
        course_run = factories.CourseRunFactory(end=None, enrollment_end=None)
        factories.CourseRunFactory(end=None,
                                   enrollment_end=None,
                                   course=course_run.course)
        factories.SeatFactory(course_run=course_run,
                              type='verified',
                              upgrade_deadline=None)
        program = factories.ProgramFactory(
            courses=[course_run.course],
            one_click_purchase_enabled=True,
            type=program_type,
        )
        self.assertFalse(program.is_program_eligible_for_one_click_purchase)

        # Program has one_click_purchase_enabled set to True and
        # one course with one course run excluded from the program
        course_run = factories.CourseRunFactory(end=None, enrollment_end=None)
        factories.SeatFactory(course_run=course_run,
                              type='verified',
                              upgrade_deadline=None)
        program = factories.ProgramFactory(
            courses=[course_run.course],
            one_click_purchase_enabled=True,
            excluded_course_runs=[course_run],
            type=program_type,
        )
        self.assertFalse(program.is_program_eligible_for_one_click_purchase)

        # Program has one_click_purchase_enabled set to True, one course
        # with one course run, course run end date passed
        self.assert_one_click_purchase_ineligible_program(
            end=yesterday,
            program_type=program_type,
        )

        # Program has one_click_purchase_enabled set to True, one course
        # with one course run, course run enrollment start date not passed
        self.assert_one_click_purchase_ineligible_program(
            enrollment_start=tomorrow,
            program_type=program_type,
        )

        # Program has one_click_purchase_enabled set to True, one course
        # with one course run, course run enrollment end date passed
        self.assert_one_click_purchase_ineligible_program(
            enrollment_end=yesterday,
            program_type=program_type,
        )

        # Program has one_click_purchase_enabled set to True, one course
        # with one course run, seat upgrade deadline passed
        self.assert_one_click_purchase_ineligible_program(
            upgrade_deadline=yesterday,
            program_type=program_type,
        )

        # Program has one_click_purchase_enabled set to True, one course
        # with one course run, seat type is not purchasable
        self.assert_one_click_purchase_ineligible_program(
            seat_type='incorrect',
            program_type=program_type,
        )