""" Tests calling the grades api directly """ import ddt from mock import patch from lms.djangoapps.grades import api from lms.djangoapps.grades.models import ( PersistentSubsectionGrade, PersistentSubsectionGradeOverride, ) from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory @ddt.ddt class OverrideSubsectionGradeTests(ModuleStoreTestCase): """ Tests for the override subsection grades api call """ @classmethod def setUpTestData(cls): super(OverrideSubsectionGradeTests, cls).setUpTestData() cls.user = UserFactory() cls.overriding_user = UserFactory() cls.signal_patcher = patch('lms.djangoapps.grades.signals.signals.SUBSECTION_OVERRIDE_CHANGED.send') cls.signal_patcher.start() cls.id_patcher = patch('lms.djangoapps.grades.api.create_new_event_transaction_id') cls.mock_create_id = cls.id_patcher.start() cls.mock_create_id.return_value = 1 cls.type_patcher = patch('lms.djangoapps.grades.api.set_event_transaction_type') cls.type_patcher.start() @classmethod def tearDownClass(cls): super(OverrideSubsectionGradeTests, cls).tearDownClass() cls.signal_patcher.stop() cls.id_patcher.stop() cls.type_patcher.stop() def setUp(self): super(OverrideSubsectionGradeTests, self).setUp() self.course = CourseFactory.create(org='edX', number='DemoX', display_name='Demo_Course', run='Spring2019') self.subsection = ItemFactory.create(parent=self.course, category="subsection", display_name="Subsection") self.grade = PersistentSubsectionGrade.update_or_create_grade( user_id=self.user.id, course_id=self.course.id, usage_key=self.subsection.location, first_attempted=None, visible_blocks=[], earned_all=6.0, possible_all=6.0, earned_graded=5.0, possible_graded=5.0 ) def tearDown(self): super(OverrideSubsectionGradeTests, self).tearDown() PersistentSubsectionGradeOverride.objects.all().delete() # clear out all previous overrides @ddt.data(0.0, None, 3.0) def test_override_subsection_grade(self, earned_graded): api.override_subsection_grade( self.user.id, self.course.id, self.subsection.location, overrider=self.overriding_user, earned_graded=earned_graded, comment='Test Override Comment', ) override_obj = api.get_subsection_grade_override( self.user.id, self.course.id, self.subsection.location ) self.assertIsNotNone(override_obj) self.assertEqual(override_obj.earned_graded_override, earned_graded) self.assertEqual(override_obj.override_reason, 'Test Override Comment') for i in range(3): override_obj.override_reason = 'this field purposefully left blank' override_obj.earned_graded_override = i override_obj.save() api.override_subsection_grade( self.user.id, self.course.id, self.subsection.location, overrider=self.overriding_user, earned_graded=earned_graded, comment='Test Override Comment 2', ) override_obj = api.get_subsection_grade_override( self.user.id, self.course.id, self.subsection.location ) self.assertIsNotNone(override_obj) self.assertEqual(override_obj.earned_graded_override, earned_graded) self.assertEqual(override_obj.override_reason, 'Test Override Comment 2') self.assertEqual(5, len(override_obj.history.all())) for history_entry in override_obj.history.all(): if history_entry.override_reason.startswith('Test Override Comment'): self.assertEqual(self.overriding_user, history_entry.history_user) self.assertEqual(self.overriding_user.id, history_entry.history_user_id) else: self.assertIsNone(history_entry.history_user) self.assertIsNone(history_entry.history_user_id)