Пример #1
0
def add_entrance_exam_milestone(course_id, x_block):
    # Add an entrance exam milestone if one does not already exist for given xBlock
    # As this is a standalone method for entrance exam, We should check that given xBlock should be an entrance exam.
    if x_block.is_entrance_exam:
        namespace_choices = milestones_helpers.get_namespace_choices()
        milestone_namespace = milestones_helpers.generate_milestone_namespace(
            namespace_choices.get('ENTRANCE_EXAM'),
            course_id
        )
        milestones = milestones_helpers.get_milestones(milestone_namespace)
        if len(milestones):
            milestone = milestones[0]
        else:
            description = u'Autogenerated during {} entrance exam creation.'.format(six.text_type(course_id))
            milestone = milestones_helpers.add_milestone({
                'name': _('Completed Course Entrance Exam'),
                'namespace': milestone_namespace,
                'description': description
            })
        relationship_types = milestones_helpers.get_milestone_relationship_types()
        milestones_helpers.add_course_milestone(
            six.text_type(course_id),
            relationship_types['REQUIRES'],
            milestone
        )
        milestones_helpers.add_course_content_milestone(
            six.text_type(course_id),
            six.text_type(x_block.location),
            relationship_types['FULFILLS'],
            milestone
        )
Пример #2
0
def add_entrance_exam_milestone(course, entrance_exam):
    """
    Adds the milestone for given `entrance_exam` in `course`

    Args:
        course (Course): Course object in which the extrance_exam is located
        entrance_exam (xblock): the entrance exam to be added as a milestone
    """
    namespace_choices = get_namespace_choices()
    milestone_relationship_types = get_milestone_relationship_types()

    milestone_namespace = generate_milestone_namespace(
        namespace_choices.get('ENTRANCE_EXAM'),
        course.id
    )
    milestone = add_milestone(
        {
            'name': 'Test Milestone',
            'namespace': milestone_namespace,
            'description': 'Testing Courseware Entrance Exam Chapter',
        }
    )
    add_course_milestone(
        unicode(course.id),
        milestone_relationship_types['REQUIRES'],
        milestone
    )
    add_course_content_milestone(
        unicode(course.id),
        unicode(entrance_exam.location),
        milestone_relationship_types['FULFILLS'],
        milestone
    )
Пример #3
0
def add_entrance_exam_milestone(course_id, x_block):
    # Add an entrance exam milestone if one does not already exist for given xBlock
    # As this is a standalone method for entrance exam, We should check that given xBlock should be an entrance exam.
    if x_block.is_entrance_exam:
        namespace_choices = milestones_helpers.get_namespace_choices()
        milestone_namespace = milestones_helpers.generate_milestone_namespace(
            namespace_choices.get('ENTRANCE_EXAM'),
            course_id
        )
        milestones = milestones_helpers.get_milestones(milestone_namespace)
        if len(milestones):
            milestone = milestones[0]
        else:
            description = 'Autogenerated during {} entrance exam creation.'.format(unicode(course_id))
            milestone = milestones_helpers.add_milestone({
                'name': _('Completed Course Entrance Exam'),
                'namespace': milestone_namespace,
                'description': description
            })
        relationship_types = milestones_helpers.get_milestone_relationship_types()
        milestones_helpers.add_course_milestone(
            unicode(course_id),
            relationship_types['REQUIRES'],
            milestone
        )
        milestones_helpers.add_course_content_milestone(
            unicode(course_id),
            unicode(x_block.location),
            relationship_types['FULFILLS'],
            milestone
        )
Пример #4
0
 def test_get_course_tabs_list_entrance_exam_enabled(self):
     """
     Unit Test: test_get_course_tabs_list_entrance_exam_enabled
     """
     entrance_exam = ItemFactory.create(
         category="chapter",
         parent_location=self.course.location,
         data="Exam Data",
         display_name="Entrance Exam",
         is_entrance_exam=True)
     milestone = {
         'name': 'Test Milestone',
         'namespace': '{}.entrance_exams'.format(unicode(self.course.id)),
         'description': 'Testing Courseware Tabs'
     }
     self.user.is_staff = False
     request = get_mock_request(self.user)
     self.course.entrance_exam_enabled = True
     self.course.entrance_exam_id = unicode(entrance_exam.location)
     milestone = add_milestone(milestone)
     add_course_milestone(unicode(self.course.id),
                          self.relationship_types['REQUIRES'], milestone)
     add_course_content_milestone(unicode(self.course.id),
                                  unicode(entrance_exam.location),
                                  self.relationship_types['FULFILLS'],
                                  milestone)
     course_tab_list = get_course_tab_list(request, self.course)
     self.assertEqual(len(course_tab_list), 1)
     self.assertEqual(course_tab_list[0]['tab_id'], 'courseware')
     self.assertEqual(course_tab_list[0]['name'], 'Entrance Exam')
