def test_nested_required_field(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "object": prop.Object( structure={ "sub_string": prop.String("the string", required=False), "required_string": prop.String(required=True) }) } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "object": { "sub_string": "hello", }, } with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "The field 'required_string' is required but not found in the body!"
def test_nullable_array_of_strings(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "array_of_strings": prop.Array( repeated_structure=prop.String("just a list of strings"), description="A description of what this array contains", required=True, nullable=False) } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "array_of_strings": None } with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "Non nullable field 'array_of_strings' is null!"
def test_multiple_invalid_fields_validation(): input_schema = { "social_security_number": prop.String(validators=[validators.SocialSecurityNumber()]), "exact_length_string": prop.String(validators=[validators.ExactLength(3)]), } given_request = { "social_security_number": "578234", "exact_length_string": "not three long", } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { 'message': 'Multiple fields have an error.', 'field_error_messages': { 'exact_length_string': "String is not the correct length! " "The string 'not three long' is 14 characters long, not 3!", 'social_security_number': '578234 is not a valid social security number!' } } assert http_status == HTTPStatus.BAD_REQUEST
def test_create_output_identical_dict(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "sub_dict": prop.Object(structure={"sub_string": prop.String()}) } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "sub_dict": { "sub_string": "hello", } } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "basic_string": "test string", "basic_boolean": True, "sub_dict": { "sub_string": "hello" } }
def test_create_output_array_of_strings(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "array_of_strings": prop.Array( repeated_structure=prop.String("just a list of strings"), description="A description of what this array contains") } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "array_of_strings": ["hello", "hello again"] } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "basic_string": "test string", "basic_boolean": True, "array_of_strings": ["hello", "hello again"] }
def test_validate_input_one_of_invalid(): input_schema = { "id": prop_wrapper.OneOf([ prop.String(validators=[validators.ExactLength(3)]), prop.String(validators=[validators.ExactLength(8)]), prop.Number() ]) } given_request = {"id": "banana_phone"} http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { 'message': 'A field has an error.', 'field_error_messages': { 'id': ("The value 'banana_phone' from field 'id' is not valid for one of the defined props for " "the following reasons: String is not the correct length! The string 'banana_phone' is " "12 characters long, not 3!, String is not the correct length! The string 'banana_phone' is " "12 characters long, not 8!, The value 'banana_phone' from field 'id' is the wrong " 'type, expected: Number') } } assert http_status == HTTPStatus.BAD_REQUEST
class DogFields(Fields): base_schema = { "name": prop.String("The dog's name."), "breed": prop.String("The dog's breed.") } def __init__(self): super().__init__(self.base_schema)
class CatFields(Fields): base_schema = { "name": prop.String("The cat's name."), "breed": prop.String("The cat's breed."), "color": prop.String("The cat's color.") } def __init__(self): super().__init__(self.base_schema)
def test_validate_input_one_of(): input_schema = { "id": prop_wrapper.OneOf([ prop.String(validators=[validators.ExactLength(3)]), prop.String(validators=[validators.ExactLength(8)]), prop.Number() ]) } given_request = {"id": "abc"} http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == {} assert http_status is HTTPStatus.OK
def test_triple_nested_dicts(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "sub_dict": prop.Object(structure={ "sub_string": prop.String("the string"), "sub_sub_dict": prop.Object(structure={"boo": prop.Boolean()}) }, description="A list of plans.") } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "sub_dict": { "sub_string": "hello", "not_this": "Not this", "sub_sub_dict": { "boo": False, "why_is_this_here": "ignore" } } } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "basic_string": "test string", "basic_boolean": True, "sub_dict": { "sub_string": "hello", "sub_sub_dict": { "boo": False } } }
def test_validate_input_multiple_missing_fields(): input_schema = { "basic_string": prop.String(required=True), "another_basic_string": prop.String(required=True), "basic_boolean": prop.Boolean() } given_request = { "basic_boolean": True, } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { "message": "Required fields are missing: ['basic_string', 'another_basic_string']", } assert http_status == HTTPStatus.BAD_REQUEST
def test_multiple_outputs(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean() }, HTTPStatus.BAD_REQUEST: { "message": prop.String("Nope") } } result = HTTPStatus.BAD_REQUEST, {"message": "Oh man"} http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 400 assert returned_dict == { "message": "Oh man", }
def test_create_output_array_of_objects(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "array_of_objects": prop.Array(repeated_structure=prop.Object( structure={"sub_string": prop.String("the string")}), description="A list of plans.") } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "array_of_objects": [{ "sub_string": "hello", "not_this": "not this" }, { "sub_string": "hello", "not_this": "still not this", "another_one": "???" }] } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "basic_string": "test string", "basic_boolean": True, "array_of_objects": [{ "sub_string": "hello", }, { "sub_string": "hello", }] }
def __init__(self, validated_fields=None): if validated_fields is not None: fields = {} for field in validated_fields: fields[field] = prop.String( f"A error message specific to the {field} field.") self.base_schema["field_error_messages"] = prop.Object( structure=fields, required=False, nullable=True) super().__init__(self.base_schema)
def test_validate_input_multiple_input_issues(): input_schema = { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "not_present_required_field": prop.String(required=True) } given_request = { "basic_string": "test string", "basic_boolean": True, "what_the_heck": "is this????", "more_BS": "SQL INJECTION!!" } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { "message": ("Unexpected fields were sent to the server: [\'what_the_heck\', \'more_BS\'] /// " "A required field is missing: not_present_required_field") } assert http_status == HTTPStatus.BAD_REQUEST
def test_very_nested_nullable_field(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "array_of_objects": prop.Array(repeated_structure=prop.Object( structure={ "sub_string": prop.String("the string", required=True, nullable=False), "required_one": prop.String(required=True, nullable=False) }), description="A list of plans.") } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "array_of_objects": [{ "sub_string": None, "required_one": "here" }, { "sub_string": "hello", "required_one": "here_too" }] } with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "Non nullable field 'sub_string' is null!"
def test_output_of_wrong_type(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), } } result = HTTPStatus.OK, {"basic_string": 80.99} with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "The value 80.99 from field 'basic_string' is the wrong type, expected: String"
def test_one_of(): output_schema = { HTTPStatus.OK: { "basic_string": prop_wrapper.OneOf([prop.String(), prop.Boolean()]) } } result = HTTPStatus.OK, {"basic_string": "asdf"} http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == {"basic_string": "asdf"}
def test_no_defined_schema(): output_schema = { HTTPStatus.BAD_REQUEST: { "basic_string": prop.String("Description", required=True, nullable=True), } } result = HTTPStatus.OK, {} with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "Endpoint does not define http status code 200 in the output schema!"
def test_required_false_nullable_true_is_present_not_none_not_there(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String("Description", required=False, nullable=True), } } result = HTTPStatus.OK, {} http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == {}
def test_required_true_nullable_true_not_present(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String("Description", required=True, nullable=True), } } result = HTTPStatus.OK, {} with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "The field 'basic_string' is required but not found in the body!"
def test_validate_input(): input_schema = { "basic_string": prop.String(), "basic_boolean": prop.Boolean() } given_request = { "basic_string": "test string", "basic_boolean": True, } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == {} assert http_status is HTTPStatus.OK
def test_required_false_nullable_false_is_present_not_none_there_and_null(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String("Description", required=False, nullable=False), } } result = HTTPStatus.OK, {"basic_string": None} with pytest.raises(prop.ValidationError) as e: create_output(result, output_schema) assert e.value.message == "Non nullable field 'basic_string' is null!"
def test_create_output_different_dict(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean(), "sub_dict": prop.Object( structure={"sub_string": prop.String()}, description="This is a fake object nested in a dictionary", required=True, nullable=False) } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "sub_dict": { "sub_string": "hello", "not_this": "Not this" } } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "basic_string": "test string", "basic_boolean": True, "sub_dict": { "sub_string": "hello" } }
def test_validate_input_missing_field(): input_schema = { "basic_string": prop.String(required=True), "basic_boolean": prop.Boolean() } given_request = { "basic_boolean": True, } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { "message": "A required field is missing: basic_string" } assert http_status == HTTPStatus.BAD_REQUEST
def test_validate_input_unexpected_field(): input_schema = { "basic_string": prop.String(), "basic_boolean": prop.Boolean() } given_request = { "basic_string": "test string", "basic_boolean": True, "what_the_heck": "is this????" } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { "message": "An unexpected field was sent to the server: what_the_heck" } assert http_status == HTTPStatus.BAD_REQUEST
def test_nested_specializer_object_with_results_array_of_strings(): output_schema = { HTTPStatus.OK: { "results": prop.Array(repeated_structure=prop.String( "this is an array of strings", required=True, nullable=False)) } } result = HTTPStatus.OK, { "results": ["perfectly", "valid", "array", "of", "strings"] } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "results": ["perfectly", "valid", "array", "of", "strings"] }
def test_validate_input_exact_length_string(): input_schema = { "basic_string": prop.String(validators=[validators.ExactLength(8)]), } given_request = { "basic_string": "noteightlong", } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { 'message': 'A field has an error.', 'field_error_messages': { 'basic_string': 'String is not the correct length! The string \'noteightlong\' is 12 characters long, not 8!' } } assert http_status == HTTPStatus.BAD_REQUEST
def test_validate_social_security_number(): input_schema = { "social_security_number": prop.String(validators=[validators.SocialSecurityNumber()]), } given_request = { "social_security_number": "219099999", } http_status, reject_dict = validate_input(given_request, input_schema) assert reject_dict == { 'message': 'A field has an error.', 'field_error_messages': { 'social_security_number': '219099999 is not a valid social security number!' } } assert http_status == HTTPStatus.BAD_REQUEST
def test_create_output(): output_schema = { HTTPStatus.OK: { "basic_string": prop.String(), "basic_boolean": prop.Boolean() } } result = HTTPStatus.OK, { "basic_string": "test string", "basic_boolean": True, "secret_info": "secret info" } http_status_code, returned_dict = create_output(result, output_schema) assert http_status_code == 200 assert returned_dict == { "basic_string": "test string", "basic_boolean": True }