Esempio n. 1
0
    def test_delete_submission_scores(self, _mock_signal):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(
            student=user,
            course_id=self.course_key,
            module_state_key=problem_location,
            state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': self.course_key.to_deprecated_string(),
            'item_id': problem_location.to_deprecated_string(),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(
            self.course_key, user, problem_location,
            requesting_user=user,
            delete_module=True,
        )

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Esempio n. 2
0
    def test_reset_team_attempts(self):
        self.setup_team()
        team_ora_location = self.team_enabled_ora.location
        # All teammates should have a student module (except lazy_teammate)
        self.assertIsNotNone(
            self.get_student_module(self.user, team_ora_location))
        self.assertIsNotNone(
            self.get_student_module(self.teammate_a, team_ora_location))
        self.assertIsNotNone(
            self.get_student_module(self.teammate_b, team_ora_location))
        self.assert_no_student_module(self.lazy_teammate, team_ora_location)

        reset_student_attempts(self.course_key,
                               self.user,
                               team_ora_location,
                               requesting_user=self.user)

        # Everyone's state should have had the attempts set to zero but otherwise unchanged
        attempt_reset_team_state_dict = dict(self.team_state_dict)
        attempt_reset_team_state_dict['attempts'] = 0

        def _assert_student_module(user):
            student_module = self.get_student_module(user, team_ora_location)
            self.assertIsNotNone(student_module)
            student_state = json.loads(student_module.state)
            self.assertDictEqual(student_state, attempt_reset_team_state_dict)

        _assert_student_module(self.user)
        _assert_student_module(self.teammate_a)
        _assert_student_module(self.teammate_b)
        # Still should have no state
        self.assert_no_student_module(self.lazy_teammate, team_ora_location)
Esempio n. 3
0
    def test_reset_student_attempts_children(self):
        parent_state = json.loads(self.get_state(self.parent.location))
        self.assertEqual(parent_state['attempts'], 32)
        self.assertEqual(parent_state['otherstuff'], 'alsorobots')

        child_state = json.loads(self.get_state(self.child.location))
        self.assertEqual(child_state['attempts'], 10)
        self.assertEqual(child_state['whatever'], 'things')

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')

        reset_student_attempts(self.course_key, self.user, self.parent.location, requesting_user=self.user)

        parent_state = json.loads(self.get_state(self.parent.location))
        self.assertEqual(json.loads(self.get_state(self.parent.location))['attempts'], 0)
        self.assertEqual(parent_state['otherstuff'], 'alsorobots')

        child_state = json.loads(self.get_state(self.child.location))
        self.assertEqual(child_state['attempts'], 0)
        self.assertEqual(child_state['whatever'], 'things')

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')
Esempio n. 4
0
    def test_reset_student_attempts_children(self):
        parent_state = json.loads(self.get_state(self.parent.location))
        assert parent_state['attempts'] == 32
        assert parent_state['otherstuff'] == 'alsorobots'

        child_state = json.loads(self.get_state(self.child.location))
        assert child_state['attempts'] == 10
        assert child_state['whatever'] == 'things'

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        assert unrelated_state['attempts'] == 12
        assert unrelated_state['brains'] == 'zombie'

        reset_student_attempts(self.course_key,
                               self.user,
                               self.parent.location,
                               requesting_user=self.user)

        parent_state = json.loads(self.get_state(self.parent.location))
        assert json.loads(self.get_state(
            self.parent.location))['attempts'] == 0
        assert parent_state['otherstuff'] == 'alsorobots'

        child_state = json.loads(self.get_state(self.child.location))
        assert child_state['attempts'] == 0
        assert child_state['whatever'] == 'things'

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        assert unrelated_state['attempts'] == 12
        assert unrelated_state['brains'] == 'zombie'
Esempio n. 5
0
    def test_delete_submission_scores_attempts_children(self):
        parent_state = json.loads(self.get_state(self.parent.location))
        self.assertEqual(parent_state['attempts'], 32)
        self.assertEqual(parent_state['otherstuff'], 'alsorobots')

        child_state = json.loads(self.get_state(self.child.location))
        self.assertEqual(child_state['attempts'], 10)
        self.assertEqual(child_state['whatever'], 'things')

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')

        reset_student_attempts(
            self.course_key,
            self.user,
            self.parent.location,
            requesting_user=self.user,
            delete_module=True,
        )

        self.assertRaises(StudentModule.DoesNotExist, self.get_state, self.parent.location)
        self.assertRaises(StudentModule.DoesNotExist, self.get_state, self.child.location)

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')
    def test_delete_submission_scores(self, _mock_signal):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(
            student=user,
            course_id=self.course_key,
            module_state_key=problem_location,
            state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': self.course_key.to_deprecated_string(),
            'item_id': problem_location.to_deprecated_string(),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(
            self.course_key, user, problem_location,
            requesting_user=user,
            delete_module=True,
        )

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Esempio n. 7
0
    def test_reset_student_attempts_children(self):
        parent_state = json.loads(self.get_state(self.parent.location))
        self.assertEqual(parent_state['attempts'], 32)
        self.assertEqual(parent_state['otherstuff'], 'alsorobots')

        child_state = json.loads(self.get_state(self.child.location))
        self.assertEqual(child_state['attempts'], 10)
        self.assertEqual(child_state['whatever'], 'things')

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')

        reset_student_attempts(self.course_key,
                               self.user,
                               self.parent.location,
                               requesting_user=self.user)

        parent_state = json.loads(self.get_state(self.parent.location))
        self.assertEqual(
            json.loads(self.get_state(self.parent.location))['attempts'], 0)
        self.assertEqual(parent_state['otherstuff'], 'alsorobots')

        child_state = json.loads(self.get_state(self.child.location))
        self.assertEqual(child_state['attempts'], 0)
        self.assertEqual(child_state['whatever'], 'things')

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')
Esempio n. 8
0
    def test_delete_team_attempts_no_team_fallthrough(self, _mock_signal):
        self.setup_team()
        team_ora_location = self.team_enabled_ora.location

        # Remove self.user from the team
        CourseTeamMembership.objects.get(user=self.user,
                                         team=self.team).delete()

        # All teammates should have a student module (except lazy_teammate)
        self.assertIsNotNone(
            self.get_student_module(self.user, team_ora_location))
        self.assertIsNotNone(
            self.get_student_module(self.teammate_a, team_ora_location))
        self.assertIsNotNone(
            self.get_student_module(self.teammate_b, team_ora_location))
        self.assert_no_student_module(self.lazy_teammate, team_ora_location)

        reset_student_attempts(self.course_key,
                               self.user,
                               team_ora_location,
                               requesting_user=self.user,
                               delete_module=True)

        # self.user should be deleted, but no other teammates should be affected.
        self.assert_no_student_module(self.user, team_ora_location)
        self.assertIsNotNone(
            self.get_student_module(self.teammate_a, team_ora_location))
        self.assertIsNotNone(
            self.get_student_module(self.teammate_b, team_ora_location))
        self.assert_no_student_module(self.lazy_teammate, team_ora_location)
Esempio n. 9
0
    def test_delete_submission_scores_attempts_children(self):
        parent_state = json.loads(self.get_state(self.parent.location))
        self.assertEqual(parent_state['attempts'], 32)
        self.assertEqual(parent_state['otherstuff'], 'alsorobots')

        child_state = json.loads(self.get_state(self.child.location))
        self.assertEqual(child_state['attempts'], 10)
        self.assertEqual(child_state['whatever'], 'things')

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')

        reset_student_attempts(
            self.course_key,
            self.user,
            self.parent.location,
            requesting_user=self.user,
            delete_module=True,
        )

        self.assertRaises(StudentModule.DoesNotExist, self.get_state,
                          self.parent.location)
        self.assertRaises(StudentModule.DoesNotExist, self.get_state,
                          self.child.location)

        unrelated_state = json.loads(self.get_state(self.unrelated.location))
        self.assertEqual(unrelated_state['attempts'], 12)
        self.assertEqual(unrelated_state['brains'], 'zombie')
    def delete_student_attempt(self, student_identifier, course_id, content_id, requesting_user):
        """
        Deletes student state for a problem. requesting_user may be kept as an audit trail.

        Takes some of the following query parameters
            - student_identifier is an email or username
            - content_id is a url-name of a problem
            - course_id is the id for the course
        """
        course_id = CourseKey.from_string(course_id)

        try:
            student = get_student_from_identifier(student_identifier)
        except ObjectDoesNotExist:
            err_msg = (
                'Error occurred while attempting to reset student attempts for user '
                '{student_identifier} for content_id {content_id}. '
                'User does not exist!'.format(
                    student_identifier=student_identifier,
                    content_id=content_id
                )
            )
            log.error(err_msg)
            return

        try:
            module_state_key = UsageKey.from_string(content_id)
        except InvalidKeyError:
            err_msg = (
                f'Invalid content_id {content_id}!'
            )
            log.error(err_msg)
            return

        if student:
            try:
                enrollment.reset_student_attempts(
                    course_id,
                    student,
                    module_state_key,
                    requesting_user=requesting_user,
                    delete_module=True,
                )
            except (StudentModule.DoesNotExist, enrollment.sub_api.SubmissionError):
                err_msg = (
                    'Error occurred while attempting to reset student attempts for user '
                    '{student_identifier} for content_id {content_id}.'.format(
                        student_identifier=student_identifier,
                        content_id=content_id
                    )
                )
                log.error(err_msg)
Esempio n. 11
0
    def delete_student_attempt(self, student_identifier, course_id, content_id, requesting_user):
        """
        Deletes student state for a problem. requesting_user may be kept as an audit trail.

        Takes some of the following query parameters
            - student_identifier is an email or username
            - content_id is a url-name of a problem
            - course_id is the id for the course
        """
        course_id = CourseKey.from_string(course_id)

        try:
            student = get_student_from_identifier(student_identifier)
        except ObjectDoesNotExist:
            err_msg = (
                'Error occurred while attempting to reset student attempts for user '
                '{student_identifier} for content_id {content_id}. '
                'User does not exist!'.format(
                    student_identifier=student_identifier,
                    content_id=content_id
                )
            )
            log.error(err_msg)
            return

        try:
            module_state_key = UsageKey.from_string(content_id)
        except InvalidKeyError:
            err_msg = (
                'Invalid content_id {content_id}!'.format(content_id=content_id)
            )
            log.error(err_msg)
            return

        if student:
            try:
                enrollment.reset_student_attempts(
                    course_id,
                    student,
                    module_state_key,
                    requesting_user=requesting_user,
                    delete_module=True,
                )
            except (StudentModule.DoesNotExist, enrollment.sub_api.SubmissionError):
                err_msg = (
                    'Error occurred while attempting to reset student attempts for user '
                    '{student_identifier} for content_id {content_id}.'.format(
                        student_identifier=student_identifier,
                        content_id=content_id
                    )
                )
                log.error(err_msg)
Esempio n. 12
0
    def delete_student_attempt(self, student_identifier, course_id, content_id,
                               requesting_user):
        """
        Deletes student state for a problem. requesting_user may be kept as an audit trail.

        Takes some of the following query parameters
            - student_identifier is an email or username
            - content_id is a url-name of a problem
            - course_id is the id for the course
        """
        course_id = CourseKey.from_string(course_id)

        try:
            student = get_user_by_username_or_email(student_identifier)
        except ObjectDoesNotExist:
            err_msg = (
                'Error occurred while attempting to reset student attempts for user '
                f'{student_identifier} for content_id {content_id}. '
                'User does not exist!')
            log.error(err_msg)
            return

        try:
            module_state_key = UsageKey.from_string(content_id)
        except InvalidKeyError:
            err_msg = (f'Invalid content_id {content_id}!')
            log.error(err_msg)
            return

        if student:
            try:
                enrollment.reset_student_attempts(
                    course_id,
                    student,
                    module_state_key,
                    requesting_user=requesting_user,
                    delete_module=True,
                )
            except (StudentModule.DoesNotExist,
                    enrollment.sub_api.SubmissionError):
                err_msg = (
                    'Error occurred while attempting to reset student attempts for user '
                    f'{student_identifier} for content_id {content_id}.')
                log.error(err_msg)

            # In some cases, reset_student_attempts does not clear the entire exam's completion state.
            # One example of this is an exam with multiple units (verticals) within it and the learner
            # never viewing one of the units. All of the content in that unit will still be marked complete,
            # but the reset code is unable to handle clearing the completion in that scenario.
            update_exam_completion_task.apply_async(
                (student_identifier, content_id, 0.0))
Esempio n. 13
0
 def test_reset_student_attempts(self):
     msk = self.course_key.make_usage_key('dummy', 'module')
     original_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'})
     StudentModule.objects.create(
         student=self.user,
         course_id=self.course_key,
         module_state_key=msk,
         state=original_state
     )
     # lambda to reload the module state from the database
     module = lambda: StudentModule.objects.get(student=self.user, course_id=self.course_key, module_state_key=msk)
     self.assertEqual(json.loads(module().state)['attempts'], 32)
     reset_student_attempts(self.course_key, self.user, msk, requesting_user=self.user)
     self.assertEqual(json.loads(module().state)['attempts'], 0)
Esempio n. 14
0
 def test_reset_student_attempts(self):
     msk = self.course_key.make_usage_key('dummy', 'module')
     original_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'})
     StudentModule.objects.create(
         student=self.user,
         course_id=self.course_key,
         module_state_key=msk,
         state=original_state
     )
     # lambda to reload the module state from the database
     module = lambda: StudentModule.objects.get(student=self.user, course_id=self.course_key, module_state_key=msk)
     self.assertEqual(json.loads(module().state)['attempts'], 32)
     reset_student_attempts(self.course_key, self.user, msk, requesting_user=self.user)
     self.assertEqual(json.loads(module().state)['attempts'], 0)
Esempio n. 15
0
    def test_delete_student_state(self):
        self.submit_question_answer('p1', {'2_1': 'choice_choice_2'})

        with patch('lms.djangoapps.instructor.enrollment.tracker') as enrollment_tracker:
            with patch('lms.djangoapps.grades.events.tracker') as events_tracker:
                reset_student_attempts(
                    self.course.id, self.student, self.problem.location, self.instructor, delete_module=True,
                )
        course = self.store.get_course(self.course.id, depth=0)

        event_transaction_id = enrollment_tracker.method_calls[0][1][1]['event_transaction_id']
        enrollment_tracker.emit.assert_called_with(
            events.STATE_DELETED_EVENT_TYPE,
            {
                'user_id': str(self.student.id),
                'course_id': str(self.course.id),
                'problem_id': str(self.problem.location),
                'instructor_id': str(self.instructor.id),
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': events.STATE_DELETED_EVENT_TYPE,
            }
        )
        events_tracker.emit.assert_has_calls(
            [
                mock_call(
                    events.COURSE_GRADE_CALCULATED,
                    {
                        'percent_grade': 0.0,
                        'grading_policy_hash': 'ChVp0lHGQGCevD0t4njna/C44zQ=',
                        'user_id': str(self.student.id),
                        'letter_grade': '',
                        'event_transaction_id': event_transaction_id,
                        'event_transaction_type': events.STATE_DELETED_EVENT_TYPE,
                        'course_id': str(self.course.id),
                        'course_edited_timestamp': str(course.subtree_edited_on),
                        'course_version': str(course.course_version),
                    }
                ),
                mock_call(
                    events.COURSE_GRADE_NOW_FAILED_EVENT_TYPE,
                    {
                        'user_id': str(self.student.id),
                        'event_transaction_id': event_transaction_id,
                        'event_transaction_type': events.STATE_DELETED_EVENT_TYPE,
                        'course_id': str(self.course.id),
                    }
                ),
            ],
            any_order=True,
        )
Esempio n. 16
0
 def test_delete_student_state(self, _crum_mock):
     problem_location = self.problem.location
     self._get_subsection_grade_and_verify(0, 1, 0, 1)
     answer_problem(course=self.course, request=self.request, problem=self.problem, score=1, max_value=1)
     self._get_subsection_grade_and_verify(1, 1, 1, 1)
     # Delete student state using the instructor dash
     reset_student_attempts(
         self.course.id,
         self.user,
         problem_location,
         requesting_user=self.instructor,
         delete_module=True,
     )
     # Verify that the student's grades are reset
     self._get_subsection_grade_and_verify(0, 1, 0, 1)
Esempio n. 17
0
 def test_delete_student_state(self, _crum_mock):
     problem_location = self.problem.location
     self._get_subsection_grade_and_verify(0, 1, 0, 1)
     answer_problem(course=self.course, request=self.request, problem=self.problem, score=1, max_value=1)
     self._get_subsection_grade_and_verify(1, 1, 1, 1)
     # Delete student state using the instructor dash
     reset_student_attempts(
         self.course.id,
         self.user,
         problem_location,
         requesting_user=self.instructor,
         delete_module=True,
     )
     # Verify that the student's grades are reset
     self._get_subsection_grade_and_verify(0, 1, 0, 1)
Esempio n. 18
0
 def test_delete_student_attempts(self, _mock_signal):
     msk = self.course_key.make_usage_key('dummy', 'module')
     original_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'})
     StudentModule.objects.create(
         student=self.user,
         course_id=self.course_key,
         module_state_key=msk,
         state=original_state
     )
     assert StudentModule.objects.filter(
         student=self.user,
         course_id=self.course_key,
         module_state_key=msk).count() == 1
     reset_student_attempts(self.course_key, self.user, msk, requesting_user=self.user, delete_module=True)
     assert StudentModule.objects.filter(
         student=self.user,
         course_id=self.course_key,
         module_state_key=msk).count() == 0
Esempio n. 19
0
    def test_delete_team_attempts(self, _mock_signal):
        self.setup_team()
        team_ora_location = self.team_enabled_ora.location
        # All teammates should have a student module (except lazy_teammate)
        self.assertIsNotNone(self.get_student_module(self.user, team_ora_location))
        self.assertIsNotNone(self.get_student_module(self.teammate_a, team_ora_location))
        self.assertIsNotNone(self.get_student_module(self.teammate_b, team_ora_location))
        self.assert_no_student_module(self.lazy_teammate, team_ora_location)

        reset_student_attempts(
            self.course_key, self.user, team_ora_location, requesting_user=self.user, delete_module=True
        )

        # No one should have a state now
        self.assert_no_student_module(self.user, team_ora_location)
        self.assert_no_student_module(self.teammate_a, team_ora_location)
        self.assert_no_student_module(self.teammate_b, team_ora_location)
        self.assert_no_student_module(self.lazy_teammate, team_ora_location)
Esempio n. 20
0
 def test_delete_student_attempts(self, _mock_signal):
     msk = self.course_key.make_usage_key('dummy', 'module')
     original_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'})
     StudentModule.objects.create(
         student=self.user,
         course_id=self.course_key,
         module_state_key=msk,
         state=original_state
     )
     self.assertEqual(
         StudentModule.objects.filter(
             student=self.user,
             course_id=self.course_key,
             module_state_key=msk
         ).count(), 1)
     reset_student_attempts(self.course_key, self.user, msk, requesting_user=self.user, delete_module=True)
     self.assertEqual(
         StudentModule.objects.filter(
             student=self.user,
             course_id=self.course_key,
             module_state_key=msk
         ).count(), 0)
Esempio n. 21
0
    def test_delete_student_state(self):
        self.submit_question_answer('p1', {'2_1': 'choice_choice_2'})

        with patch('lms.djangoapps.instructor.enrollment.tracker') as enrollment_tracker:
            with patch('lms.djangoapps.grades.events.tracker') as events_tracker:
                reset_student_attempts(
                    self.course.id, self.student, self.problem.location, self.instructor, delete_module=True,
                )
        course = self.store.get_course(self.course.id, depth=0)

        event_transaction_id = enrollment_tracker.method_calls[0][1][1]['event_transaction_id']
        enrollment_tracker.emit.assert_called_with(
            events.STATE_DELETED_EVENT_TYPE,
            {
                'user_id': unicode(self.student.id),
                'course_id': unicode(self.course.id),
                'problem_id': unicode(self.problem.location),
                'instructor_id': unicode(self.instructor.id),
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': events.STATE_DELETED_EVENT_TYPE,
            }
        )

        events_tracker.emit.assert_called_with(
            events.COURSE_GRADE_CALCULATED,
            {
                'percent_grade': 0.0,
                'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=',
                'user_id': unicode(self.student.id),
                'letter_grade': u'',
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': events.STATE_DELETED_EVENT_TYPE,
                'course_id': unicode(self.course.id),
                'course_edited_timestamp': unicode(course.subtree_edited_on),
                'course_version': unicode(course.course_version),
            }
        )
Esempio n. 22
0
    def test_delete_submission_scores(self, mock_send_signal):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(student=user,
                                     course_id=self.course_key,
                                     module_state_key=problem_location,
                                     state=json.dumps({}))

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': text_type(self.course_key),
            'item_id': text_type(problem_location),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        mock_send_signal.reset_mock()
        reset_student_attempts(
            self.course_key,
            user,
            problem_location,
            requesting_user=user,
            delete_module=True,
        )

        # Make sure our grades signal receivers handled the reset properly
        mock_send_signal.assert_called_once()
        assert mock_send_signal.call_args[1]['weighted_earned'] == 0

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Esempio n. 23
0
    def post(self, request):
        serializer = BulkResetStudentAttemptsSerializer(data=request.data)
        results = {"course": "", "errors": {}, "problems": {}}
        if serializer.is_valid():
            course_id = serializer.data.get('course_id')
            results["course"] = course_id
            try:
                course_key = CourseKey.from_string(course_id)
                email_extension = serializer.data.get('email_extension')
                identifiers = serializer.data.get('identifiers')
                problems = serializer.data.get('problems')
                reset_state = serializer.data.get('reset_state')

                all_students, list_of_identifiers =\
                    get_identifiers(identifiers, email_extension)

                list_of_students = []
                if not all_students:
                    list_of_students, has_errors, get_students_errors =\
                        get_students(list_of_identifiers)

                    if has_errors:
                        results["errors"].update(get_students_errors)

                for problem in problems:
                    problem = problem.replace(" ", "")
                    try:
                        module_state_key =\
                            UsageKey.from_string(
                                problem
                            ).map_into_course(
                                course_key
                            )

                        results["problems"].update({problem: {}})
                        if all_students:
                            message = "Reset attempts for 'all' students is "
                            "in development. Nothing has been resetted."

                            results['problems'].update(
                                {problem: {
                                    "message": message
                                }})
                            # submit_reset_problem_attempts_for_all_students(
                            #     request, module_state_key
                            # )

                            # results['problems'].update(
                            #     {
                            #         problem: {
                            #             "students": "all",
                            #             "task": "created"
                            #         }
                            #     }
                            # )
                        else:
                            for student in list_of_students:
                                try:
                                    enrollment.reset_student_attempts(
                                        course_key,
                                        student,
                                        module_state_key,
                                        requesting_user=request.user,
                                        delete_module=reset_state)

                                    message = "Problem resetted"
                                    results["problems"][problem].update(
                                        {student.username: message})
                                except StudentModule.DoesNotExist:
                                    error_message =\
                                        _("Module does not exist.")

                                    results["problems"][problem].update(
                                        {student.username: error_message})
                                except sub_api.SubmissionError:
                                    error_message =\
                                        _("An error occurred while "
                                        "deleting the score.")

                                    results["problems"][problem].update(
                                        {student.username: error_message})

                    except InvalidKeyError:
                        error_message = _("The problem does not exist")
                        results["errors"].update({problem: error_message})

                return Response(results, status=status.HTTP_200_OK)

            except InvalidKeyError:
                error_message = _("Invalid course id: '{}'".format(course_id))
                return\
                    Response(
                        {"error": error_message},
                        status=status.HTTP_400_BAD_REQUEST
                    )
        else:
            return\
                Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Esempio n. 24
0
    def test_delete_student_state_events(self, models_tracker, handlers_tracker, enrollment_tracker):
        # submit answer
        self.submit_question_answer('p1', {'2_1': 'choice_choice_2'})

        # check logging to make sure id's are tracked correctly across events
        event_transaction_id = handlers_tracker.emit.mock_calls[0][1][1]['event_transaction_id']
        for call in models_tracker.emit.mock_calls:
            self.assertEqual(event_transaction_id, call[1][1]['event_transaction_id'])
            self.assertEqual(unicode(SUBMITTED_TYPE), call[1][1]['event_transaction_type'])

        handlers_tracker.emit.assert_called_with(
            unicode(SUBMITTED_TYPE),
            {
                'user_id': unicode(self.student.id),
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(SUBMITTED_TYPE),
                'course_id': unicode(self.course.id),
                'problem_id': unicode(self.problem.location),
                'weighted_earned': 2.0,
                'weighted_possible': 2.0,
            }
        )

        course = self.store.get_course(self.course.id, depth=0)
        models_tracker.emit.assert_called_with(
            u'edx.grades.course.grade_calculated',
            {
                'course_version': unicode(course.course_version),
                'percent_grade': 0.02,
                'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=',
                'user_id': unicode(self.student.id),
                'letter_grade': u'',
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(SUBMITTED_TYPE),
                'course_id': unicode(self.course.id),
                'course_edited_timestamp': unicode(course.subtree_edited_on),
            }
        )
        models_tracker.reset_mock()
        handlers_tracker.reset_mock()

        # delete state
        reset_student_attempts(self.course.id, self.student, self.problem.location, self.instructor, delete_module=True)

        # check logging to make sure id's are tracked correctly across events
        event_transaction_id = enrollment_tracker.method_calls[0][1][1]['event_transaction_id']

        # make sure the id is propagated throughout the event flow
        for call in models_tracker.emit.mock_calls:
            self.assertEqual(event_transaction_id, call[1][1]['event_transaction_id'])
            self.assertEqual(unicode(STATE_DELETED_TYPE), call[1][1]['event_transaction_type'])

        # ensure we do not log a problem submitted event when state is deleted
        handlers_tracker.assert_not_called()
        enrollment_tracker.emit.assert_called_with(
            unicode(STATE_DELETED_TYPE),
            {
                'user_id': unicode(self.student.id),
                'course_id': unicode(self.course.id),
                'problem_id': unicode(self.problem.location),
                'instructor_id': unicode(self.instructor.id),
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(STATE_DELETED_TYPE),
            }
        )

        course = modulestore().get_course(self.course.id, depth=0)
        models_tracker.emit.assert_called_with(
            u'edx.grades.course.grade_calculated',
            {
                'percent_grade': 0.0,
                'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=',
                'user_id': unicode(self.student.id),
                'letter_grade': u'',
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(STATE_DELETED_TYPE),
                'course_id': unicode(self.course.id),
                'course_edited_timestamp': unicode(course.subtree_edited_on),
                'course_version': unicode(course.course_version),
            }
        )
        enrollment_tracker.reset_mock()
        models_tracker.reset_mock()
        handlers_tracker.reset_mock()
Esempio n. 25
0
    def test_delete_student_state_events(self, models_tracker,
                                         handlers_tracker, enrollment_tracker):
        # submit answer
        self.submit_question_answer('p1', {'2_1': 'choice_choice_2'})

        # check logging to make sure id's are tracked correctly across events
        event_transaction_id = handlers_tracker.emit.mock_calls[0][1][1][
            'event_transaction_id']
        for call in models_tracker.emit.mock_calls:
            self.assertEqual(event_transaction_id,
                             call[1][1]['event_transaction_id'])
            self.assertEqual(unicode(SUBMITTED_TYPE),
                             call[1][1]['event_transaction_type'])

        handlers_tracker.emit.assert_called_with(
            unicode(SUBMITTED_TYPE), {
                'user_id': unicode(self.student.id),
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(SUBMITTED_TYPE),
                'course_id': unicode(self.course.id),
                'problem_id': unicode(self.problem.location),
                'weighted_earned': 2.0,
                'weighted_possible': 2.0,
            })

        course = self.store.get_course(self.course.id, depth=0)
        models_tracker.emit.assert_called_with(
            u'edx.grades.course.grade_calculated', {
                'course_version': unicode(course.course_version),
                'percent_grade': 0.02,
                'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=',
                'user_id': unicode(self.student.id),
                'letter_grade': u'',
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(SUBMITTED_TYPE),
                'course_id': unicode(self.course.id),
                'course_edited_timestamp': unicode(course.subtree_edited_on),
            })
        models_tracker.reset_mock()
        handlers_tracker.reset_mock()

        # delete state
        reset_student_attempts(self.course.id,
                               self.student,
                               self.problem.location,
                               self.instructor,
                               delete_module=True)

        # check logging to make sure id's are tracked correctly across events
        event_transaction_id = enrollment_tracker.method_calls[0][1][1][
            'event_transaction_id']

        # make sure the id is propagated throughout the event flow
        for call in models_tracker.emit.mock_calls:
            self.assertEqual(event_transaction_id,
                             call[1][1]['event_transaction_id'])
            self.assertEqual(unicode(STATE_DELETED_TYPE),
                             call[1][1]['event_transaction_type'])

        # ensure we do not log a problem submitted event when state is deleted
        handlers_tracker.assert_not_called()
        enrollment_tracker.emit.assert_called_with(
            unicode(STATE_DELETED_TYPE), {
                'user_id': unicode(self.student.id),
                'course_id': unicode(self.course.id),
                'problem_id': unicode(self.problem.location),
                'instructor_id': unicode(self.instructor.id),
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(STATE_DELETED_TYPE),
            })

        course = modulestore().get_course(self.course.id, depth=0)
        models_tracker.emit.assert_called_with(
            u'edx.grades.course.grade_calculated', {
                'percent_grade': 0.0,
                'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=',
                'user_id': unicode(self.student.id),
                'letter_grade': u'',
                'event_transaction_id': event_transaction_id,
                'event_transaction_type': unicode(STATE_DELETED_TYPE),
                'course_id': unicode(self.course.id),
                'course_edited_timestamp': unicode(course.subtree_edited_on),
                'course_version': unicode(course.course_version),
            })
        enrollment_tracker.reset_mock()
        models_tracker.reset_mock()
        handlers_tracker.reset_mock()