Commit 30fc3a55 by Alex Dusenbery Committed by Alex Dusenbery

EDUCATOR-390 and EDUCATOR-391 | Send GRADING_POLICY_CHANGED signal when…

EDUCATOR-390 and EDUCATOR-391 | Send GRADING_POLICY_CHANGED signal when something changes the grading policy.
parent 2955a6e6
......@@ -418,8 +418,9 @@ class CourseGradingTest(CourseTestCase):
subgrader = CourseGradingModel.fetch_grader(self.course.id, i)
self.assertDictEqual(grader, subgrader, str(i) + "th graders not equal")
@mock.patch('contentstore.signals.signals.GRADING_POLICY_CHANGED.send')
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
def test_update_from_json(self, store):
def test_update_from_json(self, store, send_signal):
self.course = CourseFactory.create(default_store=store)
test_grader = CourseGradingModel.fetch(self.course.id)
......@@ -450,7 +451,17 @@ class CourseGradingTest(CourseTestCase):
altered_grader = CourseGradingModel.update_from_json(self.course.id, test_grader.__dict__, self.user)
self.assertDictEqual(test_grader.__dict__, altered_grader.__dict__, "4 hour grace period")
def test_update_grader_from_json(self):
# one for each of the calls to update_from_json()
send_signal.assert_has_calls([
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
])
@mock.patch('contentstore.signals.signals.GRADING_POLICY_CHANGED.send')
def test_update_grader_from_json(self, send_signal):
test_grader = CourseGradingModel.fetch(self.course.id)
altered_grader = CourseGradingModel.update_grader_from_json(
self.course.id, test_grader.graders[1], self.user
......@@ -467,6 +478,13 @@ class CourseGradingTest(CourseTestCase):
self.course.id, test_grader.graders[1], self.user)
self.assertDictEqual(test_grader.graders[1], altered_grader, "drop_count[1] + 2")
# one for each of the calls to update_grader_from_json()
send_signal.assert_has_calls([
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
])
def test_update_cutoffs_from_json(self):
test_grader = CourseGradingModel.fetch(self.course.id)
CourseGradingModel.update_cutoffs_from_json(self.course.id, test_grader.grade_cutoffs, self.user)
......@@ -508,7 +526,8 @@ class CourseGradingTest(CourseTestCase):
# Once deleted, the grace period should simply be None
self.assertEqual(None, altered_grader.grace_period, "Delete grace period")
def test_update_section_grader_type(self):
@mock.patch('contentstore.signals.signals.GRADING_POLICY_CHANGED.send')
def test_update_section_grader_type(self, send_signal):
# Get the descriptor and the section_grader_type and assert they are the default values
descriptor = modulestore().get_item(self.course.location)
section_grader_type = CourseGradingModel.get_section_grader_type(self.course.location)
......@@ -535,29 +554,44 @@ class CourseGradingTest(CourseTestCase):
self.assertEqual(None, descriptor.format)
self.assertEqual(False, descriptor.graded)
# one for each call to update_section_grader_type()
send_signal.assert_has_calls([
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
])
def _model_from_url(self, url_base):
response = self.client.get_json(url_base)
return json.loads(response.content)
def test_get_set_grader_types_ajax(self):
"""
Test configuring the graders via ajax calls
Test creating and fetching the graders via ajax calls.
"""
grader_type_url_base = get_url(self.course.id, 'grading_handler')
# test get whole
response = self.client.get_json(grader_type_url_base)
whole_model = json.loads(response.content)
whole_model = self._model_from_url(grader_type_url_base)
self.assertIn('graders', whole_model)
self.assertIn('grade_cutoffs', whole_model)
self.assertIn('grace_period', whole_model)
# test post/update whole
whole_model['grace_period'] = {'hours': 1, 'minutes': 30, 'seconds': 0}
response = self.client.ajax_post(grader_type_url_base, whole_model)
self.assertEqual(200, response.status_code)
response = self.client.get_json(grader_type_url_base)
whole_model = json.loads(response.content)
whole_model = self._model_from_url(grader_type_url_base)
self.assertEqual(whole_model['grace_period'], {'hours': 1, 'minutes': 30, 'seconds': 0})
# test get one grader
self.assertGreater(len(whole_model['graders']), 1) # ensure test will make sense
response = self.client.get_json(grader_type_url_base + '/1')
grader_sample = json.loads(response.content)
grader_sample = self._model_from_url(grader_type_url_base + '/1')
self.assertEqual(grader_sample, whole_model['graders'][1])
@mock.patch('contentstore.signals.signals.GRADING_POLICY_CHANGED.send')
def test_add_delete_grader(self, send_signal):
grader_type_url_base = get_url(self.course.id, 'grading_handler')
original_model = self._model_from_url(grader_type_url_base)
# test add grader
new_grader = {
"type": "Extra Credit",
......@@ -566,22 +600,31 @@ class CourseGradingTest(CourseTestCase):
"short_label": None,
"weight": 15,
}
response = self.client.ajax_post(
'{}/{}'.format(grader_type_url_base, len(whole_model['graders'])),
'{}/{}'.format(grader_type_url_base, len(original_model['graders'])),
new_grader
)
self.assertEqual(200, response.status_code)
grader_sample = json.loads(response.content)
new_grader['id'] = len(whole_model['graders'])
new_grader['id'] = len(original_model['graders'])
self.assertEqual(new_grader, grader_sample)
# test delete grader
# test deleting the original grader
response = self.client.delete(grader_type_url_base + '/1', HTTP_ACCEPT="application/json")
self.assertEqual(204, response.status_code)
response = self.client.get_json(grader_type_url_base)
updated_model = json.loads(response.content)
updated_model = self._model_from_url(grader_type_url_base)
new_grader['id'] -= 1 # one fewer and the id mutates
self.assertIn(new_grader, updated_model['graders'])
self.assertNotIn(whole_model['graders'][1], updated_model['graders'])
self.assertNotIn(original_model['graders'][1], updated_model['graders'])
send_signal.assert_has_calls([
# once for the POST
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
# once for the DELETE
mock.call(sender=CourseGradingModel, user_id=self.user.id, course_id=self.course.id),
])
def setup_test_set_get_section_grader_ajax(self):
"""
......
from datetime import timedelta
from contentstore.signals.signals import GRADING_POLICY_CHANGED
from xmodule.modulestore.django import modulestore
......@@ -65,6 +67,8 @@ class CourseGradingModel(object):
CourseGradingModel.update_minimum_grade_credit_from_json(course_key, jsondict['minimum_grade_credit'], user)
GRADING_POLICY_CHANGED.send(sender=CourseGradingModel, user_id=user.id, course_id=course_key)
return CourseGradingModel.fetch(course_key)
@staticmethod
......@@ -86,6 +90,8 @@ class CourseGradingModel(object):
modulestore().update_item(descriptor, user.id)
GRADING_POLICY_CHANGED.send(sender=CourseGradingModel, user_id=user.id, course_id=course_key)
return CourseGradingModel.jsonize_grader(index, descriptor.raw_grader[index])
@staticmethod
......@@ -155,6 +161,8 @@ class CourseGradingModel(object):
modulestore().update_item(descriptor, user.id)
GRADING_POLICY_CHANGED.send(sender=CourseGradingModel, user_id=user.id, course_id=course_key)
@staticmethod
def delete_grace_period(course_key, user):
"""
......@@ -184,6 +192,13 @@ class CourseGradingModel(object):
del descriptor.graded
modulestore().update_item(descriptor, user.id)
GRADING_POLICY_CHANGED.send(
sender=CourseGradingModel,
user_id=user.id,
course_id=descriptor.location.course_key
)
return {'graderType': grader_type}
@staticmethod
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment