Beispiel #1
0
    def setUpClass(cls):
        super(TestProgramDetails, cls).setUpClass()

        modulestore_course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=unicode(modulestore_course.id))  # pylint: disable=no-member
        course = CourseFactory(course_runs=[course_run])

        cls.data = ProgramFactory(uuid=cls.program_uuid, courses=[course])
Beispiel #2
0
    def test_shared_enrollment_engagement(self, mock_get_programs):
        """
        Verify that correct programs are returned when the user is enrolled in a
        single course run appearing in multiple programs.
        """
        shared_course_run_key, solo_course_run_key = (generate_course_run_key() for __ in range(2))

        batch = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=shared_course_run_key),
                    ]),
                ]
            )
            for __ in range(2)
        ]

        joint_programs = sorted(batch, key=lambda program: program['title'])
        data = joint_programs + [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=solo_course_run_key),
                    ]),
                ]
            ),
            ProgramFactory(),
        ]

        mock_get_programs.return_value = data

        # Enrollment for the shared course run created last (most recently).
        self._create_enrollments(solo_course_run_key, shared_course_run_key)
        meter = ProgramProgressMeter(self.user)

        self._attach_detail_url(data)
        programs = data[:3]
        self.assertEqual(meter.engaged_programs, programs)
        self._assert_progress(
            meter,
            *(ProgressFactory(uuid=program['uuid'], in_progress=1) for program in programs)
        )
        self.assertEqual(meter.completed_programs, [])
Beispiel #3
0
    def test_mutiple_program_engagement(self, mock_get_programs):
        """
        Verify that correct programs are returned in the correct order when the
        user is enrolled in course runs appearing in programs.
        """
        newer_course_run_key, older_course_run_key = (generate_course_run_key() for __ in range(2))
        data = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=newer_course_run_key),
                    ]),
                ]
            ),
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=older_course_run_key),
                    ]),
                ]
            ),
            ProgramFactory(),
        ]
        mock_get_programs.return_value = data

        # The creation time of the enrollments matters to the test. We want
        # the first_course_run_key to represent the newest enrollment.
        self._create_enrollments(older_course_run_key, newer_course_run_key)
        meter = ProgramProgressMeter(self.site, self.user)

        self._attach_detail_url(data)
        programs = data[:2]
        self.assertEqual(meter.engaged_programs, programs)

        grades = {
            newer_course_run_key: 0.0,
            older_course_run_key: 0.0,
        }
        self._assert_progress(
            meter,
            *(ProgressFactory(uuid=program['uuid'], in_progress=1, grades=grades) for program in programs)
        )
        self.assertEqual(meter.completed_programs, [])
Beispiel #4
0
    def setUp(self):
        super(TestProgramDataExtender, self).setUp()

        self.course = ModuleStoreCourseFactory()
        self.course.start = datetime.datetime.now(utc) - datetime.timedelta(days=1)
        self.course.end = datetime.datetime.now(utc) + datetime.timedelta(days=1)
        self.course = self.update_course(self.course, self.user.id)

        self.course_run = CourseRunFactory(key=unicode(self.course.id))
        self.catalog_course = CourseFactory(course_runs=[self.course_run])
        self.program = ProgramFactory(courses=[self.catalog_course])
Beispiel #5
0
    def test_get_course_runs_by_course(self, mock_get_edx_api_data):
        """
        Test retrievals of run from a Course.
        """
        catalog_course_runs = CourseRunFactory.create_batch(10)
        catalog_course = CourseFactory(course_runs=catalog_course_runs)
        mock_get_edx_api_data.return_value = catalog_course

        data = get_course_runs_for_course(course_uuid=str(catalog_course['uuid']))
        assert mock_get_edx_api_data.called
        assert data == catalog_course_runs
Beispiel #6
0
    def test_get_course_owners_by_course(self, mock_get_edx_api_data):
        """
        Test retrieval of course runs.
        """
        catalog_course_runs = CourseRunFactory.create_batch(10)
        catalog_course = CourseFactory(course_runs=catalog_course_runs)
        mock_get_edx_api_data.return_value = catalog_course

        data = get_owners_for_course(course_uuid=str(catalog_course['uuid']))
        self.assertTrue(mock_get_edx_api_data.called)
        self.assertEqual(data, catalog_course['owners'])