Пример #5
0
 def test_get_course_tabs_list_entrance_exam_enabled(self):
     """
     Unit Test: test_get_course_tabs_list_entrance_exam_enabled
     """
     entrance_exam = ItemFactory.create(
         category="chapter",
         parent_location=self.course.location,
         data="Exam Data",
         display_name="Entrance Exam",
         is_entrance_exam=True
     )
     milestone = {
         'name': 'Test Milestone',
         'namespace': '{}.entrance_exams'.format(unicode(self.course.id)),
         'description': 'Testing Courseware Tabs'
     }
     self.user.is_staff = False
     self.course.entrance_exam_enabled = True
     self.course.entrance_exam_id = unicode(entrance_exam.location)
     milestone = milestones_helpers.add_milestone(milestone)
     milestones_helpers.add_course_milestone(
         unicode(self.course.id),
         self.relationship_types['REQUIRES'],
         milestone
     )
     milestones_helpers.add_course_content_milestone(
         unicode(self.course.id),
         unicode(entrance_exam.location),
         self.relationship_types['FULFILLS'],
         milestone
     )
     course_tab_list = get_course_tab_list(self.course, self.user)
     self.assertEqual(len(course_tab_list), 1)
     self.assertEqual(course_tab_list[0]['tab_id'], 'courseware')
     self.assertEqual(course_tab_list[0]['name'], 'Entrance Exam')
Пример #6
0
 def test_get_course_tabs_list_entrance_exam_enabled(self):
     """
     Unit Test: test_get_course_tabs_list_entrance_exam_enabled
     """
     entrance_exam = ItemFactory.create(
         category="chapter", parent_location=self.course.location, data="Exam Data", display_name="Entrance Exam"
     )
     entrance_exam.is_entrance_exam = True
     milestone = {
         "name": "Test Milestone",
         "namespace": "{}.entrance_exams".format(unicode(self.course.id)),
         "description": "Testing Courseware Tabs",
     }
     self.course.entrance_exam_enabled = True
     self.course.entrance_exam_id = unicode(entrance_exam.location)
     milestone = milestones_helpers.add_milestone(milestone)
     milestones_helpers.add_course_milestone(
         unicode(self.course.id), self.relationship_types["REQUIRES"], milestone
     )
     milestones_helpers.add_course_content_milestone(
         unicode(self.course.id), unicode(entrance_exam.location), self.relationship_types["FULFILLS"], milestone
     )
     course_tab_list = get_course_tab_list(self.course, self.user)
     self.assertEqual(len(course_tab_list), 2)
     self.assertEqual(course_tab_list[0]["tab_id"], "courseware")
     self.assertEqual(course_tab_list[0]["name"], "Entrance Exam")
     self.assertEqual(course_tab_list[1]["tab_id"], "instructor")
Пример #7
0
    def test_get_required_content_with_anonymous_user(self):
        course = CourseFactory()

        required_content = milestones_helpers.get_required_content(course.id, AnonymousUser())
        assert required_content == []

        # NOTE (CCB): The initial version of anonymous courseware access is very simple. We avoid accidentally
        # exposing locked content by simply avoiding anonymous access altogether for courses runs with milestones.
        milestone = milestones_api.add_milestone({
            'name': 'test',
            'namespace': 'test',
        })
        milestones_helpers.add_course_milestone(str(course.id), 'requires', milestone)
        with pytest.raises(InvalidUserException):
            milestones_helpers.get_required_content(course.id, AnonymousUser())
