Skip to content

Commit

Permalink
Expand on error descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
bjester committed Apr 8, 2022
1 parent b548ca7 commit 6952d7f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 10 deletions.
22 changes: 18 additions & 4 deletions contentcuration/contentcuration/constants/completion_criteria.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from django.core.exceptions import ValidationError
from jsonschema import RefResolver
from jsonschema.exceptions import best_match
from jsonschema.validators import validator_for
from le_utils.constants import completion_criteria
from le_utils.constants import content_kinds
Expand Down Expand Up @@ -31,9 +30,24 @@ def validate(data, kind=None):
if isinstance(data, (dict,)) and not data:
return

error = best_match(validator.iter_errors(data))
if error is not None:
raise ValidationError("Completion criteria does not conform to schema") from error
error_descriptions = []
# @see https://python-jsonschema.readthedocs.io/en/latest/errors/
for error in validator.iter_errors(data):
if error.cause:
# documentation says this will only be set on FormatChecker errors
error_descriptions.append(error.cause)
elif error.absolute_path:
# if there's a path to a field, we can give a specific error
json_path = ".".join(error.absolute_path)
error_descriptions.append(ValidationError("{} {}".format(json_path, error.message)))
else:
# without a path, likely top-level validation error, e.g. `anyOf` conditions
error_descriptions.append(ValidationError("object doesn't satisfy '{}' conditions".format(error.validator)))

if error_descriptions:
e = ValidationError("Completion criteria doesn't conform to schema")
e.error_list.extend(error_descriptions)
raise e

model = data.get("model")
if kind is None or model is None:
Expand Down
17 changes: 11 additions & 6 deletions contentcuration/contentcuration/tests/test_completion_criteria.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.test import SimpleTestCase
from le_utils.constants import completion_criteria
from le_utils.constants import content_kinds
from le_utils.constants import mastery_criteria

from contentcuration.constants.completion_criteria import validate

Expand All @@ -13,12 +14,16 @@ def test_validate__success(self):
def test_validate__success__empty(self):
validate({})

def test_validate__fail(self):
with self.assertRaises(ValidationError):
def test_validate__fail__model(self):
with self.assertRaisesRegex(ValidationError, "model 'does not exist' is not one of"):
validate({"model": "does not exist"})

def test_validate__fail__threshold(self):
with self.assertRaisesRegex(ValidationError, "object doesn't satisfy 'anyOf' conditions"):
validate({"model": completion_criteria.PAGES, "threshold": "not a number"})

def test_validate__content_kind(self):
with self.assertRaises(ValidationError):
validate({"model": completion_criteria.PAGES}, kind=content_kinds.EXERCISE)
with self.assertRaises(ValidationError):
validate({"model": completion_criteria.MASTERY}, kind=content_kinds.DOCUMENT)
with self.assertRaisesRegex(ValidationError, "is invalid for content kind"):
validate({"model": completion_criteria.PAGES, "threshold": 1}, kind=content_kinds.EXERCISE)
with self.assertRaisesRegex(ValidationError, "is invalid for content kind"):
validate({"model": completion_criteria.MASTERY, "threshold": {"mastery_model": mastery_criteria.DO_ALL}}, kind=content_kinds.DOCUMENT)

0 comments on commit 6952d7f

Please sign in to comment.