def submit_studio_edits(self, data, suffix=''): """ AJAX handler for studio_view() Save button """ values = {} # dict of new field values we are updating to_reset = [] # list of field names to delete from this XBlock for field_name in self.editable_fields: field = self.fields[field_name] if field_name in data['values']: if isinstance(field, JSONField): values[field_name] = field.from_json(data['values'][field_name]) else: raise JsonHandlerError(400, "Unsupported field type: {}".format(field_name)) elif field_name in data['defaults'] and field.is_set_on(self): to_reset.append(field_name) self.clean_studio_edits(values) validation = Validation(self.scope_ids.usage_id) # We cannot set the fields on self yet, because even if validation fails, studio is going to save any changes we # make. So we create a "fake" object that has all the field values we are about to set. preview_data = FutureFields( new_fields_dict=values, newly_removed_fields=to_reset, fallback_obj=self ) self.validate_field_data(validation, preview_data) if validation: for field_name, value in values.iteritems(): setattr(self, field_name, value) for field_name in to_reset: self.fields[field_name].delete_from(self) return {'result': 'success'} else: raise JsonHandlerError(400, validation.to_json())
def submit_studio_edits(self, data, suffix=''): """ AJAX handler for studio_view() Save button """ values = {} # dict of new field values we are updating to_reset = [] # list of field names to delete from this XBlock for field_name in self.editable_fields: field = self.fields[field_name] if field_name in data['values']: if isinstance(field, JSONField): values[field_name] = field.from_json( data['values'][field_name]) else: raise JsonHandlerError( 400, "Unsupported field type: {}".format(field_name)) elif field_name in data['defaults'] and field.is_set_on(self): to_reset.append(field_name) self.clean_studio_edits(values) validation = Validation(self.scope_ids.usage_id) # We cannot set the fields on self yet, because even if validation fails, studio is going to save any changes we # make. So we create a "fake" object that has all the field values we are about to set. preview_data = FutureFields(new_fields_dict=values, newly_removed_fields=to_reset, fallback_obj=self) self.validate_field_data(validation, preview_data) if validation: for field_name, value in six.iteritems(values): setattr(self, field_name, value) for field_name in to_reset: self.fields[field_name].delete_from(self) return {'result': 'success'} else: raise JsonHandlerError(400, validation.to_json())
def test_add_messages_error(self): """ Test that calling `add_messages` with something that is not a `Validation` instances throw an error. """ validation = Validation("id") with assert_raises(TypeError): validation.add_messages("foo")
def fe_submit_studio_edits(self, data, suffix=''): """ AJAX handler for studio edit submission """ if self.xblock_id is None: self.xblock_id = unicode( self.location.replace(branch=None, version=None)) updated_question_template = data['question_template'] updated_variables = data['variables'] updated_answer_template = data['answer_template'] qgb_db_service.update_question_template(self.xblock_id, updated_question_template, updated_variables, updated_answer_template) # "refresh" XBlock's values self.question_template = updated_question_template self.variables = updated_variables self.answer_template = updated_answer_template # call parent method # StudioEditableXBlockMixin.submit_studio_edits(self, data, suffix) # self.submit_studio_edits(data, suffix) # super(FormulaExerciseXBlock, self).submit_studio_edits(data, suffix) # copy from StudioEditableXBlockMixin (can not call parent method) values = {} # dict of new field values we are updating to_reset = [] # list of field names to delete from this XBlock for field_name in self.editable_fields: field = self.fields[field_name] if field_name in data['values']: if isinstance(field, JSONField): values[field_name] = field.from_json( data['values'][field_name]) else: raise JsonHandlerError( 400, "Unsupported field type: {}".format(field_name)) elif field_name in data['defaults'] and field.is_set_on(self): to_reset.append(field_name) self.clean_studio_edits(values) validation = Validation(self.scope_ids.usage_id) # We cannot set the fields on self yet, because even if validation fails, studio is going to save any changes we # make. So we create a "fake" object that has all the field values we are about to set. preview_data = FutureFields(new_fields_dict=values, newly_removed_fields=to_reset, fallback_obj=self) self.validate_field_data(validation, preview_data) if validation: for field_name, value in values.iteritems(): setattr(self, field_name, value) for field_name in to_reset: self.fields[field_name].delete_from(self) return {'result': 'success'} else: raise JsonHandlerError(400, validation.to_json())
def test_empty(self): """ Test that `empty` return True iff there are no messages. Also test the "bool" property of `Validation`. """ validation = Validation("id") self.assertTrue(validation.empty) self.assertTrue(validation) validation.add(ValidationMessage(ValidationMessage.ERROR, "Error message")) self.assertFalse(validation.empty) self.assertFalse(validation)
def test_to_json(self): """ Test the ability to serialize a `Validation` instance. """ validation = Validation("id") expected = {"xblock_id": "id", "messages": [], "empty": True} self.assertEqual(expected, validation.to_json()) validation.add( ValidationMessage(ValidationMessage.ERROR, "Error message")) validation.add( ValidationMessage(ValidationMessage.WARNING, "Warning message")) expected = { "xblock_id": "id", "messages": [{ "type": ValidationMessage.ERROR, "text": "Error message" }, { "type": ValidationMessage.WARNING, "text": "Warning message" }], "empty": False } self.assertEqual(expected, validation.to_json())
def test_copy(self): validation = Validation("id") validation.add(ValidationMessage(ValidationMessage.ERROR, u"Error message")) studio_validation = StudioValidation.copy(validation) self.assertIsInstance(studio_validation, StudioValidation) self.assertFalse(studio_validation) self.assertEqual(1, len(studio_validation.messages)) expected = { "type": StudioValidationMessage.ERROR, "text": u"Error message" } self.assertEqual(expected, studio_validation.messages[0].to_json()) self.assertIsNone(studio_validation.summary)
def test_copy(self): validation = Validation("id") validation.add( ValidationMessage(ValidationMessage.ERROR, "Error message")) studio_validation = StudioValidation.copy(validation) assert isinstance(studio_validation, StudioValidation) assert not studio_validation assert 1 == len(studio_validation.messages) expected = { "type": StudioValidationMessage.ERROR, "text": "Error message" } assert expected == studio_validation.messages[0].to_json() assert studio_validation.summary is None
def validate(self): """ Ask this xblock to validate itself. Subclasses are expected to override this method, as there is currently only a no-op implementation. Any overriding method should call super to collect validation results from its superclasses, and then add any additional results as necessary. """ return Validation(self.scope_ids.usage_id)
def test_add_messages(self): """ Test the behavior of adding the messages from another `Validation` object to this instance. """ validation_1 = Validation("id") validation_1.add(ValidationMessage(ValidationMessage.ERROR, "Error message")) validation_2 = Validation("id") validation_2.add(ValidationMessage(ValidationMessage.WARNING, "Warning message")) validation_1.add_messages(validation_2) self.assertEqual(2, len(validation_1.messages)) self.assertEqual(ValidationMessage.ERROR, validation_1.messages[0].type) self.assertEqual("Error message", validation_1.messages[0].text) self.assertEqual(ValidationMessage.WARNING, validation_1.messages[1].type) self.assertEqual("Warning message", validation_1.messages[1].text)
def test_to_json(self): """ Test the ability to serialize a `Validation` instance. """ validation = Validation("id") expected = { "xblock_id": "id", "messages": [], "empty": True } self.assertEqual(expected, validation.to_json()) validation.add(ValidationMessage(ValidationMessage.ERROR, "Error message")) validation.add(ValidationMessage(ValidationMessage.WARNING, "Warning message")) expected = { "xblock_id": "id", "messages": [ {"type": ValidationMessage.ERROR, "text": "Error message"}, {"type": ValidationMessage.WARNING, "text": "Warning message"} ], "empty": False } self.assertEqual(expected, validation.to_json())
def verify_validation(self, data, expect_success): validation = Validation('xblock_id') self.block.validate_field_data(validation, data) self.assertEqual(bool(validation), expect_success)