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_returns_model_if_string_provided(self): # pylint: disable=no-self-use """string-to-model returns correct model for single string""" uid = "2d133482b3214a119f55c3060d882ceb" CourseFactory.create() f = SMMF(model=EdxAuthor, lookup="edx_uid") ms = f.to_internal_value(uid) assert len(ms) == 1 assert ms[0].edx_uid == uid
def test_program_course_auto_position(): """ If a course is added to a program with no position specified, it should be given the last position """ first_course = CourseFactory.create(position_in_program=None) assert first_course.position_in_program == 1 second_course = CourseFactory.create(program=first_course.program, position_in_program=None) assert second_course.position_in_program == 2
def test_returns_models_if_list_provided(self): # pylint: disable=no-self-use """string-to-model returns correct model for list""" uid = "2d133482b3214a119f55c3060d882ceb" uid2 = "3d133482b3214a119f55c3060d882ceb" CourseFactory.create() f = SMMF(model=EdxAuthor, lookup="edx_uid") ms = f.to_internal_value([uid, uid2]) assert len(ms) == 2 assert ms[0].edx_uid != ms[1].edx_uid assert ms[0].edx_uid in [uid, uid2] assert ms[1].edx_uid in [uid, uid2]
def test_complete(self, first_has_frozen, second_has_frozen, result): """ Test has_frozen_grades_for_all_courses """ course_1 = CourseFactory.create(title="Title") course_2 = CourseFactory.create(title="Title", program=course_1.program) if first_has_frozen: self.create_frozen_run(course_1) if second_has_frozen: self.create_frozen_run(course_2) assert course_1.program.has_frozen_grades_for_all_courses() is result
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_program_num_courses(): """ Program should return number of courses associated with it """ program = ProgramFactory.create() assert program.num_courses == 0 CourseFactory.create(program=program) assert program.num_courses == 1 CourseFactory.create(program=program) assert program.num_courses == 2
def test_program_courses(self): """ Test ProgramSerializer with multiple courses """ CourseFactory.create_batch(5, program=self.program) data = ProgramSerializer(self.program, context=self.context).data assert data == { 'id': self.program.id, 'title': self.program.title, 'programpage_url': None, 'enrolled': False, 'total_courses': 5, }
def test_serialize_basket_product_version_program(mock_context): """Test ProductVersion serialization for a Program""" program = ProgramFactory.create() courses = CourseFactory.create_batch(3, program=program) product_version = ProductVersionFactory.create( product=ProductFactory(content_object=program) ) data = FullProductVersionSerializer( instance=product_version, context=mock_context ).data assert data == { "id": product_version.id, "description": product_version.description, "content_title": product_version.product.content_object.title, "price": str(round_half_up(product_version.price)), "type": product_version.product.content_type.model, "courses": [ CourseSerializer(instance=course, context=mock_context).data for course in courses ], "thumbnail_url": program.catalog_image_url, "object_id": product_version.product.object_id, "product_id": product_version.product.id, "readable_id": get_readable_id(product_version.product.content_object), "run_tag": None, "created_on": product_version.created_on.strftime(datetime_millis_format), "start_date": product_version.product.content_object.next_run_date.isoformat() if product_version.product.content_object.next_run_date else None, }
def test_courses_not_live_in_courses_api(client, live): """Courses should be filtered out of the courses API if not live""" course = CourseFactory.create(live=live) resp = client.get(reverse("courses_api-list")) assert resp.status_code == status.HTTP_200_OK assert_drf_json_equal(resp.json(), [CourseSerializer(course).data] if live else [])
def setUpTestData(cls): super().setUpTestData() with mute_signals(post_save): cls.user = ProfileFactory.create().user cls.program = ProgramFactory.create() cls.course = CourseFactory.create(program=cls.program)
def test_program_page_serializer(self): """ Test program page serializer """ page = ProgramPageFactory.create() courses = CourseFactory.create_batch(6, program=page.program) faculty = FacultyFactory.create_batch(3, program_page=page) elective_set = ElectivesSet.objects.create(program=page.program, required_number=2, title="Elective") # Add 3 courses to elective set - For required 2 of 3 scenario for elective_course in courses[:3]: ElectiveCourse.objects.create(electives_set=elective_set, course=elective_course) data = ProgramPageSerializer(page).data data['faculty'] = sorted(data['faculty'], key=lambda member: member['name']) assert data == { "id": page.program.id, "title": page.title, "slug": ProgramPageSerializer().get_slug(page), "faculty": FacultySerializer(sorted(faculty, key=lambda member: member.name), many=True).data, # Only core courses (Not associated with electives) "courses": CourseSerializer(courses[3:], many=True).data, "electives_sets": ElectivesSetSerializer([elective_set], many=True).data, }
def test_count_courses_passed_normal(self): """ Assert that count_courses_passed works in case of normal program. """ mmtrack = MMTrack( user=self.user, program=self.program, edx_user_data=self.cached_edx_user_data ) assert mmtrack.count_courses_passed() == 0 course_run = self.cruns[0] FinalGradeFactory.create( user=self.user, course_run=course_run, passed=True ) assert mmtrack.count_courses_passed() == 1 course = CourseFactory.create(program=self.program) final_grade = FinalGradeFactory.create( user=self.user, course_run__course=course, passed=True ) mmtrack.edx_course_keys.add(final_grade.course_run.edx_course_key) assert mmtrack.count_courses_passed() == 2
def test_count_courses_mixed_fa(self): """ Test count_courses_passed with mixed course-exam configuration """ mmtrack = MMTrack( user=self.user, program=self.program_financial_aid, edx_user_data=self.cached_edx_user_data ) # this is course with exam run and the user has CombinedFinalGrade for it course_with_exam_1 = CourseFactory.create(program=self.program_financial_aid) ExamRunFactory.create(course=course_with_exam_1, date_grades_available=now_in_utc()-timedelta(weeks=1)) CombinedFinalGrade.objects.create(user=self.user, course=course_with_exam_1, grade=0.7) # create course with exam run the user did not pass ExamRunFactory.create( course__program=self.program_financial_aid, date_grades_available=now_in_utc() - timedelta(weeks=1) ) # another course with no exam FinalGradeFactory.create( user=self.user, course_run=self.crun_fa, passed=True ) assert mmtrack.count_courses_passed() == 2
def test_program_page(browser, base_test_data, logged_in_student): """ Test viewing the program page """ courses = list(base_test_data.program.course_set.all()) + \ CourseFactory.create_batch(2, program=base_test_data.program) page = ProgramPageFactory.create(program=base_test_data.program, title="A Program Title") faculty = FacultyFactory.create_batch(3, program_page=page) info_links = InfoLinksFactory.create_batch(3, program_page=page) semester_dates = SemesterDateFactory.create_batch(3, program_page=page) program_courses = ProgramCourseFactory.create_batch( len(courses), program_page=page, course=Iterator(courses)) browser.get("/a-program-title/") faculty_elements = browser.driver.find_elements_by_css_selector( ".faculty-tile") assert len(faculty) == len(faculty_elements) info_elements = browser.driver.find_elements_by_css_selector( ".program-contact-link") assert len(info_links) == len(info_elements) semester_elements = browser.driver.find_elements_by_css_selector( ".semester-date") assert len(semester_dates) == len(semester_elements) program_course_elements = browser.driver.find_elements_by_css_selector( ".program-course .title") assert len(program_courses) == len(program_course_elements)
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 test_program_page(browser, base_test_data, logged_in_student): """ Test viewing the program page """ courses = list(base_test_data.program.course_set.all()) + \ CourseFactory.create_batch(2, program=base_test_data.program) page = ProgramPageFactory.create(program=base_test_data.program, title="A Program Title") faculty = FacultyFactory.create_batch(3, program_page=page) info_links = InfoLinksFactory.create_batch(3, program_page=page) semester_dates = SemesterDateFactory.create_batch(3, program_page=page) program_courses = ProgramCourseFactory.create_batch( len(courses), program_page=page, course=Iterator(courses) ) browser.get("/a-program-title/") faculty_elements = browser.driver.find_elements_by_css_selector(".faculty-tile") assert len(faculty) == len(faculty_elements) info_elements = browser.driver.find_elements_by_css_selector(".program-contact-link") assert len(info_links) == len(info_elements) semester_elements = browser.driver.find_elements_by_css_selector(".semester-date") assert len(semester_dates) == len(semester_elements) program_course_elements = browser.driver.find_elements_by_css_selector(".program-course .title") assert len(program_courses) == len(program_course_elements)
def test_program_enrolled_user_serializer(self): # pylint: disable=no-self-use """ Asserts the output of the serializer for program-enrolled users (ProgramEnrollments) """ with mute_signals(post_save): profile = ProfileFactory.create() EducationFactory.create(profile=profile) EmploymentFactory.create(profile=profile) program = ProgramFactory.create() course = CourseFactory.create(program=program) course_runs = [ CourseRunFactory.create(course=course) for _ in range(2) ] for course_run in course_runs: CachedCertificateFactory.create(user=profile.user, course_run=course_run) CachedEnrollmentFactory.create(user=profile.user, course_run=course_run) program_enrollment = ProgramEnrollment.objects.create( user=profile.user, program=program) assert serialize_program_enrolled_user(program_enrollment) == { '_id': program_enrollment.id, 'id': program_enrollment.id, 'user_id': profile.user.id, 'email': profile.user.email, 'profile': ProfileSerializer().to_representation(profile), 'program': UserProgramSerializer.serialize(program_enrollment) }
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_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 test_user_exists(self): """If no uid not set, 400""" course = CourseFactory.create() author = EdxAuthorFactory.create(edx_uid=str(uuid.uuid4().hex)) course.instructors.add(author) resp = self.client.get(reverse('user-existence'), {'uid': author.edx_uid}) self.assertEqual(resp.status_code, 200) self.assertEqual(json.loads(resp.content.decode('utf-8')), {'exists': True})
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_course_page(): """ page property should return an associated Wagtail page if one exists """ course = CourseFactory.create(page=None) assert course.page is None page = CoursePageFactory.create(course=course) assert course.page == page
def test_course_team_email_with_no_enrollment(self): """ Test that an attempt to send an email to a course in an un-enrolled program will fail """ self.client.force_login(self.staff_user) new_course = CourseFactory.create(contact_email='*****@*****.**') url = reverse(self.url_name, kwargs={'course_id': new_course.id}) resp = self.client.post(url, data=self.request_data, format='json') assert resp.status_code == status.HTTP_403_FORBIDDEN
def test_courses_not_live_in_programs_api(client, live): """Courses should be filtered out of the programs API if not live""" course = CourseFactory.create(live=live, program__live=True) ProductVersionFactory.create(product=ProductFactory( content_object=course.program)) resp = client.get(reverse("programs_api-list")) assert resp.status_code == status.HTTP_200_OK assert_drf_json_equal(resp.json()[0]["courses"], [CourseSerializer(course).data] if live else [])
def handle(self, *args, **options): # Check if we have a semester try: semester = Semester.get_current() course = CourseFactory.create(semester = semester) except IndexError: course = CourseFactory.create() self.stdout.write('Created Course {}.\n'.format(course)) assignment = AssignmentFactory.create(course = course) self.stdout.write('Created Assignment {}.\n'.format(assignment)) faculty = FacultyFactory.create() course.faculty.add(faculty) self.stdout.write('Created Faculty {} and assigned to course.\n'.format(faculty)) self.stdout.write('Successfully populated DB.\n')
def test_lookup_by_non_pk(self): """ Should be able to look things up by uuid too. """ WebhookFactory.create(url="http://example.org") course = CourseFactory.create() with mock.patch('webhooks.tasks.requests', autospec=True) as mock_requests: publish_webhook('courses.Course', 'uuid', course.uuid) assert mock_requests.post.call_count == 1
def test_autogenerated_hash(self): """Test that MicromastersCourseCertificate auto-generates a hash when none is provided""" user = UserFactory.create() course = CourseFactory.create() mm_certificate = MicromastersCourseCertificate.objects.create( user=user, course=course) assert len(mm_certificate.hash) == 32 assert mm_certificate.hash == generate_md5('{}|{}'.format( user.id, course.id).encode('utf-8'))
def test_course_available_runs(): """enrolled runs for a user should not be in the list of available runs""" user = UserFactory.create() course = CourseFactory.create() runs = CourseRunFactory.create_batch(2, course=course, live=True) runs.sort(key=lambda run: run.start_date) CourseRunEnrollmentFactory.create(run=runs[0], user=user) assert course.available_runs(user) == [runs[1]] assert course.available_runs(UserFactory.create()) == runs
def test_lookup_by_nonexistent_field(self): """ Properly handles error if non-existent field provided. """ WebhookFactory.create(url="http://example.org") course = CourseFactory.create() with mock.patch('webhooks.tasks.requests', autospec=True): with pytest.raises(FieldError): publish_webhook('courses.Course', 'asdf', course.pk)
def test_program_first_course_unexpired_runs(): """ first_course_unexpired_runs should return the unexpired course runs of the first course in the program (position_in_program=1) """ program = ProgramFactory.create() now = now_in_utc() past_start_dates = [ now + timedelta(days=-10), now + timedelta(days=-11), now + timedelta(days=-12), ] past_end_dates = [now + timedelta(days=-5), now + timedelta(days=-6)] future_end_dates = [ now + timedelta(days=10), now + timedelta(days=11), now + timedelta(days=12), ] first_course = CourseFactory.create(live=True, program=program, position_in_program=1) second_course = CourseFactory.create(live=True, program=program, position_in_program=2) CourseRunFactory.create_batch( 2, course=second_course, start_date=factory.Iterator(past_start_dates), end_date=factory.Iterator(past_end_dates), live=True, ) CourseRunFactory.create_batch( 3, course=first_course, start_date=factory.Iterator(past_start_dates), end_date=factory.Iterator(future_end_dates), enrollment_end=factory.Iterator(future_end_dates), live=True, ) assert len(program.first_course_unexpired_runs) == 3
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_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_course_team_email_unpaid(self): """ Test that an attempt to send an email to the course team of an unpaid course will fail """ self.client.force_login(self.staff_user) new_course = CourseFactory.create(contact_email='*****@*****.**') ProgramEnrollmentFactory.create(user=self.staff_user, program=new_course.program) url = reverse(self.url_name, kwargs={'course_id': new_course.id}) resp = self.client.post(url, data=self.request_data, format='json') assert resp.status_code == status.HTTP_403_FORBIDDEN
def setUpTestData(cls): super(DashboardTest, cls).setUpTestData() # create an user cls.user = UserFactory.create() # create a social auth for the user cls.user.social_auth.create( provider=EdxOrgOAuth2.name, uid="{}_edx".format(cls.user.username), extra_data='{"access_token": "fooooootoken"}') # create an enrollments object with open( os.path.join(os.path.dirname(__file__), 'fixtures/user_enrollments.json')) as file_obj: cls.enrollments_json = json.loads(file_obj.read()) cls.enrollments = Enrollments(cls.enrollments_json) with open( os.path.join(os.path.dirname(__file__), 'fixtures/certificates.json')) as file_obj: certificates_json = json.loads(file_obj.read()) cls.certificates = Certificates( [Certificate(cert_json) for cert_json in certificates_json]) # create the programs cls.program_1 = ProgramFactory.create(live=True) cls.program_2 = ProgramFactory.create(live=True) cls.program_no_live = ProgramFactory.create(live=False) # create some courses for each program cls.courses_1 = [] cls.courses_2 = [] for num in range(2): cls.courses_1.append( CourseFactory.create(title="title course prog1 {}".format(num), program=cls.program_1)) cls.courses_2.append( CourseFactory.create(title="title course prog2 {}".format(num), program=cls.program_2)) # url for the dashboard cls.url = reverse('dashboard_api')
def handle(self, *args, **options): # Check if we have a semester try: semester = Semester.get_current() course = CourseFactory.create(semester=semester) except IndexError: course = CourseFactory.create() self.stdout.write('Created Course {}.\n'.format(course)) assignment = AssignmentFactory.create(course=course) self.stdout.write('Created Assignment {}.\n'.format(assignment)) faculty = FacultyFactory.create() course.faculty.add(faculty) self.stdout.write( 'Created Faculty {} and assigned to course.\n'.format(faculty)) self.stdout.write('Successfully populated DB.\n')
def test_create_course_certificate(self, generate_program_cert_mock, mock_on_commit): """ Test that generate_program_certificate is called when a course certificate is created """ course = CourseFactory.create() cert = MicromastersCourseCertificateFactory.create(user=self.user, course=course) generate_program_cert_mock.assert_called_once_with(self.user, course.program) cert.save() generate_program_cert_mock.assert_called_once_with(self.user, course.program)
def test_returns_string_for_all_objects(self): # pylint: disable=no-self-use """model-to-string returns correct strings""" e1 = EdxAuthorFactory.create() e2 = EdxAuthorFactory.create() co = CourseFactory.create() co.instructors.add(e1) co.instructors.add(e2) f = SMMF(model=EdxAuthor, lookup="edx_uid") assert sorted([str(e1), str(e2)]) == sorted(f.to_representation(co.instructors))
def _generate_cached_enrollments(user, program, num_course_runs=1, data=None): """ Helper method to generate CachedEnrollments for test cases """ course = CourseFactory.create(program=program) course_runs = [CourseRunFactory.create(course=course) 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_elective_course(self): """ Make sure elective course serializes properly """ course = CourseFactory.create() elective_set = ElectivesSet.objects.create(program=course.program, required_number=1) ElectiveCourse.objects.create(course=course, electives_set=elective_set) data = CourseSerializer(course).data assert data['elective_tag'] == 'elective'
def test_disable_faculty(self): """ Tests if our tasks will disable inactive faculty """ faculty = FacultyFactory.create() current_semester = SemesterFactory.create(end=datetime.now().date() - timedelta(days=1)) next_semester = SemesterFactory.create( start=datetime.now().date() + timedelta(days=60), end=datetime.now().date() + timedelta(days=90) ) current_course = CourseFactory.create(semester=current_semester) next_course = CourseFactory.create(semester=next_semester) current_course.faculty.add(faculty) disable_faculty() faculty = User.objects.get(username=faculty.username) self.assertEquals(faculty.is_active, False)
def test_add_edx_record(self, index_type, mock_on_commit): """ Test that cached edX records are indexed after being added """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [CachedCertificateFactory, CachedEnrollmentFactory, CachedCurrentGradeFactory]: assert es.search(index_type)['total'] == DOC_TYPES_PER_ENROLLMENT course = CourseFactory.create(program=program_enrollment.program) course_run = CourseRunFactory.create(course=course) edx_cached_model_factory.create(user=program_enrollment.user, course_run=course_run) index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_model_posts_to_endpoint(self): """ Happy case of posting. """ WebhookFactory.create(url="http://example.org") course = CourseFactory.create() with mock.patch('webhooks.tasks.requests', autospec=True) as mock_requests: publish_webhook('courses.Course', 'pk', course.pk) assert mock_requests.post.call_count == 1 _, kwargs = mock_requests.post.call_args payload = kwargs['json'] assert isinstance(payload, dict) assert payload['action'] == 'update'
def create(cls, **kwargs): """ Overrides default ProgramEnrollment object creation for the factory. """ user = kwargs.get('user', UserFactory.create()) program = kwargs.get('program', ProgramFactory.create()) course = CourseFactory.create(program=program) course_run = CourseRunFactory.create(course=course) CachedEnrollmentFactory.create(user=user, course_run=course_run) CachedCertificateFactory.create(user=user, course_run=course_run) CachedCurrentGradeFactory.create(user=user, course_run=course_run) program_enrollment = ProgramEnrollment.objects.create(user=user, program=program) return program_enrollment
def setUpTestData(cls): with mute_signals(post_save): cls.profile = ProfileFactory.create() EducationFactory.create(profile=cls.profile) EmploymentFactory.create(profile=cls.profile) EmploymentFactory.create(profile=cls.profile, end_date=None) program = ProgramFactory.create() course = CourseFactory.create(program=program) course_runs = [CourseRunFactory.create(course=course) for _ in range(2)] for course_run in course_runs: CachedCertificateFactory.create(user=cls.profile.user, course_run=course_run) CachedEnrollmentFactory.create(user=cls.profile.user, course_run=course_run) cls.program_enrollment = ProgramEnrollment.objects.create(user=cls.profile.user, program=program)
def test_module_save_publishes(self): """ When module is saved, it should trigger webhook. """ course = CourseFactory.create() module = ModuleFactory.build(course=course) with mock.patch('courses.signals.publish_webhook', autospec=True) as wh_mock: module.save() assert wh_mock.delay.call_count == 1 args, _ = wh_mock.delay.call_args assert args[0] == 'courses.Module' assert args[1] == 'uuid' assert args[2] == str(module.uuid)
def test_course_save_publishes(self): """ When course is saved, it should trigger webhook. """ bi = BackingInstanceFactory.create() course = CourseFactory.build(edx_instance=bi) with mock.patch('courses.signals.publish_webhook', autospec=True) as wh_mock: course.save() assert wh_mock.delay.call_count == 1 args, _ = wh_mock.delay.call_args assert args[0] == 'courses.Course' assert args[1] == 'uuid' assert args[2] == str(course.uuid)
def test_one_post_of_many_failing(self): """ Validates that if one post fails they don't all fail. """ WebhookFactory.create(url="http://example.org") WebhookFactory.create(url="http://example.com") course = CourseFactory.create() with mock.patch('webhooks.tasks.requests', autospec=True) as mock_requests: response = Response() response._content = b"" # pylint: disable=protected-access response.status_code = 400 mock_requests.post.side_effect = [RequestException("couldn't post"), response] publish_webhook('courses.Course', 'pk', course.pk) assert mock_requests.post.call_count == 2
def test_get_course_list(self): """ The course list API should list all courses available. """ course = CourseFactory.create() resp = self.client.get(reverse('course-list')) assert resp.status_code == 200, resp.content.decode('utf-8') course_list = json.loads(resp.content.decode('utf-8')) assert course_list == [course_detail_dict(course)] # Make sure users not logged in can't list courses self.client.logout() resp = self.client.get(reverse('course-list')) assert resp.status_code == 401, resp.content.decode('utf-8')
def test_get_course_detail(self): """ The course detail API should show information about a specific course. """ course = CourseFactory.create() resp = self.client.get(reverse('course-detail', kwargs={"uuid": str(course.uuid)})) assert resp.status_code == 200, resp.content.decode('utf-8') course_detail = json.loads(resp.content.decode('utf-8')) assert course_detail == course_detail_dict(course) # Make sure users not logged in can't see the course detail view self.client.logout() resp = self.client.get(reverse('course-detail', kwargs={"uuid": str(course.uuid)})) assert resp.status_code == 401, resp.content.decode('utf-8')
def test_course(self): """ Make sure course serializes correctly """ course = CourseFactory.create() data = CourseSerializer(course).data expected = { "id": course.id, "title": course.title, "description": course.description, "url": "", "enrollment_text": "Not available", } assert data == expected
def test_delete_edx_record(self, index_type, mock_on_commit): """ Test that a cached edX record is removed from index after being deleted """ program_enrollment = ProgramEnrollmentFactory.create() for edx_cached_model_factory in [CachedCertificateFactory, CachedEnrollmentFactory, CachedCurrentGradeFactory]: course = CourseFactory.create(program=program_enrollment.program) course_run = CourseRunFactory.create(course=course) edx_record = edx_cached_model_factory.create(user=program_enrollment.user, course_run=course_run) index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type) edx_record.delete() index_program_enrolled_users([program_enrollment]) assert_search(es.search(index_type), [program_enrollment], index_type=index_type)
def test_send_to_course_team_without_email(self, mock_post): """ Tests that an attempt to send an email to a course with no contact email will fail """ course_no_email = CourseFactory.create(title='course no email', contact_email=None) with self.assertRaises(ImproperlyConfigured) as ex: MailgunClient.send_course_team_email( self.user, course_no_email, 'email subject', 'email body' ) assert ex.exception.args[0].startswith('Course team contact email attempted') assert not mock_post.called