コード例 #1
0
ファイル: models_test.py プロジェクト: mitodl/mitxpro
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
コード例 #2
0
ファイル: fields_test.py プロジェクト: mitodl/ccxcon
 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
コード例 #3
0
ファイル: models_test.py プロジェクト: mitodl/mitxpro
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
コード例 #4
0
ファイル: fields_test.py プロジェクト: mitodl/ccxcon
 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]
コード例 #5
0
    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
コード例 #6
0
    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
        )
コード例 #7
0
ファイル: models_test.py プロジェクト: mitodl/micromasters
    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
コード例 #8
0
ファイル: utils_test.py プロジェクト: mitodl/micromasters
    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
        )
コード例 #9
0
ファイル: models_test.py プロジェクト: mitodl/mitxpro
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
コード例 #10
0
 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,
     }
コード例 #11
0
 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,
     }
コード例 #12
0
ファイル: serializers_test.py プロジェクト: mitodl/mitxpro
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,
    }
コード例 #13
0
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 [])
コード例 #14
0
    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)
コード例 #15
0
    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,
        }
コード例 #16
0
    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
コード例 #17
0
ファイル: utils_test.py プロジェクト: mitodl/micromasters
    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
コード例 #18
0
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)
コード例 #19
0
    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
コード例 #20
0
 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
     ]
コード例 #21
0
ファイル: basic_test.py プロジェクト: mitodl/micromasters
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)
コード例 #22
0
ファイル: utils_test.py プロジェクト: mitodl/micromasters
    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
コード例 #23
0
    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)
        }
コード例 #24
0
 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
     ]
コード例 #25
0
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),
    }
コード例 #26
0
ファイル: views_test.py プロジェクト: mitodl/ccxcon
 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})
コード例 #27
0
 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
コード例 #28
0
ファイル: models_test.py プロジェクト: mitodl/mitxpro
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
コード例 #29
0
 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
コード例 #30
0
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 [])
コード例 #31
0
    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')
コード例 #32
0
ファイル: tasks_test.py プロジェクト: mitodl/ccxcon
 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
コード例 #33
0
 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'))
コード例 #34
0
ファイル: models_test.py プロジェクト: mitodl/mitxpro
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
コード例 #35
0
ファイル: tasks_test.py プロジェクト: mitodl/ccxcon
 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)
コード例 #36
0
ファイル: views_test.py プロジェクト: mitodl/micromasters
 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
コード例 #37
0
ファイル: models_test.py プロジェクト: mitodl/mitxpro
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
コード例 #38
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)
コード例 #39
0
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
コード例 #40
0
ファイル: views_test.py プロジェクト: mitodl/micromasters
 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
コード例 #41
0
    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')
コード例 #42
0
    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')
コード例 #43
0
ファイル: signals_test.py プロジェクト: mitodl/micromasters
 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)
コード例 #44
0
ファイル: fields_test.py プロジェクト: mitodl/ccxcon
    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))
コード例 #45
0
 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]
コード例 #46
0
 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'
コード例 #47
0
 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
コード例 #48
0
ファイル: tests.py プロジェクト: 7thZoneTechnology/Lms-4
    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)
コード例 #49
0
 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)
コード例 #50
0
ファイル: tasks_test.py プロジェクト: mitodl/ccxcon
 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'
コード例 #51
0
ファイル: factories.py プロジェクト: mitodl/micromasters
 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
コード例 #52
0
 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)
コード例 #53
0
ファイル: signals_test.py プロジェクト: mitodl/ccxcon
 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)
コード例 #54
0
ファイル: signals_test.py プロジェクト: mitodl/ccxcon
 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)
コード例 #55
0
ファイル: tasks_test.py プロジェクト: mitodl/ccxcon
 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
コード例 #56
0
ファイル: views_test.py プロジェクト: mitodl/ccxcon
    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')
コード例 #57
0
ファイル: views_test.py プロジェクト: mitodl/ccxcon
    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')
コード例 #58
0
 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
コード例 #59
0
 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)
コード例 #60
0
ファイル: api_test.py プロジェクト: mitodl/micromasters
 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