Пример #8
0
def _create_entrance_exam(request,
                          course_key,
                          entrance_exam_minimum_score_pct=None):
    """
    Internal workflow operation to create an entrance exam
    """
    # Provide a default value for the minimum score percent if nothing specified
    if entrance_exam_minimum_score_pct is None:
        entrance_exam_minimum_score_pct = _get_default_entrance_exam_minimum_pct(
        )

    # Confirm the course exists
    course = modulestore().get_course(course_key)
    if course is None:
        return HttpResponse(status=400)

    # Create the entrance exam item (currently it's just a chapter)
    payload = {
        'category': "chapter",
        'display_name': _("Entrance Exam"),
        'parent_locator': unicode(course.location),
        'is_entrance_exam': True,
        'in_entrance_exam': True,
    }
    parent_locator = unicode(course.location)
    created_block = create_xblock(parent_locator=parent_locator,
                                  user=request.user,
                                  category='chapter',
                                  display_name=_('Entrance Exam'),
                                  is_entrance_exam=True)

    # Set the entrance exam metadata flags for this course
    # Reload the course so we don't overwrite the new child reference
    course = modulestore().get_course(course_key)
    metadata = {
        'entrance_exam_enabled': True,
        'entrance_exam_minimum_score_pct':
        unicode(entrance_exam_minimum_score_pct),
        'entrance_exam_id': unicode(created_block.location),
    }
    CourseMetadata.update_from_dict(metadata, course, request.user)

    # Create the entrance exam section item.
    create_xblock(parent_locator=unicode(created_block.location),
                  user=request.user,
                  category='sequential',
                  display_name=_('Entrance Exam - Subsection'))

    # Add an entrance exam milestone if one does not already exist
    namespace_choices = milestones_helpers.get_namespace_choices()
    milestone_namespace = milestones_helpers.generate_milestone_namespace(
        namespace_choices.get('ENTRANCE_EXAM'), course_key)
    milestones = milestones_helpers.get_milestones(milestone_namespace)
    if len(milestones):
        milestone = milestones[0]
    else:
        description = 'Autogenerated during {} entrance exam creation.'.format(
            unicode(course.id))
        milestone = milestones_helpers.add_milestone({
            'name':
            _('Completed Course Entrance Exam'),
            'namespace':
            milestone_namespace,
            'description':
            description
        })
    relationship_types = milestones_helpers.get_milestone_relationship_types()
    milestones_helpers.add_course_milestone(unicode(course.id),
                                            relationship_types['REQUIRES'],
                                            milestone)
    milestones_helpers.add_course_content_milestone(
        unicode(course.id), unicode(created_block.location),
        relationship_types['FULFILLS'], milestone)

    return HttpResponse(status=201)
Пример #9
0
 def test_add_course_milestone_returns_none_when_app_disabled(self):
     response = milestones_helpers.add_course_milestone(unicode(self.course.id), 'requires', self.milestone)
     self.assertIsNone(response)