Beispiel #7
0
    def setUpClass(cls):
        super(TestProgramListing, cls).setUpClass()

        cls.course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=six.text_type(cls.course.id))
        course = CourseFactory(course_runs=[course_run])

        cls.first_program = ProgramFactory(courses=[course])
        cls.second_program = ProgramFactory(courses=[course])

        cls.data = sorted([cls.first_program, cls.second_program], key=cls.program_sort_key)
    def setUpClass(cls):
        super().setUpClass()

        cls.course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=str(cls.course.id))  # lint-amnesty, pylint: disable=no-member
        course = CourseFactory(course_runs=[course_run])

        cls.first_program = ProgramFactory(courses=[course])
        cls.second_program = ProgramFactory(courses=[course])

        cls.data = sorted([cls.first_program, cls.second_program], key=cls.program_sort_key)
Beispiel #9
0
    def test_multiple_published_course_runs(self):
        """
        Learner should not be eligible for one click purchase if:
            - program has a course with more than one published course run
        """
        course_run_1 = CourseRunFactory(
            key=str(ModuleStoreCourseFactory().id),
            status='published'
        )
        course_run_2 = CourseRunFactory(
            key=str(ModuleStoreCourseFactory().id),
            status='published'
        )
        course = CourseFactory(course_runs=[course_run_1, course_run_2])
        program = ProgramFactory(
            courses=[
                CourseFactory(course_runs=[
                    CourseRunFactory(
                        key=str(ModuleStoreCourseFactory().id),
                        status='published'
                    )
                ]),
                course,
                CourseFactory(course_runs=[
                    CourseRunFactory(
                        key=str(ModuleStoreCourseFactory().id),
                        status='published'
                    )
                ])
            ],
            is_program_eligible_for_one_click_purchase=True,
            applicable_seat_types=['verified']
        )
        data = ProgramDataExtender(program, self.user).extend()

        self.assertFalse(data['is_learner_eligible_for_one_click_purchase'])

        course_run_2['status'] = 'unpublished'
        data = ProgramDataExtender(program, self.user).extend()

        self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
Beispiel #10
0
    def setUpClass(cls):
        super(TestProgramDetails, cls).setUpClass()

        modulestore_course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=unicode(modulestore_course.id))  # pylint: disable=no-member
        course = CourseFactory(course_runs=[course_run])

        cls.program_data = ProgramFactory(uuid=cls.program_uuid, courses=[course])
        cls.pathway_data = CreditPathwayFactory()
        cls.program_data['pathway_ids'] = [cls.pathway_data['id']]
        cls.pathway_data['program_uuids'] = [cls.program_data['uuid']]
        del cls.pathway_data['programs']
Beispiel #11
0
    def setUpClass(cls):
        super().setUpClass()

        modulestore_course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=str(modulestore_course.id))  # lint-amnesty, pylint: disable=no-member
        course = CourseFactory(course_runs=[course_run])

        cls.program_data = ProgramFactory(uuid=cls.program_uuid, courses=[course])
        cls.pathway_data = PathwayFactory()
        cls.program_data['pathway_ids'] = [cls.pathway_data['id']]
        cls.pathway_data['program_uuids'] = [cls.program_data['uuid']]
        del cls.pathway_data['programs']  # lint-amnesty, pylint: disable=unsupported-delete-operation
Beispiel #12
0
    def setUpClass(cls):
        super(TestProgramDetails, cls).setUpClass()

        modulestore_course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=six.text_type(modulestore_course.id))
        course = CourseFactory(course_runs=[course_run])

        cls.program_data = ProgramFactory(uuid=cls.program_uuid, courses=[course])
        cls.pathway_data = PathwayFactory()
        cls.program_data['pathway_ids'] = [cls.pathway_data['id']]
        cls.pathway_data['program_uuids'] = [cls.program_data['uuid']]
        del cls.pathway_data['programs']
Beispiel #13
0
 def _get_programs_data(self, hierarchy_type):
     """
     Generate a mock response for get_programs() with the given type of
     course hierarchy.  Dramatically simplifies (and makes consistent
     between test runs) the ddt-generated test_flatten methods.
     """
     if hierarchy_type == self.SEPARATE_PROGRAMS:
         return [
             ProgramFactory(courses=[
                 CourseFactory(course_runs=[
                     CourseRunFactory(key=self.course_run_key),
                 ]),
             ]),
             ProgramFactory(courses=[
                 CourseFactory(course_runs=[
                     CourseRunFactory(key=self.alternate_course_run_key),
                 ]),
             ]),
         ]
     elif hierarchy_type == self.SEPARATE_COURSES:
         return [
             ProgramFactory(courses=[
                 CourseFactory(course_runs=[
                     CourseRunFactory(key=self.course_run_key),
                 ]),
                 CourseFactory(course_runs=[
                     CourseRunFactory(key=self.alternate_course_run_key),
                 ]),
             ]),
         ]
     else:  # SAME_COURSE
         return [
             ProgramFactory(courses=[
                 CourseFactory(course_runs=[
                     CourseRunFactory(key=self.course_run_key),
                     CourseRunFactory(key=self.alternate_course_run_key),
                 ]),
             ]),
         ]
