def test_retry_failed_edx_enrollments(mocker, exception_raised): """ Tests that retry_failed_edx_enrollments loops through enrollments that failed in edX and attempts to enroll them again """ with freeze_time(now_in_utc() - timedelta(days=1)): failed_enrollments = CourseRunEnrollmentFactory.create_batch( 3, edx_enrolled=False, user__is_active=True) CourseRunEnrollmentFactory.create(edx_enrolled=False, user__is_active=False) patched_enroll_in_edx = mocker.patch( "courseware.api.enroll_in_edx_course_runs", side_effect=[None, exception_raised or None, None], ) patched_log_exception = mocker.patch("courseware.api.log.exception") successful_enrollments = retry_failed_edx_enrollments() assert patched_enroll_in_edx.call_count == len(failed_enrollments) assert len(successful_enrollments) == (3 if exception_raised is None else 2) assert patched_log_exception.called == bool(exception_raised) if exception_raised: failed_enroll_user, failed_enroll_runs = patched_enroll_in_edx.call_args_list[ 1][0] expected_successful_enrollments = [ e for e in failed_enrollments if e.user != failed_enroll_user and e.run != failed_enroll_runs[0] ] assert {e.id for e in successful_enrollments } == {e.id for e in expected_successful_enrollments}
def test_defer_enrollment_validation(mocker, user): """ defer_enrollment should raise an exception if the 'from' or 'to' course runs are invalid """ courses = CourseFactory.create_batch(2) enrollments = CourseRunEnrollmentFactory.create_batch( 3, user=user, active=factory.Iterator([False, True, True]), run__course=factory.Iterator([courses[0], courses[0], courses[1]]), ) unenrollable_run = CourseRunFactory.create(enrollment_end=now_in_utc() - timedelta(days=1)) patched_create_enrollments = mocker.patch( "courses.api.create_run_enrollments", return_value=([], False)) mocker.patch("courses.api.deactivate_run_enrollment", return_value=[]) with pytest.raises(ValidationError): # Deferring to the same course run should raise a validation error defer_enrollment(user, enrollments[0].run.courseware_id, enrollments[0].run.courseware_id) patched_create_enrollments.assert_not_called() with pytest.raises(ValidationError): # Deferring to a course run that is outside of its enrollment period should raise a validation error defer_enrollment(user, enrollments[0].run.courseware_id, unenrollable_run.courseware_id) patched_create_enrollments.assert_not_called() with pytest.raises(ValidationError): # Deferring from an inactive enrollment should raise a validation error defer_enrollment(user, enrollments[0].run.courseware_id, enrollments[1].run.courseware_id) patched_create_enrollments.assert_not_called() with pytest.raises(ValidationError): # Deferring to a course run in a different course should raise a validation error defer_enrollment(user, enrollments[1].run.courseware_id, enrollments[2].run.courseware_id) patched_create_enrollments.assert_not_called() # The last two cases should not raise an exception if the 'force' flag is set to True defer_enrollment( user, enrollments[0].run.courseware_id, enrollments[1].run.courseware_id, force=True, ) assert patched_create_enrollments.call_count == 1 defer_enrollment( user, enrollments[1].run.courseware_id, enrollments[2].run.courseware_id, force=True, ) assert patched_create_enrollments.call_count == 2
def test_get_program_run_enrollments(user): """ Test that the get_program_run_enrollments helper method for CourseRunEnrollment returns the appropriate course run enrollments for a program """ programs = ProgramFactory.create_batch(2) program = programs[0] course_run_enrollments = CourseRunEnrollmentFactory.create_batch( 2, user=user, run__course__program=factory.Iterator([program, program, programs[1]]), ) expected_run_enrollments = set(course_run_enrollments[0:2]) assert (set(CourseRunEnrollment.get_program_run_enrollments( user, program)) == expected_run_enrollments)
def test_deactivate_program_enrollment(self, user, patches): """ deactivate_program_enrollment set the local program enrollment record to inactive as well as all associated course run enrollments """ order = OrderFactory.create() program_enrollment = ProgramEnrollmentFactory.create(user=user, order=order) course = CourseFactory.create(program=program_enrollment.program) course_run_enrollments = CourseRunEnrollmentFactory.create_batch( 3, user=user, run__course=course, active=True, order=factory.Iterator([order, order, None]), ) expected_inactive_run_enrollments = course_run_enrollments[0:2] expected_ignored_run_enrollment = course_run_enrollments[2] returned_program_enrollment, returned_run_enrollments = deactivate_program_enrollment( program_enrollment, change_status=ENROLL_CHANGE_STATUS_REFUNDED) program_enrollment.refresh_from_db() assert program_enrollment.change_status == ENROLL_CHANGE_STATUS_REFUNDED assert program_enrollment.active is False assert returned_program_enrollment == program_enrollment assert {e.id for e in returned_run_enrollments } == {e.id for e in expected_inactive_run_enrollments} assert patches.edx_unenroll.call_count == len( expected_inactive_run_enrollments) assert patches.send_unenrollment_email.call_count == len( expected_inactive_run_enrollments) for run_enrollment in expected_inactive_run_enrollments: run_enrollment.refresh_from_db() assert run_enrollment.change_status == ENROLL_CHANGE_STATUS_REFUNDED assert run_enrollment.active is False assert expected_ignored_run_enrollment.active is True
def test_serialize_program_enrollments(settings, has_company, receipts_enabled): """Test that ProgramEnrollmentSerializer has correct data""" settings.ENABLE_ORDER_RECEIPTS = receipts_enabled program = ProgramFactory.create() course_run_enrollments = CourseRunEnrollmentFactory.create_batch( 3, run__course__program=factory.Iterator([program, program, None]), run__course__position_in_program=factory.Iterator([2, 1, None]), ) program_enrollment = ProgramEnrollmentFactory.create( program=program, has_company_affiliation=has_company) serialized_data = ProgramEnrollmentSerializer(program_enrollment, context={ "course_run_enrollments": course_run_enrollments }).data assert serialized_data == { "id": program_enrollment.id, "program": BaseProgramSerializer(program).data, "company": (CompanySerializer(program_enrollment.company).data if has_company else None), # Only enrollments for the given program should be serialized, and they should be # sorted by position in program. "course_run_enrollments": CourseRunEnrollmentSerializer( [course_run_enrollments[1], course_run_enrollments[0]], many=True).data, "certificate": None, "receipt": program_enrollment.order_id if program_enrollment.order.status == Order.FULFILLED and receipts_enabled else None, }
def test_get_user_enrollments(user): """Test that get_user_enrollments returns an object with a user's program and course enrollments""" past_date = now_in_utc() - timedelta(days=1) past_start_dates = [ now_in_utc() - timedelta(days=2), now_in_utc() - timedelta(days=3), now_in_utc() - timedelta(days=4), ] program = ProgramFactory.create() past_program = ProgramFactory.create() program_course_runs = CourseRunFactory.create_batch( 3, course__program=program) past_program_course_runs = CourseRunFactory.create_batch( 3, start_date=factory.Iterator(past_start_dates), end_date=past_date, course__program=past_program, ) non_program_course_runs = CourseRunFactory.create_batch( 2, course__program=None) past_non_program_course_runs = CourseRunFactory.create_batch( 2, start_date=factory.Iterator(past_start_dates), end_date=past_date, course__program=None, ) all_course_runs = (program_course_runs + past_program_course_runs + non_program_course_runs + past_non_program_course_runs) course_run_enrollments = CourseRunEnrollmentFactory.create_batch( len(all_course_runs), run=factory.Iterator(all_course_runs), user=user) program_enrollment = ProgramEnrollmentFactory.create(program=program, user=user) past_program_enrollment = ProgramEnrollmentFactory.create( program=past_program, user=user) # Add a non-active enrollment so we can confirm that it isn't returned CourseRunEnrollmentFactory.create(user=user, active=False) def key_func(enrollment): """ Function for sorting runs by start_date""" return enrollment.run.start_date user_enrollments = get_user_enrollments(user) assert list(user_enrollments.programs) == [program_enrollment] assert list(user_enrollments.past_programs) == [past_program_enrollment] assert list(user_enrollments.program_runs) == sorted( [ run_enrollment for run_enrollment in course_run_enrollments if run_enrollment.run in program_course_runs + past_program_course_runs ], key=key_func, ) assert list(user_enrollments.non_program_runs) == sorted( [ run_enrollment for run_enrollment in course_run_enrollments if run_enrollment.run in non_program_course_runs ], key=key_func, ) assert list(user_enrollments.past_non_program_runs) == sorted( [ run_enrollment for run_enrollment in course_run_enrollments if run_enrollment.run in past_non_program_course_runs ], key=key_func, )