def test_allof_complex(): schema_without_allof = { 'type': 'object', 'properties': { 'name': { 'type': STRING, }, 'age': { 'type': INTEGER, } } } schema_with_allof = { 'type': 'object', 'allOf': [ { 'properties': { 'name': { 'type': STRING, } } }, { 'properties': { 'age': { 'type': INTEGER, } } }, ] } good_data = dict(name="foo", age=42) bad_data = dict(name="foo", age="bar") validator_without_allof = generate_validator_from_schema( schema_without_allof) validator_with_allof = generate_validator_from_schema(schema_with_allof) validator_without_allof(good_data) validator_with_allof(good_data) with pytest.raises(ValidationError): validator_without_allof(bad_data) with pytest.raises(ValidationError): validator_with_allof(bad_data)
def test_enum_noop_when_not_required_and_field_not_present(): schema = { 'enum': [True, False, 1.0, 2.0, 'A'], } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_enum_with_valid_array(letters): schema = { 'enum': [2, 1, 'a', 'b', 'c', True, False], } validator = generate_validator_from_schema(schema) validator(letters)
def test_field_declared_as_required_with_field_present_is_valid(): schema = { 'required': True, } validator = generate_validator_from_schema(schema) validator('John Smith')
def test_enum_disperate_text_types(enum_value, value): schema = { 'enum': [enum_value], } validator = generate_validator_from_schema(schema) validator(value)
def test_date_time_is_noop_when_not_present_or_required(): schema = { 'format': 'date-time', } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_integer_type_valid(): schema = { 'type': INTEGER, } validator = generate_validator_from_schema(schema) validator(1)
def test_items_past_the_number_of_schemas_provided_are_skipped(): schema = { 'type': ARRAY, 'items': [ { 'type': INTEGER, 'minimum': 0, 'maximum': 10 }, { 'type': INTEGER, 'minimum': 0, 'maximum': 10 }, { 'type': INTEGER, 'minimum': 0, 'maximum': 10 }, ], } validator = generate_validator_from_schema(schema) validator( [0, 5, 10, 20, 30, 40], # 20, 30, and 40 don't conform, but are beyond the declared number of schemas. )
def test_invalid_values_against_list_of_schemas(): from django.core.exceptions import ValidationError schema = { 'type': ARRAY, 'items': [ {'type': INTEGER, 'minimum': 0, 'maximum': 10}, {'type': STRING, 'minLength': 3, 'maxLength': 5}, {'type': INTEGER, 'minimum': 0, 'maximum': 10}, {'type': STRING, 'minLength': 3, 'maxLength': 5}, {'type': INTEGER, 'minimum': 0, 'maximum': 10}, ], } validator = generate_validator_from_schema(schema) with pytest.raises(ValidationError) as err: validator( [11, 'abc-abc', -5, 'ab', 'wrong-type'], inner=True, ) assert 'items' in err.value.messages[0] assert len(err.value.messages[0]['items']) == 5 _1, _2, _3, _4, _5 = err.value.messages[0]['items'] assert 'maximum' in _1 assert 'maxLength' in _2 assert 'minimum' in _3 assert 'minLength' in _4 assert 'type' in _5
def test_field_declared_as_required_with_field_present_is_valid(): schema = { 'type': OBJECT, 'required': [ 'field-A', # 'field-B', ], } validator = generate_validator_from_schema(schema) try: validator({'field-A': 'present'}) except ValidationError as err: errors = err.detail else: errors = {} assert_path_not_in_errors( 'required.field-A', errors, ) assert_path_not_in_errors( 'required.field-B', errors, )
def test_enum_disperate_text_types(enum_value, value): schema = { 'enum': [enum_value], } validator = generate_validator_from_schema(schema) validator(value)
def test_enum_with_valid_array(letters): schema = { 'enum': [2, 1, 'a', 'b', 'c', True, False], } validator = generate_validator_from_schema(schema) validator(letters)
def test_field_declared_as_required_with_field_present_is_valid(): schema = { 'type': OBJECT, 'required': [ 'field-A', # 'field-B', ], } validator = generate_validator_from_schema(schema) try: validator({'field-A': 'present'}) except ValidationError as err: errors = err.detail else: errors = {} assert_path_not_in_errors( 'required.field-A', errors, ) assert_path_not_in_errors( 'required.field-B', errors, )
def test_enum_noop_when_not_required_and_field_not_present(): schema = { 'enum': [True, False, 1.0, 2.0, 'A'], } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_date_is_noop_when_not_present_or_required(): schema = { 'format': 'date', } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_date_format_validation(when): schema = { 'format': 'date', } validator = generate_validator_from_schema(schema) validator(when)
def test_date_time_format_validation(when): schema = { 'format': 'date-time', } validator = generate_validator_from_schema(schema) validator(when)
def test_non_required_circular_reference(): """ A schema which references itself is allowable, as long as the self reference is not required. This test ensures that such a case is handled. """ schema = { '$ref': 'Node', } definitions = schema_definitions_validator( { 'Node': { 'properties': { 'parent': { '$ref': 'Node' }, 'value': { 'type': STRING }, }, }, }, context={'deferred_references': set()}, ) validator = generate_validator_from_schema( schema, context={'definitions': definitions}, )
def test_field_declared_as_required_with_field_present_is_valid(): schema = { 'required': True, } validator = generate_validator_from_schema(schema) validator('John Smith')
def test_allof_complex(): schema_without_allof = { 'type': 'object', 'properties': { 'name': { 'type': STRING, }, 'age': { 'type': INTEGER, } } } schema_with_allof = { 'type': 'object', 'allOf': [ { 'properties': { 'name': { 'type': STRING, } } }, { 'properties': { 'age': { 'type': INTEGER, } } }, ] } good_data = dict(name="foo", age=42) bad_data = dict(name="foo", age="bar") validator_without_allof = generate_validator_from_schema(schema_without_allof) validator_with_allof = generate_validator_from_schema(schema_with_allof) validator_without_allof(good_data) validator_with_allof(good_data) with pytest.raises(ValidationError): validator_without_allof(bad_data) with pytest.raises(ValidationError): validator_with_allof(bad_data)
def test_pattern_is_noop_when_not_required_and_not_present(): schema = { 'type': STRING, 'pattern': ZIPCODE_REGEX, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_integer_multiple_of(count): schema = { 'type': INTEGER, 'multipleOf': 7, } validator = generate_validator_from_schema(schema) validator(count)
def test_maximum_length_is_noop_when_not_required_and_not_present(): schema = { 'type': STRING, 'maxLength': 5, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_unique_items_is_noop_when_not_required_and_not_present(): schema = { 'type': ARRAY, 'uniqueItems': True, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_maximum_length_with_valid_string(zipcode): schema = { 'type': STRING, 'maxLength': 10, } validator = generate_validator_from_schema(schema) validator(zipcode)
def test_maximum_length_with_valid_string(zipcode): schema = { 'type': STRING, 'maxLength': 10, } validator = generate_validator_from_schema(schema) validator(zipcode)
def test_type_validation_is_noop_when_not_required_and_not_present(): schema = { 'type': [INTEGER, STRING], } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_pattern_on_good_strings(zipcode): schema = { 'type': STRING, 'pattern': ZIPCODE_REGEX, } validator = generate_validator_from_schema(schema) validator(zipcode)
def test_min_items_allows_empty_when_not_required_and_not_present(): schema = { 'type': ARRAY, 'minItems': 3, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_unique_items_with_unique_array(letters): schema = { 'type': ARRAY, 'uniqueItems': True, } validator = generate_validator_from_schema(schema) validator(letters)
def test_valid_array_with_max_items(letters): schema = { 'type': ARRAY, 'maxItems': 3, } validator = generate_validator_from_schema(schema) validator(letters)
def test_unique_items_with_unique_array(letters): schema = { 'type': ARRAY, 'uniqueItems': True, } validator = generate_validator_from_schema(schema) validator(letters)
def test_pattern_on_good_strings(zipcode): schema = { 'type': STRING, 'pattern': ZIPCODE_REGEX, } validator = generate_validator_from_schema(schema) validator(zipcode)
def test_unique_items_is_noop_when_not_required_and_not_present(): schema = { 'type': ARRAY, 'uniqueItems': True, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_enum_with_invalid_items(letters): schema = { 'enum': [True, False, 1.0, 2.0, 'A'], } validator = generate_validator_from_schema(schema) with pytest.raises(ValueError): validator(letters)
def test_max_items_allows_empty_when_not_required_and_not_present(): schema = { 'type': ARRAY, 'maxItems': 3, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_valid_array_with_max_items(letters): schema = { 'type': ARRAY, 'maxItems': 3, } validator = generate_validator_from_schema(schema) validator(letters)
def test_multiple_of_is_noop_if_not_required_and_not_present(): schema = { 'type': INTEGER, 'multipleOf': 0.3, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_float_multiple_of(count): schema = { 'type': NUMBER, 'multipleOf': 0.1, } validator = generate_validator_from_schema(schema) validator(count)
def test_float_multiple_of(count): schema = { 'type': NUMBER, 'multipleOf': 0.1, } validator = generate_validator_from_schema(schema) validator(count)
def test_integer_multiple_of(count): schema = { 'type': INTEGER, 'multipleOf': 7, } validator = generate_validator_from_schema(schema) validator(count)
def test_min_properties_with_enough_properties(element): schema = { 'type': OBJECT, 'minProperties': 2, } validator = generate_validator_from_schema(schema) validator(element)
def test_multiple_of_is_noop_if_not_required_and_not_present(): schema = { 'type': INTEGER, 'multipleOf': 0.3, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_min_properties_is_noop_when_not_required_or_present(): schema = { 'type': OBJECT, 'minProperties': 2, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_pattern_is_noop_when_not_required_and_not_present(): schema = { 'type': STRING, 'pattern': ZIPCODE_REGEX, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_maximum_length_is_noop_when_not_required_and_not_present(): schema = { 'type': STRING, 'maxLength': 5, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_field_declared_as_required(): schema = { 'required': True, } validator = generate_validator_from_schema(schema) with pytest.raises(ValueError): validator(EMPTY)
def test_date_time_with_invalid_dates_strings(when): schema = { 'format': 'date-time', } validator = generate_validator_from_schema(schema) with pytest.raises(ValueError): validator(when)
def test_max_properties_is_noop_when_not_required_or_present(): schema = { 'type': OBJECT, 'maxProperties': 2, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_max_properties_with_enough_properties(element): schema = { 'type': OBJECT, 'maxProperties': 2, } validator = generate_validator_from_schema(schema) validator(element)
def test_minimum_noop_when_not_required_or_present(): schema = { 'type': NUMBER, 'minimum': 5, } validator = generate_validator_from_schema(schema) validator(EMPTY)
def test_inclusive_minimum_validation_with_valid_numbers(width): schema = { 'type': NUMBER, 'minimum': 5, } validator = generate_validator_from_schema(schema) validator(width)
def test_maximum_length_with_too_long_string(zipcode): schema = { 'type': STRING, 'maxLength': 10, } validator = generate_validator_from_schema(schema) with pytest.raises(ValidationError): validator(zipcode)
def test_minimum_length_with_too_short_string(zipcode): schema = { 'type': STRING, 'minLength': 5, } validator = generate_validator_from_schema(schema) with pytest.raises(ValidationError): validator(zipcode)
def test_max_properties_with_too_many_properties(element): schema = { 'type': OBJECT, 'maxProperties': 2, } validator = generate_validator_from_schema(schema) with pytest.raises(ValueError): validator(element)
def test_exclusive_maximum_validation_with_valid_numbers(width): schema = { 'type': NUMBER, 'maximum': 5, 'exclusiveMaximum': True, } validator = generate_validator_from_schema(schema) validator(width)