Beispiel #14
0
    def test_course_pricing_when_all_course_runs_have_no_seats(self):
        # Create three seatless course runs and add them to the program
        course_runs = []
        for __ in range(3):
            course = ModuleStoreCourseFactory()
            course = self.update_course(course, self.user.id)
            course_runs.append(CourseRunFactory(key=unicode(course.id), seats=[]))
        program = ProgramFactory(courses=[CourseFactory(course_runs=course_runs)])

        data = ProgramMarketingDataExtender(program, self.user).extend()

        self.assertEqual(data['number_of_courses'], len(program['courses']))
        self.assertEqual(data['full_program_price'], 0.0)
        self.assertEqual(data['avg_price_per_course'], 0.0)
Beispiel #15
0
 def test_credit_course_counted_complete_for_verified(self, mock_completed_course_runs, mock_get_programs):
     """
     Verify that 'credit' course certificate type are treated as if they were
     "verified" when checking for course completion status.
     """
     course_run_key = generate_course_run_key()
     course = CourseFactory(course_runs=[
         CourseRunFactory(key=course_run_key, type='credit'),
     ])
     program = ProgramFactory(courses=[course])
     mock_get_programs.return_value = [program]
     self._create_enrollments(course_run_key)
     meter = ProgramProgressMeter(self.user)
     mock_completed_course_runs.return_value = [{'course_run_id': course_run_key, 'type': 'verified'}]
     self.assertEqual(meter._is_course_complete(course), True)
Beispiel #16
0
    def _create_course(self, course_price):
        """
        Creates the course in mongo and update it with the instructor data.
        Also creates catalog course with respect to course run.

        Returns:
            Catalog course dict.
        """
        course = ModuleStoreCourseFactory()
        course.start = datetime.datetime.now(utc) - datetime.timedelta(days=1)
        course.end = datetime.datetime.now(utc) + datetime.timedelta(days=1)
        course.instructor_info = self.instructors
        course = self.update_course(course, self.user.id)

        course_run = CourseRunFactory(key=unicode(course.id),
                                      seats=[SeatFactory(price=course_price)])
        return CourseFactory(course_runs=[course_run])
    def test_unpublished_sessions_for_entitlement(self, mock_get_edx_api_data):
        """
        Test unpublished course runs are not part of visible session entitlements when the user
        is not enrolled.
        """
        catalog_course_run = CourseRunFactory.create(status=COURSE_UNPUBLISHED)
        catalog_course = CourseFactory(course_runs=[catalog_course_run])
        mock_get_edx_api_data.return_value = catalog_course
        course_key = CourseKey.from_string(catalog_course_run.get('key'))
        course_overview = CourseOverviewFactory.create(id=course_key, start=self.tomorrow)
        CourseModeFactory.create(mode_slug=CourseMode.VERIFIED, min_price=100, course_id=course_overview.id)
        entitlement = CourseEntitlementFactory(
            user=self.user, mode=CourseMode.VERIFIED
        )

        session_entitlements = get_visible_sessions_for_entitlement(entitlement)
        self.assertEqual(session_entitlements, [])
