コード例 #1
0
class EntranceExamHandlerTests(CourseTestCase, MilestonesTestCaseMixin):
    """
    Base test class for create, save, and delete
    """
    def setUp(self):
        """
        Shared scaffolding for individual test runs
        """
        super(EntranceExamHandlerTests, self).setUp()
        self.course_key = self.course.id
        self.usage_key = self.course.location
        self.course_url = '/course/{}'.format(six.text_type(self.course.id))
        self.exam_url = '/course/{}/entrance_exam/'.format(
            six.text_type(self.course.id))
        self.milestone_relationship_types = milestones_helpers.get_milestone_relationship_types(
        )

    def test_entrance_exam_milestone_addition(self):
        """
        Unit Test: test addition of entrance exam milestone content
        """
        parent_locator = six.text_type(self.course.location)
        created_block = create_xblock(parent_locator=parent_locator,
                                      user=self.user,
                                      category='chapter',
                                      display_name=('Entrance Exam'),
                                      is_entrance_exam=True)
        add_entrance_exam_milestone(self.course.id, created_block)
        content_milestones = milestones_helpers.get_course_content_milestones(
            six.text_type(self.course.id),
            six.text_type(created_block.location),
            self.milestone_relationship_types['FULFILLS'])
        self.assertTrue(len(content_milestones))
        self.assertEqual(
            len(milestones_helpers.get_course_milestones(self.course.id)), 1)

    def test_entrance_exam_milestone_removal(self):
        """
        Unit Test: test removal of entrance exam milestone content
        """
        parent_locator = six.text_type(self.course.location)
        created_block = create_xblock(parent_locator=parent_locator,
                                      user=self.user,
                                      category='chapter',
                                      display_name=('Entrance Exam'),
                                      is_entrance_exam=True)
        add_entrance_exam_milestone(self.course.id, created_block)
        content_milestones = milestones_helpers.get_course_content_milestones(
            six.text_type(self.course.id),
            six.text_type(created_block.location),
            self.milestone_relationship_types['FULFILLS'])
        self.assertEqual(len(content_milestones), 1)
        user = UserFactory()
        request = RequestFactory().request()
        request.user = user
        remove_entrance_exam_milestone_reference(request, self.course.id)
        content_milestones = milestones_helpers.get_course_content_milestones(
            six.text_type(self.course.id),
            six.text_type(created_block.location),
            self.milestone_relationship_types['FULFILLS'])
        self.assertEqual(len(content_milestones), 0)

    def test_contentstore_views_entrance_exam_post(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post
        """
        resp = self.client.post(self.exam_url, {},
                                http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

        # Reload the test course now that the exam module has been added
        self.course = modulestore().get_course(self.course.id)
        metadata = CourseMetadata.fetch_all(self.course)
        self.assertTrue(metadata['entrance_exam_enabled'])
        self.assertIsNotNone(metadata['entrance_exam_minimum_score_pct'])
        self.assertIsNotNone(metadata['entrance_exam_id']['value'])
        self.assertTrue(
            len(
                milestones_helpers.get_course_milestones(
                    six.text_type(self.course.id))))
        content_milestones = milestones_helpers.get_course_content_milestones(
            six.text_type(self.course.id),
            metadata['entrance_exam_id']['value'],
            self.milestone_relationship_types['FULFILLS'])
        self.assertTrue(len(content_milestones))

    def test_contentstore_views_entrance_exam_post_new_sequential_confirm_grader(
            self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post
        """
        resp = self.client.post(self.exam_url, {},
                                http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

        # Reload the test course now that the exam module has been added
        self.course = modulestore().get_course(self.course.id)

        # Add a new child sequential to the exam module
        # Confirm that the grader type is 'Entrance Exam'
        chapter_locator_string = json.loads(
            resp.content.decode('utf-8')).get('locator')
        # chapter_locator = UsageKey.from_string(chapter_locator_string)
        seq_data = {
            'category': "sequential",
            'display_name': "Entrance Exam Subsection",
            'parent_locator': chapter_locator_string,
        }
        resp = self.client.ajax_post(reverse_url('xblock_handler'), seq_data)
        seq_locator_string = json.loads(
            resp.content.decode('utf-8')).get('locator')
        seq_locator = UsageKey.from_string(seq_locator_string)
        section_grader_type = CourseGradingModel.get_section_grader_type(
            seq_locator)
        self.assertEqual(GRADER_TYPES['ENTRANCE_EXAM'],
                         section_grader_type['graderType'])

    def test_contentstore_views_entrance_exam_get(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get
        """
        resp = self.client.post(self.exam_url, {
            'entrance_exam_minimum_score_pct':
            settings.ENTRANCE_EXAM_MIN_SCORE_PCT
        },
                                http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

    def test_contentstore_views_entrance_exam_delete(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_delete
        """
        resp = self.client.post(self.exam_url, {},
                                http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)
        resp = self.client.delete(self.exam_url)
        self.assertEqual(resp.status_code, 204)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 404)

        user = User.objects.create(
            username='******',
            email='*****@*****.**',
            is_active=True,
        )
        user.set_password('test')
        user.save()
        milestones = milestones_helpers.get_course_milestones(
            six.text_type(self.course_key))
        self.assertEqual(len(milestones), 1)
        milestone_key = '{}.{}'.format(milestones[0]['namespace'],
                                       milestones[0]['name'])
        paths = milestones_helpers.get_course_milestones_fulfillment_paths(
            six.text_type(self.course_key),
            milestones_helpers.serialize_user(user))

        # What we have now is a course milestone requirement and no valid fulfillment
        # paths for the specified user.  The LMS is going to have to ignore this situation,
        # because we can't confidently prevent it from occuring at some point in the future.
        # milestone_key_1 =
        self.assertEqual(len(paths[milestone_key]), 0)

        # Re-adding an entrance exam to the course should fix the missing link
        # It wipes out any old entrance exam artifacts and inserts a new exam course chapter/module
        resp = self.client.post(self.exam_url, {},
                                http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

        # Confirm that we have only one Entrance Exam grader after re-adding the exam (validates SOL-475)
        graders = CourseGradingModel.fetch(self.course_key).graders
        count = 0
        for grader in graders:
            if grader['type'] == GRADER_TYPES['ENTRANCE_EXAM']:
                count += 1
        self.assertEqual(count, 1)

    def test_contentstore_views_entrance_exam_delete_bogus_course(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_delete_bogus_course
        """
        resp = self.client.delete('/course/bad/course/key/entrance_exam')
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_get_bogus_course(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get_bogus_course
        """
        resp = self.client.get('/course/bad/course/key/entrance_exam')
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_get_bogus_exam(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get_bogus_exam
        """
        resp = self.client.post(self.exam_url,
                                {'entrance_exam_minimum_score_pct': '50'},
                                http_accept='application/json')

        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)
        self.course = modulestore().get_course(self.course.id)
        # Should raise an ItemNotFoundError and return a 404
        updated_metadata = {
            'entrance_exam_id':
            'i4x://org.4/course_4/chapter/ed7c4c6a4d68409998e2c8554c4629d1'
        }

        CourseMetadata.update_from_dict(
            updated_metadata,
            self.course,
            self.user,
        )
        self.course = modulestore().get_course(self.course.id)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 404)

        # Should raise an InvalidKeyError and return a 404
        updated_metadata = {'entrance_exam_id': '123afsdfsad90f87'}

        CourseMetadata.update_from_dict(
            updated_metadata,
            self.course,
            self.user,
        )
        self.course = modulestore().get_course(self.course.id)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 404)

    def test_contentstore_views_entrance_exam_post_bogus_course(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post_bogus_course
        """
        resp = self.client.post('/course/bad/course/key/entrance_exam', {},
                                http_accept='application/json')
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_post_invalid_http_accept(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post_invalid_http_accept
        """
        resp = self.client.post('/course/bad/course/key/entrance_exam', {},
                                http_accept='text/html')
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_get_invalid_user(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get_invalid_user
        """
        user = User.objects.create(
            username='******',
            email='*****@*****.**',
            is_active=True,
        )
        user.set_password('test')
        user.save()
        self.client = AjaxEnabledTestClient()
        self.client.login(username='******', password='******')
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 403)

    def test_contentstore_views_entrance_exam_unsupported_method(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_unsupported_method
        """
        resp = self.client.put(self.exam_url)
        self.assertEqual(resp.status_code, 405)

    def test_entrance_exam_view_direct_missing_score_setting(self):
        """
        Unit Test: test_entrance_exam_view_direct_missing_score_setting
        """
        user = UserFactory()
        user.is_staff = True
        request = RequestFactory()
        request.user = user

        resp = create_entrance_exam(request, self.course.id, None)
        self.assertEqual(resp.status_code, 201)

    @patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': False})
    def test_entrance_exam_feature_flag_gating(self):
        user = UserFactory()
        user.is_staff = True
        request = RequestFactory()
        request.user = user

        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 400)

        resp = create_entrance_exam(request, self.course.id, None)
        self.assertEqual(resp.status_code, 400)

        resp = delete_entrance_exam(request, self.course.id)
        self.assertEqual(resp.status_code, 400)

        # No return, so we'll just ensure no exception is thrown
        update_entrance_exam(request, self.course.id, {})
コード例 #2
0
class EntranceExamHandlerTests(CourseTestCase, MilestonesTestCaseMixin):
    """
    Base test class for create, save, and delete
    """
    def setUp(self):
        """
        Shared scaffolding for individual test runs
        """
        super(EntranceExamHandlerTests, self).setUp()
        self.course_key = self.course.id
        self.usage_key = self.course.location
        self.course_url = '/course/{}'.format(unicode(self.course.id))
        self.exam_url = '/course/{}/entrance_exam/'.format(unicode(self.course.id))
        self.milestone_relationship_types = milestones_helpers.get_milestone_relationship_types()

    def test_entrance_exam_milestone_addition(self):
        """
        Unit Test: test addition of entrance exam milestone content
        """
        parent_locator = unicode(self.course.location)
        created_block = create_xblock(
            parent_locator=parent_locator,
            user=self.user,
            category='chapter',
            display_name=('Entrance Exam'),
            is_entrance_exam=True
        )
        add_entrance_exam_milestone(self.course.id, created_block)
        content_milestones = milestones_helpers.get_course_content_milestones(
            unicode(self.course.id),
            unicode(created_block.location),
            self.milestone_relationship_types['FULFILLS']
        )
        self.assertTrue(len(content_milestones))
        self.assertEqual(len(milestones_helpers.get_course_milestones(self.course.id)), 1)

    def test_entrance_exam_milestone_removal(self):
        """
        Unit Test: test removal of entrance exam milestone content
        """
        parent_locator = unicode(self.course.location)
        created_block = create_xblock(
            parent_locator=parent_locator,
            user=self.user,
            category='chapter',
            display_name=('Entrance Exam'),
            is_entrance_exam=True
        )
        add_entrance_exam_milestone(self.course.id, created_block)
        content_milestones = milestones_helpers.get_course_content_milestones(
            unicode(self.course.id),
            unicode(created_block.location),
            self.milestone_relationship_types['FULFILLS']
        )
        self.assertEqual(len(content_milestones), 1)
        user = UserFactory()
        request = RequestFactory().request()
        request.user = user
        remove_entrance_exam_milestone_reference(request, self.course.id)
        content_milestones = milestones_helpers.get_course_content_milestones(
            unicode(self.course.id),
            unicode(created_block.location),
            self.milestone_relationship_types['FULFILLS']
        )
        self.assertEqual(len(content_milestones), 0)

    def test_contentstore_views_entrance_exam_post(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post
        """
        resp = self.client.post(self.exam_url, {}, http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

        # Reload the test course now that the exam module has been added
        self.course = modulestore().get_course(self.course.id)
        metadata = CourseMetadata.fetch_all(self.course)
        self.assertTrue(metadata['entrance_exam_enabled'])
        self.assertIsNotNone(metadata['entrance_exam_minimum_score_pct'])
        self.assertIsNotNone(metadata['entrance_exam_id']['value'])
        self.assertTrue(len(milestones_helpers.get_course_milestones(unicode(self.course.id))))
        content_milestones = milestones_helpers.get_course_content_milestones(
            unicode(self.course.id),
            metadata['entrance_exam_id']['value'],
            self.milestone_relationship_types['FULFILLS']
        )
        self.assertTrue(len(content_milestones))

    def test_contentstore_views_entrance_exam_post_new_sequential_confirm_grader(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post
        """
        resp = self.client.post(self.exam_url, {}, http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

        # Reload the test course now that the exam module has been added
        self.course = modulestore().get_course(self.course.id)

        # Add a new child sequential to the exam module
        # Confirm that the grader type is 'Entrance Exam'
        chapter_locator_string = json.loads(resp.content).get('locator')
        # chapter_locator = UsageKey.from_string(chapter_locator_string)
        seq_data = {
            'category': "sequential",
            'display_name': "Entrance Exam Subsection",
            'parent_locator': chapter_locator_string,
        }
        resp = self.client.ajax_post(reverse_url('xblock_handler'), seq_data)
        seq_locator_string = json.loads(resp.content).get('locator')
        seq_locator = UsageKey.from_string(seq_locator_string)
        section_grader_type = CourseGradingModel.get_section_grader_type(seq_locator)
        self.assertEqual(GRADER_TYPES['ENTRANCE_EXAM'], section_grader_type['graderType'])

    def test_contentstore_views_entrance_exam_get(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get
        """
        resp = self.client.post(
            self.exam_url,
            {'entrance_exam_minimum_score_pct': settings.ENTRANCE_EXAM_MIN_SCORE_PCT},
            http_accept='application/json'
        )
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

    def test_contentstore_views_entrance_exam_delete(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_delete
        """
        resp = self.client.post(self.exam_url, {}, http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)
        resp = self.client.delete(self.exam_url)
        self.assertEqual(resp.status_code, 204)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 404)

        user = User.objects.create(
            username='******',
            email='*****@*****.**',
            is_active=True,
        )
        user.set_password('test')
        user.save()
        milestones = milestones_helpers.get_course_milestones(unicode(self.course_key))
        self.assertEqual(len(milestones), 1)
        milestone_key = '{}.{}'.format(milestones[0]['namespace'], milestones[0]['name'])
        paths = milestones_helpers.get_course_milestones_fulfillment_paths(
            unicode(self.course_key),
            milestones_helpers.serialize_user(user)
        )

        # What we have now is a course milestone requirement and no valid fulfillment
        # paths for the specified user.  The LMS is going to have to ignore this situation,
        # because we can't confidently prevent it from occuring at some point in the future.
        # milestone_key_1 =
        self.assertEqual(len(paths[milestone_key]), 0)

        # Re-adding an entrance exam to the course should fix the missing link
        # It wipes out any old entrance exam artifacts and inserts a new exam course chapter/module
        resp = self.client.post(self.exam_url, {}, http_accept='application/json')
        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)

        # Confirm that we have only one Entrance Exam grader after re-adding the exam (validates SOL-475)
        graders = CourseGradingModel.fetch(self.course_key).graders
        count = 0
        for grader in graders:
            if grader['type'] == GRADER_TYPES['ENTRANCE_EXAM']:
                count += 1
        self.assertEqual(count, 1)

    def test_contentstore_views_entrance_exam_delete_bogus_course(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_delete_bogus_course
        """
        resp = self.client.delete('/course/bad/course/key/entrance_exam')
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_get_bogus_course(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get_bogus_course
        """
        resp = self.client.get('/course/bad/course/key/entrance_exam')
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_get_bogus_exam(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get_bogus_exam
        """
        resp = self.client.post(
            self.exam_url,
            {'entrance_exam_minimum_score_pct': '50'},
            http_accept='application/json'
        )

        self.assertEqual(resp.status_code, 201)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 200)
        self.course = modulestore().get_course(self.course.id)
        # Should raise an ItemNotFoundError and return a 404
        updated_metadata = {'entrance_exam_id': 'i4x://org.4/course_4/chapter/ed7c4c6a4d68409998e2c8554c4629d1'}

        CourseMetadata.update_from_dict(
            updated_metadata,
            self.course,
            self.user,
        )
        self.course = modulestore().get_course(self.course.id)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 404)

        # Should raise an InvalidKeyError and return a 404
        updated_metadata = {'entrance_exam_id': '123afsdfsad90f87'}

        CourseMetadata.update_from_dict(
            updated_metadata,
            self.course,
            self.user,
        )
        self.course = modulestore().get_course(self.course.id)
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 404)

    def test_contentstore_views_entrance_exam_post_bogus_course(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post_bogus_course
        """
        resp = self.client.post(
            '/course/bad/course/key/entrance_exam',
            {},
            http_accept='application/json'
        )
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_post_invalid_http_accept(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_post_invalid_http_accept
        """
        resp = self.client.post(
            '/course/bad/course/key/entrance_exam',
            {},
            http_accept='text/html'
        )
        self.assertEqual(resp.status_code, 400)

    def test_contentstore_views_entrance_exam_get_invalid_user(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_get_invalid_user
        """
        user = User.objects.create(
            username='******',
            email='*****@*****.**',
            is_active=True,
        )
        user.set_password('test')
        user.save()
        self.client = AjaxEnabledTestClient()
        self.client.login(username='******', password='******')
        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 403)

    def test_contentstore_views_entrance_exam_unsupported_method(self):
        """
        Unit Test: test_contentstore_views_entrance_exam_unsupported_method
        """
        resp = self.client.put(self.exam_url)
        self.assertEqual(resp.status_code, 405)

    def test_entrance_exam_view_direct_missing_score_setting(self):
        """
        Unit Test: test_entrance_exam_view_direct_missing_score_setting
        """
        user = UserFactory()
        user.is_staff = True
        request = RequestFactory()
        request.user = user

        resp = create_entrance_exam(request, self.course.id, None)
        self.assertEqual(resp.status_code, 201)

    @patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': False})
    def test_entrance_exam_feature_flag_gating(self):
        user = UserFactory()
        user.is_staff = True
        request = RequestFactory()
        request.user = user

        resp = self.client.get(self.exam_url)
        self.assertEqual(resp.status_code, 400)

        resp = create_entrance_exam(request, self.course.id, None)
        self.assertEqual(resp.status_code, 400)

        resp = delete_entrance_exam(request, self.course.id)
        self.assertEqual(resp.status_code, 400)

        # No return, so we'll just ensure no exception is thrown
        update_entrance_exam(request, self.course.id, {})