Пример #10
0
    def setUp(self):
        """
        Test case scaffolding
        """
        super(EntranceExamTestCases, self).setUp()
        self.course = CourseFactory.create(metadata={
            'entrance_exam_enabled': True,
        })
        self.chapter = ItemFactory.create(parent=self.course,
                                          display_name='Overview')
        ItemFactory.create(parent=self.chapter, display_name='Welcome')
        ItemFactory.create(parent=self.course,
                           category='chapter',
                           display_name="Week 1")
        self.chapter_subsection = ItemFactory.create(parent=self.chapter,
                                                     category='sequential',
                                                     display_name="Lesson 1")
        chapter_vertical = ItemFactory.create(
            parent=self.chapter_subsection,
            category='vertical',
            display_name='Lesson 1 Vertical - Unit 1')
        ItemFactory.create(parent=chapter_vertical,
                           category="problem",
                           display_name="Problem - Unit 1 Problem 1")
        ItemFactory.create(parent=chapter_vertical,
                           category="problem",
                           display_name="Problem - Unit 1 Problem 2")

        ItemFactory.create(category="instructor",
                           parent=self.course,
                           data="Instructor Tab",
                           display_name="Instructor")
        self.entrance_exam = ItemFactory.create(
            parent=self.course,
            category="chapter",
            display_name="Entrance Exam Section - Chapter 1",
            is_entrance_exam=True,
            in_entrance_exam=True)
        self.exam_1 = ItemFactory.create(
            parent=self.entrance_exam,
            category='sequential',
            display_name="Exam Sequential - Subsection 1",
            graded=True,
            in_entrance_exam=True)
        subsection = ItemFactory.create(parent=self.exam_1,
                                        category='vertical',
                                        display_name='Exam Vertical - Unit 1')
        self.problem_1 = ItemFactory.create(
            parent=subsection,
            category="problem",
            display_name="Exam Problem - Problem 1")
        self.problem_2 = ItemFactory.create(
            parent=subsection,
            category="problem",
            display_name="Exam Problem - Problem 2")
        self.problem_3 = ItemFactory.create(
            parent=subsection,
            category="problem",
            display_name="Exam Problem - Problem 3")
        if settings.FEATURES.get('ENTRANCE_EXAMS', False):
            namespace_choices = milestones_helpers.get_namespace_choices()
            milestone_namespace = milestones_helpers.generate_milestone_namespace(
                namespace_choices.get('ENTRANCE_EXAM'), self.course.id)
            self.milestone = {
                'name': 'Test Milestone',
                'namespace': milestone_namespace,
                'description': 'Testing Courseware Entrance Exam Chapter',
            }
            milestones_helpers.seed_milestone_relationship_types()
            self.milestone_relationship_types = milestones_helpers.get_milestone_relationship_types(
            )
            self.milestone = milestones_helpers.add_milestone(self.milestone)
            milestones_helpers.add_course_milestone(
                unicode(self.course.id),
                self.milestone_relationship_types['REQUIRES'], self.milestone)
            milestones_helpers.add_course_content_milestone(
                unicode(self.course.id), unicode(self.entrance_exam.location),
                self.milestone_relationship_types['FULFILLS'], self.milestone)
        user = UserFactory()
        self.request = RequestFactory()
        self.request.user = user
        self.request.COOKIES = {}
        self.request.META = {}
        self.request.is_secure = lambda: True
        self.request.get_host = lambda: "edx.org"
        self.request.method = 'GET'
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, user, self.entrance_exam)
        self.course.entrance_exam_enabled = True
        self.course.entrance_exam_minimum_score_pct = 0.50
        self.course.entrance_exam_id = unicode(
            self.entrance_exam.scope_ids.usage_id)
        modulestore().update_item(self.course, user.id)  # pylint: disable=no-member

        self.client.login(username=self.request.user.username, password="******")
        CourseEnrollment.enroll(self.request.user, self.course.id)

        self.expected_locked_toc = ([{
            'active':
            True,
            'sections': [{
                'url_name': u'Exam_Sequential_-_Subsection_1',
                'display_name': u'Exam Sequential - Subsection 1',
                'graded': True,
                'format': '',
                'due': None,
                'active': True
            }],
            'url_name':
            u'Entrance_Exam_Section_-_Chapter_1',
            'display_name':
            u'Entrance Exam Section - Chapter 1'
        }])
        self.expected_unlocked_toc = ([{
            'active':
            False,
            'sections': [{
                'url_name': u'Welcome',
                'display_name': u'Welcome',
                'graded': False,
                'format': '',
                'due': None,
                'active': False
            }, {
                'url_name': u'Lesson_1',
                'display_name': u'Lesson 1',
                'graded': False,
                'format': '',
                'due': None,
                'active': False
            }],
            'url_name':
            u'Overview',
            'display_name':
            u'Overview'
        }, {
            'active': False,
            'sections': [],
            'url_name': u'Week_1',
            'display_name': u'Week 1'
        }, {
            'active': False,
            'sections': [],
            'url_name': u'Instructor',
            'display_name': u'Instructor'
        }, {
            'active':
            True,
            'sections': [{
                'url_name': u'Exam_Sequential_-_Subsection_1',
                'display_name': u'Exam Sequential - Subsection 1',
                'graded': True,
                'format': '',
                'due': None,
                'active': True
            }],
            'url_name':
            u'Entrance_Exam_Section_-_Chapter_1',
            'display_name':
            u'Entrance Exam Section - Chapter 1'
        }])
 def test_add_course_milestone_returns_none_when_app_disabled(self):
     response = milestones_helpers.add_course_milestone(unicode(self.course.id), 'requires', self.milestone)
     self.assertIsNone(response)
