def test_nonverified_course_run_completion(self, mock_completed_course_runs, mock_get_programs): """ Course runs aren't necessarily of type verified. Verify that a program can still be completed when this is the case. """ course_run_key = generate_course_run_key() data = [ ProgramFactory( courses=[ CourseFactory(course_runs=[ CourseRunFactory(key=course_run_key, type='honor'), CourseRunFactory(), ]), ] ), ProgramFactory(), ] mock_get_programs.return_value = data self._create_enrollments(course_run_key) mock_completed_course_runs.return_value = [ {'course_run_id': course_run_key, 'type': MODES.honor}, ] meter = ProgramProgressMeter(self.user) program, program_uuid = data[0], data[0]['uuid'] self._assert_progress( meter, ProgressFactory(uuid=program_uuid, completed=1) ) self.assertEqual(meter.completed_programs, [program_uuid])
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.user) program = data[0] expected = [ ProgressFactory( uuid=program['uuid'], completed=[], in_progress=[program['courses'][0]], not_started=[] ) ] self.assertEqual(meter.progress(count_only=False), expected)
def test_single_program_engagement(self, mock_get_programs): """ Verify that correct program is returned when the user is enrolled in a course run appearing in one program. """ course_run_key = generate_course_run_key() data = [ ProgramFactory( courses=[ CourseFactory(course_runs=[ CourseRunFactory(key=course_run_key), ]), ] ), ProgramFactory(), ] mock_get_programs.return_value = data self._create_enrollments(course_run_key) meter = ProgramProgressMeter(self.user) self._attach_detail_url(data) program = data[0] self.assertEqual(meter.engaged_programs, [program]) self._assert_progress( meter, ProgressFactory(uuid=program['uuid'], in_progress=1) ) self.assertEqual(meter.completed_programs, [])
def test_course_progress(self, mock_get_programs): """ Verify that the progress meter can represent progress in terms of serialized courses. """ course_run_key = generate_course_run_key() data = [ ProgramFactory( courses=[ CourseFactory(course_runs=[ CourseRunFactory(key=course_run_key), ]), ] ) ] 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=[], in_progress=[program['courses'][0]], not_started=[] ) ] self.assertEqual(meter.progress(count_only=False), expected)
def test_course_grade_results(self, mock_get_programs): grade_percent = .8 with mock_passing_grade(percent=grade_percent): course_run_key = generate_course_run_key() data = [ ProgramFactory( courses=[ CourseFactory(course_runs=[ CourseRunFactory(key=course_run_key), ]), ] ) ] mock_get_programs.return_value = data self._create_enrollments(course_run_key) 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: grade_percent}, ) ] self.assertEqual(meter.progress(count_only=False), expected)
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.user) self._attach_detail_url(data) programs = data[:2] 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, [])
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.site, self.user) self._attach_detail_url(data) programs = data[:3] self.assertEqual(meter.engaged_programs, programs) grades = { solo_course_run_key: 0.0, shared_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, [])
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)
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_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])