def setUpTestData(cls): cls.user = UserFactory.create() # Create Programs, Courses, CourseRuns... cls.p1_course_run_keys = ['p1_course_run'] cls.p2_course_run_keys = ['p2_course_run_1', 'p2_course_run_2'] cls.p1_course_run = CourseRunFactory.create( edx_course_key=cls.p1_course_run_keys[0]) p2 = FullProgramFactory.create() first_course = p2.course_set.first() extra_course = CourseFactory.create(program=p2) cls.p2_course_run_1 = CourseRunFactory.create( course=first_course, edx_course_key=cls.p2_course_run_keys[0]) cls.p2_course_run_2 = CourseRunFactory.create( course=extra_course, edx_course_key=cls.p2_course_run_keys[1]) all_course_runs = [ cls.p1_course_run, cls.p2_course_run_1, cls.p2_course_run_2 ] # Create cached edX data cls.enrollments = [ CachedEnrollmentFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs ] cls.certificates = [ CachedCertificateFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs ] cls.current_grades = [ CachedCurrentGradeFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs ]
def two_no_show_exam_attempts(self): """Passed and later failed course, and two exam attempts""" self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) course = Course.objects.get(title='Digital Learning 200') course_run = CourseRunFactory(course=course, edx_course_key='course-passed') call_command( "alter_data", 'set_to_passed', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) ExamProfileFactory.create(status='success', profile=self.user.profile) # run 1 exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True, exam_no_show=True ) # run 2 exam_run = ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) ExamAuthorizationFactory.create( user=self.user, course=course, exam_run=exam_run, status='success', exam_taken=True, exam_no_show=True ) # another offered course_run = CourseRunFactory.create(course=course, edx_course_key='course-enrollable') call_command( "alter_data", 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) course_run = CourseRunFactory.create(course=course, edx_course_key='course-failed') call_command( "alter_data", 'set_to_failed', '--username', 'staff', '--course-run-key', course_run.edx_course_key, '--audit', )
def voucher_and_partial_matches(voucher_and_user_client): """ Returns a voucher with partial matching CourseRuns """ voucher = voucher_and_user_client.voucher company = CompanyFactory() course_run_1 = CourseRunFactory( start_date=datetime.combine(voucher.course_start_date_input, datetime.min.time(), tzinfo=pytz.UTC), live=True, ) course_run_2 = CourseRunFactory( course__readable_id=voucher.course_id_input, live=True) course_run_3 = CourseRunFactory(course__title=voucher.course_title_input, live=True) course_run_4 = CourseRunFactory( course__readable_id=f"{voucher.course_id_input}-noise", live=True) course_run_5 = CourseRunFactory( course__title=f"{voucher.course_title_input}-noise", live=True) return SimpleNamespace( **vars(voucher_and_user_client), company=company, partial_matches=[ course_run_1, course_run_2, course_run_3, course_run_4, course_run_5, ], )
def create_audited_passed_enrolled_again_failed(self): """Make course passed and user retaking/auditing the course again""" self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) course = Course.objects.get(title='Digital Learning 200') CourseCertificateSignatoriesFactory.create(course=course) course_run = CourseRunFactory(course=course, edx_course_key='course-passed') set_course_run_past(course_run) call_command( "alter_data", 'set_to_passed', '--username', 'staff', '--course-run-key', course_run.edx_course_key, '--grade', '80', '--audit' ) final_grade = FinalGrade.objects.filter( course_run__course__title='Digital Learning 200', user=self.user ).first() CourseRunGradingStatus.objects.create(course_run=final_grade.course_run, status='complete') course_run = CourseRunFactory(course=course, edx_course_key='course-failed') set_course_run_past(course_run) call_command( "alter_data", 'set_to_failed', '--username', 'staff', '--course-run-key', course_run.edx_course_key, '--grade', '10', '--audit' ) course_run = CourseRunFactory(course=course, edx_course_key='course-offered') set_course_run_future(course_run) call_command( 'alter_data', 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key, )
def base_test_data(): """ Fixture for test data that should be available to any test case in the suite """ # Create a live program with valid prices and financial aid program = ProgramFactory.create( live=True, financial_aid_availability=True, price=1000, ) CourseRunFactory.create(course__program=program) TierProgramFactory.create_properly_configured_batch(2, program=program) # Create users staff_user, student_user = (create_user_for_login(is_staff=True), create_user_for_login(is_staff=False)) ProgramEnrollment.objects.create(program=program, user=staff_user) ProgramEnrollment.objects.create(program=program, user=student_user) Role.objects.create( role=Staff.ROLE_ID, user=staff_user, program=program, ) return SimpleNamespace(staff_user=staff_user, student_user=student_user, program=program)
def create_paid_but_no_enrollable_run(self, enrollable, in_future, fuzzy): """Make paid but not enrolled, with offered currently, in future, and fuzzy """ self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) course = Course.objects.get(title='Digital Learning 200') course_run = course.courserun_set.order_by('start_date').first() # course_run = CourseRunFactory.create(course=course, edx_course_key='course-paid') add_paid_order_for_course(user=self.user, course_run=course_run) if enrollable: course_run = CourseRunFactory.create(course=course, edx_course_key='course-enrollable') call_command( "alter_data", 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) if in_future: course_run = CourseRunFactory.create(course=course, edx_course_key='course-in-future') call_command( "alter_data", 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key, '--in-future' ) if fuzzy: course_run = CourseRunFactory.create(course=course, edx_course_key='course-fuzzy') call_command( "alter_data", 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key, '--fuzzy' )
def test_courseware_url(settings): """Test that the courseware_url property yields the correct values""" settings.OPENEDX_BASE_REDIRECT_URL = "http://example.com" course_run = CourseRunFactory.build(courseware_url_path="/path") course_run_no_path = CourseRunFactory.build(courseware_url_path=None) assert course_run.courseware_url == "http://example.com/path" assert course_run_no_path.courseware_url is None
def test_program_certificate_start_end_dates(user): """ Test that the ProgramCertificate start_end_dates property works properly """ now = now_in_utc() start_date = now + timedelta(days=1) end_date = now + timedelta(days=100) program = ProgramFactory.create() early_course_run = CourseRunFactory.create(course__program=program, start_date=start_date, end_date=end_date) later_course_run = CourseRunFactory.create( course__program=program, start_date=start_date + timedelta(days=1), end_date=end_date + timedelta(days=1), ) # Need the course run certificates to be there in order for the start_end_dates # to return valid values CourseRunCertificateFactory.create(course_run=early_course_run, user=user) CourseRunCertificateFactory.create(course_run=later_course_run, user=user) certificate = ProgramCertificateFactory.create(program=program, user=user) program_start_date, program_end_date = certificate.start_end_dates assert program_start_date == early_course_run.start_date assert program_end_date == later_course_run.end_date
def base_test_data(): """ Fixture for test data that should be available to any test case in the suite """ # Create a live program with valid prices and financial aid program = ProgramFactory.create( live=True, financial_aid_availability=True, price=1000, ) CourseRunFactory.create(course__program=program) TierProgramFactory.create_properly_configured_batch(2, program=program) # Create users staff_user, student_user = (create_user_for_login(is_staff=True), create_user_for_login(is_staff=False)) ProgramEnrollment.objects.create(program=program, user=staff_user) ProgramEnrollment.objects.create(program=program, user=student_user) Role.objects.create( role=Staff.ROLE_ID, user=staff_user, program=program, ) return SimpleNamespace( staff_user=staff_user, student_user=student_user, program=program )
def test_program_first_unexpired_run(): """ Test that the first unexpired run of a program is returned """ program = ProgramFactory() course = CourseFactory.create(program=program) now = now_in_utc() end_date = now + timedelta(days=100) enr_end_date = now + timedelta(days=100) first_run = CourseRunFactory.create( start_date=now, course=course, end_date=end_date, enrollment_end=enr_end_date, live=True, ) # create another course and course run in program another_course = CourseFactory.create(program=program) second_run = CourseRunFactory.create( start_date=now + timedelta(days=50), course=another_course, end_date=end_date, enrollment_end=enr_end_date, ) assert first_run.start_date < second_run.start_date assert program.first_unexpired_run == first_run
def test_catalog_program_serializer(has_page, has_thumbnail): """Tests that the catalog serializer returns a correct data structure""" page = ProgramPageFactory.create( has_thumbnail=has_thumbnail) if has_page else None program = page.program if page else ProgramFactory.create() courses = CourseFactory.create_batch(3, program=program) for course in courses: CourseRunFactory.create_batch(2, course=course) faculty_name = "faculty" if has_page: ProgramFaculty.objects.create( program_page=page, name=faculty_name, ) serialized = CatalogProgramSerializer(program).data # coerce OrderedDict objects to dict serialized = { **serialized, "courses": [{ **course, "course_runs": [dict(run) for run in course["course_runs"]] } for course in serialized["courses"]] } assert serialized == { "id": program.id, "title": program.title, "programpage_url": page.get_full_url() if has_page else None, "thumbnail_url": (page.thumbnail_image.get_rendition('fill-300x186').url if has_page and has_thumbnail else None), "courses": [{ "id": course.id, "edx_key": course.edx_key, "position_in_program": course.position_in_program, "course_runs": [{ "id": course_run.id, "edx_course_key": course_run.edx_course_key, } for course_run in course.courserun_set.all()] } for course in courses], 'topics': [{ 'name': topic.name } for topic in program.topics.iterator()], "instructors": [{ "name": faculty_name }] if has_page else [], "start_date": courses[0].first_unexpired_run().start_date, "enrollment_start": courses[0].first_unexpired_run().enrollment_start, "end_date": courses[-1].courserun_set.last().end_date, "total_price": str(program.price * program.num_required_courses), }
def setUpTestData(cls): cls.user = SocialUserFactory.create() cls.run_fa = CourseRunFactory.create( freeze_grade_date=now_in_utc() - timedelta(days=1), course__program__financial_aid_availability=True, ) cls.run_fa_with_cert = CourseRunFactory.create( freeze_grade_date=None, course__program=cls.run_fa.course.program, ) cls.run_no_fa = CourseRunFactory.create( freeze_grade_date=now_in_utc() + timedelta(days=1), course__program__financial_aid_availability=False, ) cls.run_no_fa_with_cert = CourseRunFactory.create( course__program=cls.run_no_fa.course.program, ) all_course_runs = ( cls.run_fa, cls.run_fa_with_cert, cls.run_no_fa, cls.run_no_fa_with_cert, ) for run in all_course_runs: if run.course.program.financial_aid_availability: FinancialAidFactory.create( user=cls.user, tier_program=TierProgramFactory.create( program=run.course.program, income_threshold=0, current=True), status=FinancialAidStatus.RESET, ) cls.enrollments = { course_run.edx_course_key: CachedEnrollmentFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs } cls.current_grades = { course_run.edx_course_key: CachedCurrentGradeFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs } cls.certificates = { course_run.edx_course_key: CachedCertificateFactory.create(user=cls.user, course_run=course_run) for course_run in (cls.run_fa_with_cert, cls.run_no_fa_with_cert) } cls.user_edx_data = CachedEdxUserData(cls.user)
def failed_run_missed_payment_can_reenroll(self): """Failed User has missed payment but they can re-enroll""" call_command( "alter_data", 'set_to_failed', '--username', 'staff', '--course-title', 'Analog Learning 200', '--grade', '0', '--audit' ) course = Course.objects.get(title='Analog Learning 200') CourseRunFactory.create(course=course)
def missed_payment_can_reenroll(self): """User has missed payment but they can re-enroll""" call_command( "alter_data", 'set_to_needs_upgrade', '--username', 'staff', '--course-title', 'Analog Learning 200', '--missed-deadline', ) course = Course.objects.get(title='Analog Learning 200') CourseRunFactory.create(course=course)
def test_doesnt_list_courses_from_unlive_programs(self): """ If the course belongs to a non-live program, hide it. """ CourseRunFactory.create(course__program__live=False) resp = self.client.get(reverse('courserun-list')) assert len(resp.json()) == 0
def test_program_view(client, user, home_page, is_enrolled, has_product, has_unexpired_run, is_anonymous): """ Test that the program detail view has the right context and shows the right HTML for the enroll/view button """ program = ProgramFactory.create(live=True, page__parent=home_page) if has_unexpired_run: now = now_in_utc() CourseRunFactory.create_batch( 3, course=CourseFactory.create(program=program, live=True, position_in_program=1), live=True, start_date=now + timedelta(hours=2), ) if has_product: product_id = ProductVersionFactory.create(product=ProductFactory( content_object=program)).product.id else: product_id = None if is_enrolled: ProgramEnrollmentFactory.create(user=user, program=program) if not is_anonymous: client.force_login(user) resp = client.get(program.page.get_url()) assert resp.context["user"] == user if not is_anonymous else AnonymousUser( ) assert resp.context["product_id"] == product_id assert resp.context["enrolled"] == (is_enrolled and not is_anonymous) # Anynoymous users don't see the enrolled/enroll-now button. # For logged in users: # a) product should exist, next courserun should be there, user not enrolled (enroll now button) # b) user is enrolled (enrolled button) has_button = ((has_product and has_unexpired_run and not is_enrolled) or is_enrolled) and not is_anonymous url = "" # make linter happy class_name = "" if not is_anonymous: if not is_enrolled and has_product and has_unexpired_run: url = f'{reverse("checkout-page")}?product={product_id}' class_name = "enroll-now" if is_enrolled: url = reverse("user-dashboard") class_name = "enrolled" assert ( f'<a class="enroll-button {class_name}" href="{url}">'.encode("utf-8") in resp.content) is has_button assert ("Please Sign In to MITx PRO to enroll in a course".encode("utf-8") in resp.content) is (is_anonymous and has_product and has_unexpired_run)
def test_serialized_semester_value(self): """ Tests that semester information in a course run is serialized to the right values """ valid_semester_course_run = CourseRunFactory.build(start_date=datetime(2017, 1, 1, tzinfo=pytz.UTC)) no_semester_course_run = CourseRunFactory.build(start_date=None, edx_course_key='bad_key') valid_semester_serialized = UserProgramSearchSerializer.serialize_semester(valid_semester_course_run) no_semester_serialized = UserProgramSearchSerializer.serialize_semester(no_semester_course_run) assert valid_semester_serialized == '2017 - Spring' assert no_semester_serialized is None
def test_generate_program_certificate_failure(user, program): """ Test that generate_program_certificate return (None, False) and not create program certificate if there is not any course_run certificate for the given course. """ course = CourseFactory.create(program=program) CourseRunFactory.create_batch(3, course=course) result = generate_program_certificate(user=user, program=program) assert result == (None, False) assert len(ProgramCertificate.objects.all()) == 0
def test_course_fuzzy_start_date(self): """Test course with promised course run""" CourseRunFactory.create( course=self.course, fuzzy_start_date="Fall 2017", start_date=None, end_date=None, enrollment_start=None, enrollment_end=None, ) assert self.course.enrollment_text == 'Coming Fall 2017'
def test_course_run_invalid_expiration_date(start_delta, end_delta, expiration_delta): """ Test that CourseRun.expiration_date raises ValidationError if expiration_date is before start_date or end_date """ now = now_in_utc() with pytest.raises(ValidationError): CourseRunFactory.create( start_date=now + timedelta(days=start_delta), end_date=now + timedelta(days=end_delta), expiration_date=now + timedelta(days=expiration_delta), )
def setUpTestData(cls): super().setUpTestData() # create an user cls.user = UserFactory.create() cls.cached_edx_user_data = MagicMock( spec=CachedEdxUserData, enrollments=CachedEnrollment.deserialize_edx_data(cls.enrollments_json), certificates=CachedCertificate.deserialize_edx_data(cls.certificates_json), current_grades=CachedCurrentGrade.deserialize_edx_data(cls.current_grades_json), ) # create the programs cls.program = ProgramFactory.create(live=True, financial_aid_availability=False, price=1000) cls.program_financial_aid = ProgramFactory.create(live=True, financial_aid_availability=True, price=1000) # create course runs for the normal program cls.course = CourseFactory.create(program=cls.program) expected_course_keys = [ "course-v1:edX+DemoX+Demo_Course", "course-v1:MITx+8.MechCX+2014_T1", '', None, 'course-v1:odl+FOO102+CR-FALL16' ] cls.cruns = [] for course_key in expected_course_keys: course_run = CourseRunFactory.create( course=cls.course, edx_course_key=course_key ) if course_key: cls.cruns.append(course_run) # and the program with financial aid finaid_course = CourseFactory.create(program=cls.program_financial_aid) cls.now = now_in_utc() cls.end_date = cls.now - timedelta(weeks=45) cls.crun_fa = CourseRunFactory.create( course=finaid_course, start_date=cls.now-timedelta(weeks=52), end_date=cls.end_date, enrollment_start=cls.now-timedelta(weeks=62), enrollment_end=cls.now-timedelta(weeks=53), edx_course_key="course-v1:odl+FOO101+CR-FALL15" ) cls.crun_fa2 = CourseRunFactory.create( course=finaid_course ) CourseRunFactory.create( course=finaid_course, edx_course_key=None )
def test_course_run_finder_success(self): """Tests that CourseRunFinder will return a desired course run""" course_run = CourseRunFactory.create(title='courserun1', edx_course_key='coursekey1') CourseRunFactory.create(title='courserun2', edx_course_key='coursekey2') found_course_runs = [ CourseRunFinder.find(course_run_title='courserun1'), CourseRunFinder.find(course_run_title='run1'), CourseRunFinder.find(course_run_key='coursekey1'), CourseRunFinder.find(course_run_key='key1') ] assert all([course_run == found_course_run for found_course_run in found_course_runs])
def test_lists_catalog(self): """Course Runs should show up""" program = ProgramFactory.create(live=True) for course in CourseFactory.create_batch(3, program=program): CourseRunFactory.create_batch(2, course=course) resp = self.client.get(reverse('catalog-list')) assert len(resp.json()) == 1 data = CatalogProgramSerializer(program).data assert_drf_json_equal([data], resp.json())
def setUpTestData(cls): """Create a set of course runs for testing""" super().setUpTestData() cls.run1 = CourseRunFactory.create( course__program__live=True, course__program__financial_aid_availability=True, ) cls.program = cls.run1.course.program cls.run2 = CourseRunFactory.create(course=cls.run1.course) cls.runs = [cls.run1, cls.run2] cls.user = UserFactory.create() ProgramEnrollment.objects.create(user=cls.user, program=cls.run1.course.program)
def setUpTestData(cls): cls.user = UserFactory.create(username='******', email='*****@*****.**') cls.course_runs = { 'fa': CourseRunFactory.create( course__program__financial_aid_availability=True), 'non_fa': CourseRunFactory.create( course__program__financial_aid_availability=False) } for course_run in cls.course_runs.values(): ProgramEnrollmentFactory.create(user=cls.user, program=course_run.course.program)
def test_serialized_semester_value(self): """ Tests that semester information in a course run is serialized to the right values """ valid_semester_course_run = CourseRunFactory.build( start_date=datetime(2017, 1, 1, tzinfo=pytz.UTC)) no_semester_course_run = CourseRunFactory.build( start_date=None, edx_course_key='bad_key') valid_semester_serialized = UserProgramSearchSerializer.serialize_semester( valid_semester_course_run) no_semester_serialized = UserProgramSearchSerializer.serialize_semester( no_semester_course_run) assert valid_semester_serialized == '2017 - Spring' assert no_semester_serialized is None
def setUpTestData(cls): cls.user = SocialUserFactory.create() cls.run_fa = CourseRunFactory.create( freeze_grade_date=now_in_utc()-timedelta(days=1), course__program__financial_aid_availability=True, ) cls.run_fa_with_cert = CourseRunFactory.create( freeze_grade_date=None, course__program=cls.run_fa.course.program, ) cls.run_no_fa = CourseRunFactory.create( freeze_grade_date=now_in_utc()+timedelta(days=1), course__program__financial_aid_availability=False, ) cls.run_no_fa_with_cert = CourseRunFactory.create( course__program=cls.run_no_fa.course.program, ) all_course_runs = (cls.run_fa, cls.run_fa_with_cert, cls.run_no_fa, cls.run_no_fa_with_cert, ) for run in all_course_runs: if run.course.program.financial_aid_availability: FinancialAidFactory.create( user=cls.user, tier_program=TierProgramFactory.create( program=run.course.program, income_threshold=0, current=True ), status=FinancialAidStatus.RESET, ) cls.enrollments = { course_run.edx_course_key: CachedEnrollmentFactory.create( user=cls.user, course_run=course_run) for course_run in all_course_runs } cls.current_grades = { course_run.edx_course_key: CachedCurrentGradeFactory.create( user=cls.user, course_run=course_run) for course_run in all_course_runs } cls.certificates = { course_run.edx_course_key: CachedCertificateFactory.create( user=cls.user, course_run=course_run) for course_run in (cls.run_fa_with_cert, cls.run_no_fa_with_cert) } cls.user_edx_data = CachedEdxUserData(cls.user)
def create_missed_payment_for_exam(self, enrollable, future_exam, current): """Passed course but missed deadline to pay to take exam""" self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) if current: call_command( "alter_data", 'set_to_enrolled', '--username', 'staff', '--course-title', 'Digital Learning 200', '--missed-deadline' ) else: call_command( "alter_data", 'set_past_run_to_passed', '--username', 'staff', '--course-title', 'Digital Learning 200', '--grade', '87', '--audit', '--missed-deadline' ) course = Course.objects.get(title='Digital Learning 200') ExamProfileFactory.create(status='success', profile=self.user.profile) ExamRunFactory.create(course=course, eligibility_past=True, scheduling_past=True) if enrollable: course_run = CourseRunFactory.create(course=course, edx_course_key='course-enrollable') call_command( "alter_data", 'set_to_offered', '--username', 'staff', '--course-run-key', course_run.edx_course_key ) if future_exam: ExamRunFactory.create( scheduling_past=False, scheduling_future=True, authorized=True, course=course )
def setUpTestData(cls): super().setUpTestData() cls.user = UserFactory() cls.user.social_auth.create( provider='not_edx', ) cls.user.social_auth.create( provider=EdxOrgOAuth2.name, uid="{}_edx".format(cls.user.username), ) cls.order = OrderFactory.create(status=Order.CREATED, user=cls.user) cls.line1 = LineFactory.create(order=cls.order) cls.line2 = LineFactory.create(order=cls.order) cls.course_run1 = CourseRunFactory.create(edx_course_key=cls.line1.course_key) cls.course_run2 = CourseRunFactory.create(edx_course_key=cls.line2.course_key)
def test_program(self): # pylint: disable=no-self-use """ Make sure program id appears correctly """ course_run = CourseRunFactory.create() result = CourseRunSerializer().to_representation(course_run) assert result['program'] == course_run.course.program.id
def _generate_cached_enrollments(user, program, num_course_runs=1, data=None): """ Helper method to generate CachedEnrollments for test cases """ fake = faker.Factory.create() course = CourseFactory.create(program=program) course_run_params = dict(before_now=True, after_now=False, tzinfo=pytz.utc) course_runs = [ CourseRunFactory.create( course=course, enrollment_start=fake.date_time_this_month( **course_run_params), start_date=fake.date_time_this_month(**course_run_params), enrollment_end=fake.date_time_this_month(**course_run_params), end_date=fake.date_time_this_year(**course_run_params), ) for _ in range(num_course_runs) ] factory_kwargs = dict(user=user) if data is not None: factory_kwargs['data'] = data return [ CachedEnrollmentFactory.create(course_run=course_run, **factory_kwargs) for course_run in course_runs ]
def test_course_keys(self): """ Coupon.course_keys should return a list of all course run keys in a program, course, or course run """ run1 = CourseRunFactory.create(course__program__financial_aid_availability=True) run2 = CourseRunFactory.create(course=run1.course) run3 = CourseRunFactory.create(course__program=run1.course.program) run4 = CourseRunFactory.create(course=run3.course) coupon_program = CouponFactory.create( content_object=run1.course.program, ) assert sorted(coupon_program.course_keys) == sorted([run.edx_course_key for run in [run1, run2, run3, run4]]) coupon_course = CouponFactory.create(content_object=run1.course) assert sorted(coupon_course.course_keys) == sorted([run.edx_course_key for run in [run1, run2]])
def test_successful_program_certificate_generation_with_electives(self): """ Test has final grade and a certificate with elective courses """ run_2 = CourseRunFactory.create( freeze_grade_date=now_in_utc() - timedelta(days=1), course__program=self.program, ) electives_set = ElectivesSet.objects.create(program=self.program, required_number=1) for run in [self.run_1, run_2]: final_grade = FinalGradeFactory.create( user=self.user, course_run=run, passed=True, status='complete', grade=0.7 ) CourseRunGradingStatus.objects.create(course_run=run, status='complete') ElectiveCourse.objects.create(course=run.course, electives_set=electives_set) with mute_signals(post_save): MicromastersCourseCertificate.objects.create(course=final_grade.course_run.course, user=self.user) cert_qset = MicromastersProgramCertificate.objects.filter(user=self.user, program=self.program) assert cert_qset.exists() is False api.generate_program_certificate(self.user, self.program) assert cert_qset.exists() is True
def test_course_serialization_format(self): """ Tests that a user's course enrollments are serialized in a specific format """ for program_enrollment in (self.non_fa_program_enrollment, self.fa_program_enrollment): program = program_enrollment.program # Generate a new course run on an existing course, and create an unverified enrollment in it existing_course = program.course_set.first() new_course_run = CourseRunFactory(course=existing_course) self.unverified_enroll(self.user, course_run=new_course_run) # Generate a new course with only unverified course run enrollments unver_course, unver_course_runs = self.generate_course_with_runs( program, course_params=dict(title='Unverified Course'), course_run_count=2) for course_run in unver_course_runs: self.unverified_enroll(self.user, course_run=course_run) # Serialize the program enrollment and make sure each course is serialized properly serialized_program_user = UserProgramSearchSerializer.serialize( program_enrollment) serialized_enrollments = serialized_program_user['courses'] assert len(serialized_enrollments) == 2 # A course with a mix of verified and unverified course runs should be serialized as verified assert self.is_course_serialized_with_status( serialized_enrollments, existing_course, is_verified=True) # A course with a mix of all unverified course runs should be serialized as unverified assert self.is_course_serialized_with_status( serialized_enrollments, unver_course, is_verified=False)
def setUpTestData(cls): cls.users = [UserFactory.create() for _ in range(35)] freeze_date = now_in_utc()-timedelta(days=1) future_freeze_date = now_in_utc()+timedelta(days=1) cls.course_run1 = CourseRunFactory.create(freeze_grade_date=freeze_date) cls.course_run2 = CourseRunFactory.create(freeze_grade_date=freeze_date) cls.all_freezable_runs = [cls.course_run1, cls.course_run2] cls.course_run_future = CourseRunFactory.create(freeze_grade_date=future_freeze_date) cls.course_run_frozen = CourseRunFactory.create(freeze_grade_date=freeze_date) CourseRunGradingStatus.objects.create(course_run=cls.course_run_frozen, status=FinalGradeStatus.COMPLETE) for user in cls.users: CachedEnrollmentFactory.create(user=user, course_run=cls.course_run1) CachedCurrentGradeFactory.create(user=user, course_run=cls.course_run1)
def generate_course_with_runs(program, course_params=None, course_run_count=1): """ Helper method to generate a Course with CourseRuns for a Program """ course_params = course_params or {} course = CourseFactory.create(program=program, **course_params) course_runs = CourseRunFactory.create_batch(course_run_count, course=course) return course, course_runs
def test_user_has_redemptions_left(self, order_status, has_unpurchased_run, another_already_redeemed, expected): """ Coupon.user_has_redemptions_left should be true if user has not yet purchased all course runs """ run1 = CourseRunFactory.create(course__program__financial_aid_availability=True) if has_unpurchased_run: CourseRunFactory.create(course__program=run1.course.program) line = LineFactory.create(course_key=run1.edx_course_key, order__status=order_status) coupon = CouponFactory.create(content_object=run1.course.program) with patch( 'ecommerce.models.Coupon.another_user_already_redeemed', autospec=True, ) as _already_redeemed: _already_redeemed.return_value = another_already_redeemed assert coupon.user_has_redemptions_left(line.order.user) is expected _already_redeemed.assert_called_with(coupon, line.order.user)
def create_passed_and_offered_course_run(self, grades_frozen, with_certificate): """Make passed and currently offered course run, and see the View Certificate and Re-Enroll""" self.make_fa_program_enrollment(FinancialAidStatus.AUTO_APPROVED) call_command( "alter_data", 'set_to_passed', '--username', 'staff', '--course-title', 'Digital Learning 200', '--grade', '89', ) course = Course.objects.get(title='Digital Learning 200') # create another currently offered run CourseRunFactory.create(course=course) if grades_frozen: final_grade = FinalGrade.objects.filter(user=self.user, course_run__course=course, passed=True).first() CourseRunGradingStatus.objects.create(course_run=final_grade.course_run, status='complete') if with_certificate: MicromastersCourseCertificate.objects.create(user=self.user, course=course) CourseCertificateSignatoriesFactory.create(course=course)
def test_create_final_grade_fa(self, generate_letter_mock, update_grade_mock, mock_on_commit): """ Test that final grades created for non-FA courses will try to update combined final grades. """ fa_course_run = CourseRunFactory.create(course__program__financial_aid_availability=True) FinalGradeFactory.create(user=self.user, course_run=fa_course_run, grade=0.9) update_grade_mock.assert_called_once_with(self.user, fa_course_run.course) generate_letter_mock.assert_not_called()
def setUpTestData(cls): cls.user = SocialUserFactory.create() cls.run_1 = CourseRunFactory.create( freeze_grade_date=now_in_utc()-timedelta(days=1), course__program__financial_aid_availability=True, ) cls.program = cls.run_1.course.program
def setUpTestData(cls): cls.user = SocialUserFactory.create() cls.run_1 = CourseRunFactory.create( freeze_grade_date=now_in_utc()-timedelta(days=1), course__program__financial_aid_availability=True, ) CourseRunGradingStatus.objects.create(course_run=cls.run_1, status='complete') cls.program = cls.run_1.course.program
def test_course_with_run(self): """ Make sure the course URL serializes properly """ course_run = CourseRunFactory.create() course = course_run.course data = CourseSerializer(course).data assert data['url'] == course_run.enrollment_url assert data['enrollment_text'] == course.enrollment_text
def setUpTestData(cls): """ Create user, run, and coupons for testing """ super().setUpTestData() cls.user = SocialProfileFactory.create().user UserSocialAuthFactory.create(user=cls.user, provider='not_edx') run = CourseRunFactory.create(course__program__financial_aid_availability=True) cls.coupon = CouponFactory.create(content_object=run.course.program) UserCoupon.objects.create(coupon=cls.coupon, user=cls.user)
def test_coupon_allowed_course(self): """ Assert that the price is not adjusted if the coupon is for a different course in the same program """ course_run, _ = create_purchasable_course_run() other_course = CourseRunFactory.create(course__program=course_run.course.program).course price = Decimal('0.3') coupon = CouponFactory.create(content_object=other_course) assert coupon.content_object != course_run assert calculate_coupon_price(coupon, price, course_run.edx_course_key) == price
def test_another_user_already_redeemed(self, order_status, other_user_redeemed, is_automatic, expected): """ Tests for Coupon.another_user_already_redeemed """ run1 = CourseRunFactory.create(course__program__financial_aid_availability=True) run2 = CourseRunFactory.create(course=run1.course) coupon = CouponFactory.create( content_object=run1.course, coupon_type=Coupon.DISCOUNTED_PREVIOUS_COURSE if is_automatic else Coupon.STANDARD, ) line1 = LineFactory.create(course_key=run1.edx_course_key, order__status=Order.FULFILLED) RedeemedCoupon.objects.create(order=line1.order, coupon=coupon) if other_user_redeemed: line2 = LineFactory.create(course_key=run2.edx_course_key, order__status=order_status) RedeemedCoupon.objects.create(order=line2.order, coupon=coupon) assert coupon.another_user_already_redeemed(line1.order.user) is expected
def test_deserialize_user_data(self): """Test that user data is correctly deserialized""" new_course_run = CourseRunFactory.create(edx_course_key='course-v1:MITx+Analog+Learning+100+Aug_2015') new_program = new_course_run.course.program with mute_signals(post_save): user = deserialize_user_data(self.USER_DATA, [new_program]) assert user.username == '{}mario.medina'.format(FAKE_USER_USERNAME_PREFIX) assert user.profile.first_name == 'Mario' assert user.profile.date_of_birth == '1961-04-29' assert CachedEnrollment.objects.filter(user=user, course_run=new_course_run).count() == 1
def test_course_run(self): """ Make sure course run serializer correctly """ course_run = CourseRunFactory.create() data = CourseRunSerializer(course_run).data expected = { 'edx_course_key': course_run.edx_course_key, 'program_title': course_run.course.program.title, } assert data == expected
def setUpTestData(cls): super().setUpTestData() # create a user cls.user = SocialUserFactory.create() # create the course run cls.course_id = "edx+fake+key" cls.course_run = CourseRunFactory.create(edx_course_key=cls.course_id) # url for the dashboard cls.url = reverse('user_course_enrollments')
def create_frozen_run(self, course): """helper function to create frozen course runs""" now = now_in_utc() run = CourseRunFactory.create( course=course, title="Title Run", freeze_grade_date=now - timedelta(weeks=1), ) CourseRunGradingStatus.objects.create(course_run=run, status='complete') return run
def test_validate_discount_prev_run_coupon_type(self): """Coupon must be for a course if Coupon.coupon_type is DISCOUNTED_PREVIOUS_RUN""" run = CourseRunFactory.create() with self.assertRaises(ValidationError) as ex: CouponFactory.create( coupon_type=Coupon.DISCOUNTED_PREVIOUS_COURSE, content_object=run.course.program, ) assert ex.exception.args[0]['__all__'][0].args[0] == ( 'coupon must be for a course if coupon_type is discounted-previous-course' )