Пример #12
0
def _create_entrance_exam(request, course_key, entrance_exam_minimum_score_pct=None):
    """
    Internal workflow operation to create an entrance exam
    """
    # Provide a default value for the minimum score percent if nothing specified
    if entrance_exam_minimum_score_pct is None:
        entrance_exam_minimum_score_pct = _get_default_entrance_exam_minimum_pct()

    # Confirm the course exists
    course = modulestore().get_course(course_key)
    if course is None:
        return HttpResponse(status=400)

    # Create the entrance exam item (currently it's just a chapter)
    payload = {
        'category': "chapter",
        'display_name': _("Entrance Exam"),
        'parent_locator': unicode(course.location),
        'is_entrance_exam': True,
        'in_entrance_exam': True,
    }
    parent_locator = unicode(course.location)
    created_block = create_xblock(
        parent_locator=parent_locator,
        user=request.user,
        category='chapter',
        display_name=_('Entrance Exam'),
        is_entrance_exam=True
    )

    # Set the entrance exam metadata flags for this course
    # Reload the course so we don't overwrite the new child reference
    course = modulestore().get_course(course_key)
    metadata = {
        'entrance_exam_enabled': True,
        'entrance_exam_minimum_score_pct': unicode(entrance_exam_minimum_score_pct),
        'entrance_exam_id': unicode(created_block.location),
    }
    CourseMetadata.update_from_dict(metadata, course, request.user)

    # Create the entrance exam section item.
    create_xblock(
        parent_locator=unicode(created_block.location),
        user=request.user,
        category='sequential',
        display_name=_('Entrance Exam - Subsection')
    )

    # Add an entrance exam milestone if one does not already exist
    namespace_choices = milestones_helpers.get_namespace_choices()
    milestone_namespace = milestones_helpers.generate_milestone_namespace(
        namespace_choices.get('ENTRANCE_EXAM'),
        course_key
    )
    milestones = milestones_helpers.get_milestones(milestone_namespace)
    if len(milestones):
        milestone = milestones[0]
    else:
        description = 'Autogenerated during {} entrance exam creation.'.format(unicode(course.id))
        milestone = milestones_helpers.add_milestone({
            'name': _('Completed Course Entrance Exam'),
            'namespace': milestone_namespace,
            'description': description
        })
    relationship_types = milestones_helpers.get_milestone_relationship_types()
    milestones_helpers.add_course_milestone(
        unicode(course.id),
        relationship_types['REQUIRES'],
        milestone
    )
    milestones_helpers.add_course_content_milestone(
        unicode(course.id),
        unicode(created_block.location),
        relationship_types['FULFILLS'],
        milestone
    )

    return HttpResponse(status=201)
