def test_get_pets_param_order(self, spec): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets" query_params = { "limit": None, "order": "desc", } request = MockRequest( host_url, "GET", "/pets", path_pattern=path_pattern, args=query_params, ) with pytest.warns(DeprecationWarning): parameters = spec_validate_parameters(spec, request) assert parameters == Parameters( query={ "limit": None, "order": "desc", "page": 1, "search": "", } ) body = spec_validate_body(spec, request) assert body is None
def test_get_pets_param_coordinates(self, spec): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets" coordinates = { "lat": 1.12, "lon": 32.12, } query_params = { "limit": None, "coordinates": json.dumps(coordinates), } request = MockRequest( host_url, "GET", "/pets", path_pattern=path_pattern, args=query_params, ) with pytest.warns(DeprecationWarning): parameters = spec_validate_parameters(spec, request) assert parameters == Parameters( query={ "limit": None, "page": 1, "search": "", "coordinates": coordinates, } ) body = spec_validate_body(spec, request) assert body is None
def test_delete_tags_raises_missing_required_response_header( self, spec, response_validator ): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/tags" request = MockRequest( host_url, "DELETE", "/tags", path_pattern=path_pattern, ) parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters() assert body is None data = None response = MockResponse(data, status_code=200) with pytest.warns(DeprecationWarning): response_result = response_validator.validate(request, response) assert response_result.errors == [ MissingRequiredHeader(name="x-delete-confirm"), ] assert response_result.data is None
def test_missing_body(self, validator): headers = { "api-key": self.api_key_encoded, } cookies = { "user": "******", } request = MockRequest( "https://development.gigantic-server.com", "post", "/v1/pets", path_pattern="/v1/pets", headers=headers, cookies=cookies, ) result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == MissingRequiredRequestBody assert result.body is None assert result.parameters == Parameters( header={ "api-key": self.api_key, }, cookie={ "user": 123, }, )
def test_post_tags_extra_body_properties(self, spec, spec_dict): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/tags" pet_name = "Dog" alias = "kitty" data_json = { "name": pet_name, "alias": alias, } data = json.dumps(data_json) request = MockRequest( host_url, "POST", "/tags", path_pattern=path_pattern, data=data, ) parameters = spec_validate_parameters(spec, request) assert parameters == Parameters() with pytest.raises(InvalidSchemaValue): spec_validate_body(spec, request)
def test_post_pets_plain_no_schema(self, validator, spec_dict): data = "plain text" headers = { "api-key": self.api_key_encoded, } cookies = { "user": "******", } request = MockRequest( "https://development.gigantic-server.com", "post", "/v1/pets", path_pattern="/v1/pets", data=data, headers=headers, cookies=cookies, mimetype="text/plain", ) with pytest.warns(UserWarning): result = validator.validate(request) assert result.errors == [] assert result.parameters == Parameters( header={ "api-key": self.api_key, }, cookie={ "user": 123, }, ) assert result.security == {} assert result.body == data
def test_invalid_content_type(self, validator): data = "csv,data" headers = { "api-key": self.api_key_encoded, } cookies = { "user": "******", } request = MockRequest( "https://development.gigantic-server.com", "post", "/v1/pets", path_pattern="/v1/pets", mimetype="text/csv", data=data, headers=headers, cookies=cookies, ) result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == MediaTypeNotFound assert result.body is None assert result.parameters == Parameters( header={ "api-key": self.api_key, }, cookie={ "user": 123, }, )
def test_get_pet_wildcard(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets/{petId}" view_args = { "petId": "1", } request = MockRequest( host_url, "GET", "/pets/1", path_pattern=path_pattern, view_args=view_args, ) parameters = spec_validate_parameters(spec, request) assert parameters == Parameters( path={ "petId": 1, } ) body = spec_validate_body(spec, request) assert body is None data = b"imagedata" response = MockResponse(data, mimetype="image/png") with pytest.warns(UserWarning): response_result = response_validator.validate(request, response) assert response_result.errors == [] assert response_result.data == data
def test_get_tags(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/tags" request = MockRequest( host_url, "GET", "/tags", path_pattern=path_pattern, ) parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters() assert body is None data_json = ["cats", "birds"] data = json.dumps(data_json) response = MockResponse(data) response_result = response_validator.validate(request, response) assert response_result.errors == [] assert response_result.data == data_json
def _get_parameters(self, request, path, operation): operation_params = operation.get("parameters", []) path_params = path.get("parameters", []) errors = [] seen = set() parameters = Parameters() params_iter = iter_params(operation_params, path_params) for param in params_iter: param_name = param["name"] param_location = param["in"] if (param_name, param_location) in seen: # skip parameter already seen # e.g. overriden path item paremeter on operation continue seen.add((param_name, param_location)) try: value = self._get_parameter(param, request) except MissingParameter: continue except ( MissingRequiredParameter, DeserializeError, CastError, ValidateError, UnmarshalError, ) as exc: errors.append(exc) continue else: location = getattr(parameters, param_location) location[param_name] = value return parameters, errors
def test_request_missing_param(self, validator): request = MockRequest("http://example.com", "get", "/resource") result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == MissingRequiredParameter assert result.body is None assert result.parameters == Parameters()
def test_get_pet(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets/{petId}" view_args = { "petId": "1", } auth = "authuser" headers = { "Authorization": f"Basic {auth}", } request = MockRequest( host_url, "GET", "/pets/1", path_pattern=path_pattern, view_args=view_args, headers=headers, ) parameters = spec_validate_parameters(spec, request) assert parameters == Parameters( path={ "petId": 1, } ) body = spec_validate_body(spec, request) assert body is None security = spec_validate_security(spec, request) assert security == { "petstore_auth": auth, } data_id = 1 data_name = "test" data_json = { "data": { "id": data_id, "name": data_name, "ears": { "healthy": True, }, }, } data = json.dumps(data_json) response = MockResponse(data) response_result = response_validator.validate(request, response) assert response_result.errors == [] assert isinstance(response_result.data, BaseModel) assert isinstance(response_result.data.data, BaseModel) assert response_result.data.data.id == data_id assert response_result.data.data.name == data_name
def test_invalid_path(self, validator): request = MockRequest(self.host_url, "get", "/v1") result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == PathNotFound assert result.body is None assert result.parameters == Parameters()
def test_invalid_operation(self, validator): request = MockRequest(self.host_url, "patch", "/v1/pets") result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == OperationNotFound assert result.body is None assert result.parameters == Parameters()
def test_request_server_error(self, validator): request = MockRequest("http://petstore.invalid.net/v1", "get", "/") result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == PathNotFound assert result.body is None assert result.parameters == Parameters()
def test_post_pets(self, validator, spec_dict): pet_name = "Cat" pet_tag = "cats" pet_street = "Piekna" pet_city = "Warsaw" data_json = { "name": pet_name, "tag": pet_tag, "position": 2, "address": { "street": pet_street, "city": pet_city, }, "ears": { "healthy": True, }, } data = json.dumps(data_json) headers = { "api-key": self.api_key_encoded, } cookies = { "user": "******", } request = MockRequest( "https://development.gigantic-server.com", "post", "/v1/pets", path_pattern="/v1/pets", data=data, headers=headers, cookies=cookies, ) result = validator.validate(request) assert result.errors == [] assert result.parameters == Parameters( header={ "api-key": self.api_key, }, cookie={ "user": 123, }, ) assert result.security == {} schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] address_model = schemas["Address"]["x-model"] assert result.body.__class__.__name__ == pet_model assert result.body.name == pet_name assert result.body.tag == pet_tag assert result.body.position == 2 assert result.body.address.__class__.__name__ == address_model assert result.body.address.street == pet_street assert result.body.address.city == pet_city
def test_post_tags_created_datetime(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/tags" created = "2016-04-16T16:06:05Z" pet_name = "Dog" data_json = { "created": created, "name": pet_name, } data = json.dumps(data_json) request = MockRequest( host_url, "POST", "/tags", path_pattern=path_pattern, data=data, ) parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters() assert isinstance(body, BaseModel) assert body.created == datetime(2016, 4, 16, 16, 6, 5, tzinfo=UTC) assert body.name == pet_name code = 400 message = "Bad request" rootCause = "Tag already exist" additionalinfo = "Tag Dog already exist" response_data_json = { "code": code, "message": message, "rootCause": rootCause, "additionalinfo": additionalinfo, } response_data = json.dumps(response_data_json) response = MockResponse(response_data, status_code=404) data = spec_validate_data(spec, request, response) assert isinstance(data, BaseModel) assert data.code == code assert data.message == message assert data.rootCause == rootCause assert data.additionalinfo == additionalinfo response_result = response_validator.validate(request, response) assert response_result.errors == [] assert isinstance(response_result.data, BaseModel) assert response_result.data.code == code assert response_result.data.message == message assert response_result.data.rootCause == rootCause assert response_result.data.additionalinfo == additionalinfo
def test_get_pets_invalid_response(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets" query_params = { "limit": "20", } request = MockRequest( host_url, "GET", "/pets", path_pattern=path_pattern, args=query_params, ) with pytest.warns(DeprecationWarning): parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters( query={ "limit": 20, "page": 1, "search": "", } ) assert body is None response_data_json = { "data": [ { "id": 1, "name": { "first_name": "Cat", }, } ], } response_data = json.dumps(response_data_json) response = MockResponse(response_data) with pytest.raises(InvalidSchemaValue): spec_validate_data(spec, request, response) response_result = response_validator.validate(request, response) schema_errors = response_result.errors[0].schema_errors assert response_result.errors == [ InvalidSchemaValue( type="object", value=response_data_json, schema_errors=schema_errors, ), ] assert response_result.data is None
def view_response_callable(*args, **kwargs): from flask.globals import request assert request.openapi assert not request.openapi.errors assert request.openapi.parameters == Parameters(path={ "id": 12, }) resp = make_response("success", 200) resp.headers["X-Rate-Limit"] = "12" return resp
def test_missing_parameter(self, validator): request = MockRequest(self.host_url, "get", "/v1/pets") with pytest.warns(DeprecationWarning): result = validator.validate(request) assert type(result.errors[0]) == MissingRequiredParameter assert result.body is None assert result.parameters == Parameters(query={ "page": 1, "search": "", }, )
def test_invalid_path(self, factory, server, spec_path): spec_dict = factory.spec_from_file(spec_path) spec = create_spec(spec_dict) validator = RequestValidator(spec) request = MockRequest(server, "get", "/nonexistent") result = validator.validate(request) assert len(result.errors) == 1 assert isinstance(result.errors[0], PathNotFound) assert result.body is None assert result.parameters == Parameters()
def test_invalid_operation(self, factory, server, spec_path): spec_dict = factory.spec_from_file(spec_path) spec = Spec.create(spec_dict) validator = RequestValidator(spec) request = MockRequest(server, "post", "/status") result = validator.validate(request) assert len(result.errors) == 1 assert isinstance(result.errors[0], OperationNotFound) assert result.body is None assert result.parameters == Parameters()
def test_request_valid_param(self, validator): request = MockRequest( "http://example.com", "get", "/resource", args={"resId": "10"}, ) result = validator.validate(request) assert len(result.errors) == 0 assert result.body is None assert result.parameters == Parameters(query={"resId": 10})
def test_request_invalid_param(self, validator): request = MockRequest( "http://example.com", "get", "/resource", args={"resId": "invalid"}, ) result = validator.validate(request) assert len(result.errors) == 1 assert type(result.errors[0]) == CastError assert result.body is None assert result.parameters == Parameters()
def test_get_pets_response(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets" query_params = { "limit": "20", } request = MockRequest( host_url, "GET", "/pets", path_pattern=path_pattern, args=query_params, ) with pytest.warns(DeprecationWarning): parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters( query={ "limit": 20, "page": 1, "search": "", } ) assert body is None data_json = { "data": [ { "id": 1, "name": "Cat", "ears": { "healthy": True, }, } ], } data = json.dumps(data_json) response = MockResponse(data) response_result = response_validator.validate(request, response) assert response_result.errors == [] assert isinstance(response_result.data, BaseModel) assert len(response_result.data.data) == 1 assert response_result.data.data[0].id == 1 assert response_result.data.data[0].name == "Cat"
def test_delete_tags_no_requestbody(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/tags" request = MockRequest( host_url, "DELETE", "/tags", path_pattern=path_pattern, ) parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters() assert body is None
def test_post_tags_created_invalid_type(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/tags" created = "long time ago" pet_name = "Dog" data_json = { "created": created, "name": pet_name, } data = json.dumps(data_json) request = MockRequest( host_url, "POST", "/tags", path_pattern=path_pattern, data=data, ) parameters = spec_validate_parameters(spec, request) with pytest.raises(InvalidSchemaValue): spec_validate_body(spec, request) assert parameters == Parameters() code = 400 message = "Bad request" correlationId = UUID("a8098c1a-f86e-11da-bd1a-00112444be1e") rootCause = "Tag already exist" additionalinfo = "Tag Dog already exist" data_json = { "message": message, "correlationId": str(correlationId), "rootCause": rootCause, "additionalinfo": additionalinfo, } data = json.dumps(data_json) response = MockResponse(data, status_code=404) response_result = response_validator.validate(request, response) assert response_result.errors == [] assert isinstance(response_result.data, BaseModel) assert response_result.data.code == code assert response_result.data.message == message assert response_result.data.correlationId == correlationId assert response_result.data.rootCause == rootCause assert response_result.data.additionalinfo == additionalinfo
def test_post_cats_only_required_body(self, spec, spec_dict): host_url = "https://staging.gigantic-server.com/v1" path_pattern = "/v1/pets" pet_name = "Cat" pet_healthy = True data_json = { "name": pet_name, "ears": { "healthy": pet_healthy, }, } data = json.dumps(data_json) headers = { "api-key": self.api_key_encoded, } cookies = { "user": "******", } request = MockRequest( host_url, "POST", "/pets", path_pattern=path_pattern, data=data, headers=headers, cookies=cookies, ) parameters = spec_validate_parameters(spec, request) assert parameters == Parameters( header={ "api-key": self.api_key, }, cookie={ "user": 123, }, ) body = spec_validate_body(spec, request) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] assert body.__class__.__name__ == pet_model assert body.name == pet_name assert not hasattr(body, "tag") assert not hasattr(body, "address")
def test_get_pets(self, spec, response_validator): host_url = "http://petstore.swagger.io/v1" path_pattern = "/v1/pets" query_params = { "limit": "20", } request = MockRequest( host_url, "GET", "/pets", path_pattern=path_pattern, args=query_params, ) with pytest.warns(DeprecationWarning): parameters = spec_validate_parameters(spec, request) body = spec_validate_body(spec, request) assert parameters == Parameters( query={ "limit": 20, "page": 1, "search": "", } ) assert body is None data_json = { "data": [], } data = json.dumps(data_json) headers = { "Content-Type": "application/json", "x-next": "next-url", } response = MockResponse(data, headers=headers) response_result = response_validator.validate(request, response) assert response_result.errors == [] assert isinstance(response_result.data, BaseModel) assert response_result.data.data == [] assert response_result.headers == { "x-next": "next-url", }
def test_get_pet_unauthorized(self, validator): request = MockRequest( self.host_url, "get", "/v1/pets/1", path_pattern="/v1/pets/{petId}", view_args={"petId": "1"}, ) result = validator.validate(request) assert result.errors == [ InvalidSecurity(), ] assert result.body is None assert result.parameters == Parameters() assert result.security is None