Beispiel #18
0
 def setUp(self):
     super(BaseCourseEnrollmentTestsMixin, self).setUp()
     self.clear_caches()
     self.addCleanup(self.clear_caches)
     self.program_uuid = uuid4()
     self.organization_key = "orgkey"
     self.program = self.setup_catalog_cache(self.program_uuid,
                                             self.organization_key)
     self.course = self.program["courses"][0]
     self.course_run = self.course["course_runs"][0]
     self.course_key = CourseKey.from_string(self.course_run["key"])
     CourseOverviewFactory(id=self.course_key)
     self.course_not_in_program = CourseFactory()
     self.course_not_in_program_key = CourseKey.from_string(
         self.course_not_in_program["course_runs"][0]["key"])
     CourseOverviewFactory(id=self.course_not_in_program_key)
     self.default_url = self.get_url(self.program_uuid, self.course_key)
     self.client.login(username=self.global_staff, password=self.password)
    def test_handle_enqueue_failure(self, mock_log, mock_task, mock_get_programs):
        """Verify that failure to enqueue a task doesn't halt execution."""

        def side_effect(username):
            """Simulate failure to enqueue a task."""
            if username == self.alice.username:
                raise Exception

        mock_task.side_effect = side_effect

        data = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=self.course_run_key),
                    ]),
                ]
            ),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        self.assertTrue(mock_log.called)

        calls = [
            mock.call(self.alice.username),
            mock.call(self.bob.username)
        ]
        mock_task.assert_has_calls(calls, any_order=True)
    def test_get_visible_sessions_for_entitlement(self, mock_get_edx_api_data):
        """
        Test retrieval of visible session entitlements.
        """
        catalog_course_run = CourseRunFactory.create()
        catalog_course = CourseFactory(course_runs=[catalog_course_run])
        mock_get_edx_api_data.return_value = catalog_course
        course_key = CourseKey.from_string(catalog_course_run.get('key'))
        course_overview = CourseOverviewFactory.create(id=course_key, start=self.tomorrow)
        CourseModeFactory.create(mode_slug=CourseMode.VERIFIED, min_price=100, course_id=course_overview.id)
        course_enrollment = CourseEnrollmentFactory(
            user=self.user, course_id=unicode(course_overview.id), mode=CourseMode.VERIFIED
        )
        entitlement = CourseEntitlementFactory(
            user=self.user, enrollment_course_run=course_enrollment, mode=CourseMode.VERIFIED
        )

        session_entitlements = get_visible_sessions_for_entitlement(entitlement)
        self.assertEqual(session_entitlements, [catalog_course_run])
 def test_program_uuid_args(self, mock_get_programs, mock_task):
     course_1_id = 'course-v1:edX+Test+1'
     course_2_id = 'course-v1:edX+Test+2'
     program = ProgramFactory(
         courses=[
             CourseFactory(course_runs=[
                 CourseRunFactory(key=course_1_id),
                 CourseRunFactory(key=course_2_id)
             ])
         ],
         curricula=[],
     )
     self.expected_options['program_uuids'] = [program['uuid']]
     mock_get_programs.return_value = [program]
     call_command(Command(), '--program_uuids', program['uuid'])
     assert mock_task.called
     assert mock_task.call_args[0][0] == self.expected_options
     assert mock_task.call_args[0][1].sort() == [course_1_id,
                                                 course_2_id].sort()
Beispiel #22
0
    def test_in_progress_course_upgrade_deadline_check(self, offset,
                                                       mock_get_programs):
        """
        Verify that if the user's enrollment is not of the same type as the course run,
        the course will only count as in progress if there is another available seat with
        the right type for which the upgrade deadline has not passed.
        """
        course_run_key = generate_course_run_key()
        now = datetime.datetime.now(utc)
        upgrade_deadline = None if not offset else str(now +
                                                       datetime.timedelta(
                                                           days=offset))
        required_seat = SeatFactory(type='verified',
                                    upgrade_deadline=upgrade_deadline)
        enrolled_seat = SeatFactory(type='audit')
        seats = [required_seat, enrolled_seat]

        data = [
            ProgramFactory(courses=[
                CourseFactory(course_runs=[
                    CourseRunFactory(
                        key=course_run_key, type='verified', seats=seats),
                ]),
            ])
        ]
        mock_get_programs.return_value = data

        CourseEnrollmentFactory(user=self.user,
                                course_id=course_run_key,
                                mode='audit')

        meter = ProgramProgressMeter(self.site, self.user)

        program = data[0]
        expected = [
            ProgressFactory(uuid=program['uuid'],
                            completed=0,
                            in_progress=1 if offset in [None, 1] else 0,
                            not_started=1 if offset in [-1] else 0)
        ]

        self.assertEqual(meter.progress(count_only=True), expected)