Пример #13
0
    def setUp(self):
        """
        Test case scaffolding
        """
        super(EntranceExamTestCases, self).setUp()
        self.course = CourseFactory.create(
            metadata={
                'entrance_exam_enabled': True,
            }
        )
        self.chapter = ItemFactory.create(
            parent=self.course,
            display_name='Overview'
        )
        ItemFactory.create(
            parent=self.chapter,
            display_name='Welcome'
        )
        ItemFactory.create(
            parent=self.course,
            category='chapter',
            display_name="Week 1"
        )
        self.chapter_subsection = ItemFactory.create(
            parent=self.chapter,
            category='sequential',
            display_name="Lesson 1"
        )
        chapter_vertical = ItemFactory.create(
            parent=self.chapter_subsection,
            category='vertical',
            display_name='Lesson 1 Vertical - Unit 1'
        )
        ItemFactory.create(
            parent=chapter_vertical,
            category="problem",
            display_name="Problem - Unit 1 Problem 1"
        )
        ItemFactory.create(
            parent=chapter_vertical,
            category="problem",
            display_name="Problem - Unit 1 Problem 2"
        )

        ItemFactory.create(
            category="instructor",
            parent=self.course,
            data="Instructor Tab",
            display_name="Instructor"
        )
        self.entrance_exam = ItemFactory.create(
            parent=self.course,
            category="chapter",
            display_name="Entrance Exam Section - Chapter 1",
            is_entrance_exam=True,
            in_entrance_exam=True
        )
        self.exam_1 = ItemFactory.create(
            parent=self.entrance_exam,
            category='sequential',
            display_name="Exam Sequential - Subsection 1",
            graded=True,
            in_entrance_exam=True
        )
        subsection = ItemFactory.create(
            parent=self.exam_1,
            category='vertical',
            display_name='Exam Vertical - Unit 1'
        )
        self.problem_1 = ItemFactory.create(
            parent=subsection,
            category="problem",
            display_name="Exam Problem - Problem 1"
        )
        self.problem_2 = ItemFactory.create(
            parent=subsection,
            category="problem",
            display_name="Exam Problem - Problem 2"
        )
        self.problem_3 = ItemFactory.create(
            parent=subsection,
            category="problem",
            display_name="Exam Problem - Problem 3"
        )
        if settings.FEATURES.get('ENTRANCE_EXAMS', False):
            namespace_choices = milestones_helpers.get_namespace_choices()
            milestone_namespace = milestones_helpers.generate_milestone_namespace(
                namespace_choices.get('ENTRANCE_EXAM'),
                self.course.id
            )
            self.milestone = {
                'name': 'Test Milestone',
                'namespace': milestone_namespace,
                'description': 'Testing Courseware Entrance Exam Chapter',
            }
            milestones_helpers.seed_milestone_relationship_types()
            self.milestone_relationship_types = milestones_helpers.get_milestone_relationship_types()
            self.milestone = milestones_helpers.add_milestone(self.milestone)
            milestones_helpers.add_course_milestone(
                unicode(self.course.id),
                self.milestone_relationship_types['REQUIRES'],
                self.milestone
            )
            milestones_helpers.add_course_content_milestone(
                unicode(self.course.id),
                unicode(self.entrance_exam.location),
                self.milestone_relationship_types['FULFILLS'],
                self.milestone
            )
        user = UserFactory()
        self.request = RequestFactory()
        self.request.user = user
        self.request.COOKIES = {}
        self.request.META = {}
        self.request.is_secure = lambda: True
        self.request.get_host = lambda: "edx.org"
        self.request.method = 'GET'
        self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id,
            user,
            self.entrance_exam
        )
        self.course.entrance_exam_enabled = True
        self.course.entrance_exam_minimum_score_pct = 0.50
        self.course.entrance_exam_id = unicode(self.entrance_exam.scope_ids.usage_id)
        modulestore().update_item(self.course, user.id)  # pylint: disable=no-member

        self.client.login(username=self.request.user.username, password="******")
        CourseEnrollment.enroll(self.request.user, self.course.id)

        self.expected_locked_toc = (
            [
                {
                    'active': True,
                    'sections': [
                        {
                            'url_name': u'Exam_Sequential_-_Subsection_1',
                            'display_name': u'Exam Sequential - Subsection 1',
                            'graded': True,
                            'format': '',
                            'due': None,
                            'active': True
                        }
                    ],
                    'url_name': u'Entrance_Exam_Section_-_Chapter_1',
                    'display_name': u'Entrance Exam Section - Chapter 1'
                }
            ]
        )
        self.expected_unlocked_toc = (
            [
                {
                    'active': False,
                    'sections': [
                        {
                            'url_name': u'Welcome',
                            'display_name': u'Welcome',
                            'graded': False,
                            'format': '',
                            'due': None,
                            'active': False
                        },
                        {
                            'url_name': u'Lesson_1',
                            'display_name': u'Lesson 1',
                            'graded': False,
                            'format': '',
                            'due': None,
                            'active': False
                        }
                    ],
                    'url_name': u'Overview',
                    'display_name': u'Overview'
                },
                {
                    'active': False,
                    'sections': [],
                    'url_name': u'Week_1',
                    'display_name': u'Week 1'
                },
                {
                    'active': False,
                    'sections': [],
                    'url_name': u'Instructor',
                    'display_name': u'Instructor'
                },
                {
                    'active': True,
                    'sections': [
                        {
                            'url_name': u'Exam_Sequential_-_Subsection_1',
                            'display_name': u'Exam Sequential - Subsection 1',
                            'graded': True,
                            'format': '',
                            'due': None,
                            'active': True
                        }
                    ],
                    'url_name': u'Entrance_Exam_Section_-_Chapter_1',
                    'display_name': u'Entrance Exam Section - Chapter 1'
                }
            ]
        )