Beispiel #23
0
    def setUpClass(cls):
        """
        Set up test data
        """
        super().setUpClass()
        catalog_org = CatalogOrganizationFactory.create(
            key=cls.organization_key)
        cls.program = ProgramFactory.create(
            uuid=cls.program_uuid, authoring_organizations=[catalog_org])
        organization = OrganizationFactory.create(
            short_name=cls.organization_key)
        SAMLProviderConfigFactory.create(organization=organization)

        catalog_course_id_str = 'course-v1:edX+ToyX'
        course_run_id_str = f'{catalog_course_id_str}+Toy_Course'
        cls.course_id = CourseKey.from_string(course_run_id_str)
        CourseOverviewFactory(id=cls.course_id)
        course_run = CourseRunFactory(key=course_run_id_str)
        cls.course = CourseFactory(key=catalog_course_id_str,
                                   course_runs=[course_run])
        cls.student_1 = UserFactory(username='******')
        cls.student_2 = UserFactory(username='******')
Beispiel #24
0
    def setUp(self):
        super(TestProgramDataExtender, self).setUp()

        self.user = UserFactory()
        self.client.login(username=self.user.username, password=self.password)

        self.course = ModuleStoreCourseFactory()
        self.course.start = datetime.datetime.now(utc) - datetime.timedelta(
            days=1)
        self.course.end = datetime.datetime.now(utc) + datetime.timedelta(
            days=1)
        self.course = self.update_course(self.course, self.user.id)  # pylint: disable=no-member

        organization = OrganizationFactory()
        course_run = CourseRunFactory(key=unicode(self.course.id))  # pylint: disable=no-member
        course = CourseFactory(course_runs=[course_run])
        program = ProgramFactory(authoring_organizations=[organization],
                                 courses=[course])

        self.program = munge_catalog_program(program)
        self.course_code = self.program['course_codes'][0]
        self.run_mode = self.course_code['run_modes'][0]
    def test_in_progress_course_upgrade_deadline_check(self, modifier, mock_get_programs):
        """
        Verify that if the user's enrollment is not of the same type as the course run,
        the course will only count as in progress if there is another available seat with
        the right type, where the upgrade deadline has not expired.
        """
        course_run_key = generate_course_run_key()
        now = datetime.datetime.now(utc)
        date_modifier = modifier * datetime.timedelta(days=1)
        seat_with_upgrade_deadline = SeatFactory(type='test', upgrade_deadline=str(now + date_modifier))
        enrolled_seat = SeatFactory(type='verified')
        seats = [seat_with_upgrade_deadline, enrolled_seat]

        data = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=course_run_key, type='test', seats=seats),
                    ]),
                ]
            )
        ]
        mock_get_programs.return_value = data

        self._create_enrollments(course_run_key)

        meter = ProgramProgressMeter(self.user)

        program = data[0]
        expected = [
            ProgressFactory(
                uuid=program['uuid'],
                completed=0,
                in_progress=1 if modifier == 1 else 0,
                not_started=1 if modifier == -1 else 0
            )
        ]
        self.assertEqual(meter.progress(count_only=True), expected)
    def test_handle_passing_status(self, mock_task, mock_get_programs):
        """
        Verify that only course run certificates with a passing status are selected.
        """
        data = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=self.course_run_key),
                    ]),
                ]
            ),
        ]
        mock_get_programs.return_value = data

        passing_status = CertificateStatuses.downloadable
        failing_status = CertificateStatuses.notpassing

        self.assertIn(passing_status, CertificateStatuses.PASSED_STATUSES)
        self.assertNotIn(failing_status, CertificateStatuses.PASSED_STATUSES)

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=passing_status,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=failing_status,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)
Beispiel #27
0
    def _create_cached_program(self):
        """ helper method to create a cached program """
        program = ProgramFactory.create()

        for course_key in self.course_keys:
            program['courses'].append(CourseFactory(id=course_key))

        program['type'] = 'MicroBachelors'
        program['type_attrs']['coaching_supported'] = True

        for course in program['courses']:
            cache.set(
                CATALOG_COURSE_PROGRAMS_CACHE_KEY_TPL.format(
                    course_uuid=course['uuid']), [program['uuid']], None)

            course_run = course['course_runs'][0]['key']
            cache.set(
                COURSE_PROGRAMS_CACHE_KEY_TPL.format(course_run_id=course_run),
                [program['uuid']], None)
        cache.set(PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']), program,
                  None)

        return program
Beispiel #28
0
    def test_program_completion_with_no_id_professional(self, mock_get_certificates_for_user, mock_get_programs):
        """
        Verify that 'no-id-professional' certificates are treated as if they were
        'professional' certificates when determining program completion.
        """
        # Create serialized course runs like the ones we expect to receive from
        # the discovery service's API. These runs are of type 'professional'.
        course_runs = CourseRunFactory.create_batch(2, type='professional')
        program = ProgramFactory(courses=[CourseFactory(course_runs=course_runs)])
        mock_get_programs.return_value = [program]

        # Verify that the test program is not complete.
        meter = ProgramProgressMeter(self.user)
        self.assertEqual(meter.completed_programs, [])

        # Grant a 'no-id-professional' certificate for one of the course runs,
        # thereby completing the program.
        mock_get_certificates_for_user.return_value = [
            self._make_certificate_result(status='downloadable', type='no-id-professional', course_key=course_runs[0]['key'])
        ]

        # Verify that the program is complete.
        meter = ProgramProgressMeter(self.user)
        self.assertEqual(meter.completed_programs, [program['uuid']])
Beispiel #29
0
    def test_no_id_professional_in_progress(self, mock_get_programs):
        """
        Verify that the progress meter treats no-id-professional enrollments
        as professional.
        """
        course_run_key = generate_course_run_key()
        data = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=course_run_key, type=CourseMode.PROFESSIONAL),
                    ]),
                ]
            )
        ]
        mock_get_programs.return_value = data

        CourseEnrollmentFactory(
            user=self.user, course_id=course_run_key,
            mode=CourseMode.NO_ID_PROFESSIONAL_MODE
        )

        meter = ProgramProgressMeter(self.site, self.user)

        program = data[0]
        expected = [
            ProgressFactory(
                uuid=program['uuid'],
                completed=[],
                in_progress=[program['courses'][0]],
                not_started=[],
                grades={course_run_key: 0.0},
            )
        ]

        self.assertEqual(meter.progress(count_only=False), expected)
Beispiel #30
0
    def test_simulate_progress(self, mock_completed_course_runs, mock_get_programs):
        """Simulate the entirety of a user's progress through a program."""
        first_course_run_key, second_course_run_key = (generate_course_run_key() for __ in range(2))
        data = [
            ProgramFactory(
                courses=[
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=first_course_run_key),
                    ]),
                    CourseFactory(course_runs=[
                        CourseRunFactory(key=second_course_run_key),
                    ]),
                ]
            ),
            ProgramFactory(),
        ]
        mock_get_programs.return_value = data

        # No enrollments, no programs in progress.
        meter = ProgramProgressMeter(self.user)
        self._assert_progress(meter)
        self.assertEqual(meter.completed_programs, [])

        # One enrollment, one program in progress.
        self._create_enrollments(first_course_run_key)
        meter = ProgramProgressMeter(self.user)
        program, program_uuid = data[0], data[0]['uuid']
        self._assert_progress(
            meter,
            ProgressFactory(uuid=program_uuid, in_progress=1, not_started=1)
        )
        self.assertEqual(meter.completed_programs, [])

        # Two enrollments, all courses in progress.
        self._create_enrollments(second_course_run_key)
        meter = ProgramProgressMeter(self.user)
        self._assert_progress(
            meter,
            ProgressFactory(uuid=program_uuid, in_progress=2)
        )
        self.assertEqual(meter.completed_programs, [])

        # One valid certificate earned, one course complete.
        mock_completed_course_runs.return_value = [
            {'course_run_id': first_course_run_key, 'type': MODES.verified},
        ]
        meter = ProgramProgressMeter(self.user)
        self._assert_progress(
            meter,
            ProgressFactory(uuid=program_uuid, completed=1, in_progress=1)
        )
        self.assertEqual(meter.completed_programs, [])

        # Invalid certificate earned, still one course to complete.
        mock_completed_course_runs.return_value = [
            {'course_run_id': first_course_run_key, 'type': MODES.verified},
            {'course_run_id': second_course_run_key, 'type': MODES.honor},
        ]
        meter = ProgramProgressMeter(self.user)
        self._assert_progress(
            meter,
            ProgressFactory(uuid=program_uuid, completed=1, in_progress=1)
        )
        self.assertEqual(meter.completed_programs, [])

        # Second valid certificate obtained, all courses complete.
        mock_completed_course_runs.return_value = [
            {'course_run_id': first_course_run_key, 'type': MODES.verified},
            {'course_run_id': second_course_run_key, 'type': MODES.verified},
        ]
        meter = ProgramProgressMeter(self.user)
        self._assert_progress(
            meter,
            ProgressFactory(uuid=program_uuid, completed=2)
        )
        self.assertEqual(meter.completed_programs, [program_uuid])