def test_failure_on_path_parameter_used_but_not_defined(swagger_spec): swagger_spec['paths']['/user/{username}']['get']['parameters'][0][ 'name'] = '_' with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert "Path parameter 'username' used is not documented on '/user/{username}'" in str( exc_info.value)
def test_failure_on_unresolvable_path_parameter(swagger_spec): swagger_spec['paths']['/pet/{petId}']['get']['parameters'] = [] with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert "Path parameter 'petId' used is not documented on '/pet/{petId}'" in str( exc_info.value)
def load_schema(swagger_file): # type: (Path) -> dict with swagger_file.open() as swagger_json: specification = json.load(swagger_json, object_pairs_hook=OrderedDict) resolver = RefResolver( os.path.join(swagger_file.parent.absolute().as_uri(), ''), specification) resolved_specification = _resolve_refs(specification, resolver) # our schema files only contain `definitions`, so we copy them and add the # mandatory so we can use the swagger validation here valid_specification = { 'swagger': '2.0', 'info': { 'version': '0.0', 'title': '' }, 'paths': {} } valid_specification.update(resolved_specification) validate_spec(valid_specification) return resolved_specification
def build(self): if self.config['validate_swagger_spec']: validator20.validate_spec(self.spec_dict) self.api_url = build_api_serving_url(self.spec_dict, self.origin_url) self.definitions = build_models(self.spec_dict.get('definitions', {})) self.resources = build_resources(self)
def test_recursive_ref_failure(minimal_swagger_dict, node_spec): minimal_swagger_dict['definitions']['Node'] = node_spec # insert non-existent $ref node_spec['properties']['foo'] = {'$ref': '#/definitions/Foo'} with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(minimal_swagger_dict) assert 'Unresolvable JSON pointer' in str(excinfo.value)
def _validate_swagger_spec_validator(self): from swagger_spec_validator.common import SwaggerValidationError as SSVErr from swagger_spec_validator.validator20 import validate_spec try: validate_spec(self.specification) except SSVErr as ex: raise SwaggerValidationError(str(ex))
def test_failure_on_duplicate_operation_parameters(swagger_spec): param1 = {"name": "foo", "in": "query", "type": "string"} param2 = {"name": "foo", "in": "query", "type": "integer"} swagger_spec['paths']['/pet']['post']['parameters'].extend([param1, param2]) with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert ("Duplicate param found with (name, in): {}".format(("foo", "query")) in str(exc_info.value))
def generate(destination, swagger_doc, force=False, package=None, template_dir=None, templates='flask', specification=False, ui=False, validate=False): package = package or destination.replace('-', '_') data = spec_load(swagger_doc) if validate: try: validate_spec(data) click.echo("Validation passed") except SwaggerValidationError as e: raise click.ClickException(str(e)) #print 'data ',data swagger = Swagger(data) if templates == 'tornado': generator = TornadoGenerator(swagger) elif templates == 'falcon': generator = FalconGenerator(swagger) elif templates == 'sanic': generator = SanicGenerator(swagger) else: generator = FlaskGenerator(swagger) generator.with_spec = specification generator.with_ui = ui template = Template() if template_dir: template.add_searchpath(template_dir) env = dict(package=package, module=swagger.module_name) if ui: ui_dest = join(destination, '%(package)s/static/swagger-ui' % env) ui_src = join(dirname(__file__), 'templates/ui') status = _copy_ui_dir(ui_dest, ui_src) click.secho('%-12s%s' % (status, ui_dest)) for code in generator.generate(): source = template.render_code(code, package=package, module=swagger.module_name) dest = join(destination, code.dest(env)) dest_exists = exists(dest) can_override = force or code.override statuses = { (False, False): 'generate', (False, True): 'generate', (True, False): 'skip', (True, True): 'override' } status = statuses[(dest_exists, can_override)] click.secho('%-12s' % status, nl=False) click.secho(dest) if status != 'skip': write(dest, source)
def test_additional_properties_bool(minimal_swagger_dict, default_checks_spec_dict): minimal_swagger_dict['definitions']['injected_definition'] = { 'type': 'object', 'additionalProperties': False, } validate_spec(minimal_swagger_dict)
def test_failure_because_references_in_operation_responses(): my_dir = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(my_dir, '../data/v2.0/invalid_swagger_specs_because_ref_in_responses.json')) as f: invalid_spec = json.load(f) with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(invalid_spec) assert 'GET /endpoint does not have a valid responses section. ' \ 'That section cannot be just a reference to another object.' in str(excinfo.value)
def test_failure_on_duplicate_api_parameters(swagger_spec): param1 = {"name": "foo", "in": "query", "type": "string"} param2 = {"name": "foo", "in": "query", "type": "integer"} swagger_spec['paths']['/pet']['parameters'] = [param1, param2] with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert ("Duplicate param found with (name, in): ('foo', 'query')" in str(exc_info.value))
def test_specs_with_discriminator_in_allOf_fail_because_not_string(): file_path = '../../tests/data/v2.0/test_polymorphic_specs/swagger.json' swagger_dict, _ = get_spec_json_and_url(file_path) swagger_dict['definitions']['BaseObject']['discriminator'] = 'weight' with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(swagger_dict) assert 'discriminator (weight) must be a string property' in str(excinfo.value)
def jsonref_petstore_dict(): my_dir = os.path.abspath(os.path.dirname(__file__)) fpath = os.path.join(my_dir, '../../test-data/2.0/petstore/swagger.json') with open(fpath) as f: petstore = json.loads(f.read()) fix_malformed_model_refs(petstore) unrefed_petstore = jsonref.JsonRef.replace_refs(petstore) validator20.validate_spec(unrefed_petstore) return unrefed_petstore
def test_failure_on_unresolvable_ref_of_props_required_list(swagger_spec): swagger_spec['definitions']['Pet']['required'].append('bla') with pytest.raises( SwaggerValidationError, match= r".*In definition of .*, required list has properties not defined: .*", ) as exc_info: validate_spec(swagger_spec) assert str(['bla']) in str(exc_info.value)
def test_array_items_validated(minimal_swagger_dict, default_checks_spec_dict): invalid_spec = {'type': 'object', 'required': ['foo']} minimal_swagger_dict['definitions']['injected_definition'] = { 'type': 'array', 'items': invalid_spec } with pytest.raises(SwaggerValidationError): validate_spec(minimal_swagger_dict)
def test_type_array_without_items_succeed_fails(minimal_swagger_dict, swagger_dict_override): minimal_swagger_dict.update(swagger_dict_override) with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(minimal_swagger_dict) assert str( excinfo.value ) == 'Definition of type array must define `items` property (definition #/definitions/definition_1).'
def test_flattened_specs_with_no_xmodel_tags(multi_file_with_no_xmodel_spec, flattened_multi_file_with_no_xmodel_dict): flattened_spec = multi_file_with_no_xmodel_spec.flattened_spec validator20.validate_spec( # Deep copy needed because validate_spec adds x-scope information spec_dict=copy.deepcopy(flattened_spec), spec_url='', http_handlers={}, ) assert flattened_spec == flattened_multi_file_with_no_xmodel_dict
def test_specs_with_discriminator_fail_because_not_required(): file_path = '../../tests/data/v2.0/test_polymorphic_specs/swagger.json' swagger_dict, _ = get_spec_json_and_url(file_path) swagger_dict['definitions']['GenericPet']['discriminator'] = 'name' with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(swagger_dict) assert 'discriminator (name) must be defined a required property' in str(excinfo.value)
def test_failure_because_references_in_operation_responses(): with open( './tests/data/v2.0/invalid_swagger_specs_because_ref_in_responses.json' ) as f: invalid_spec = json.load(f) with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(invalid_spec) assert 'GET /endpoint does not have a valid responses section. ' \ 'That section cannot be just a reference to another object.' in str(excinfo.value)
def test_valid_specs_with_check_of_default_types(default_checks_spec_dict, property_spec): default_checks_spec_dict['definitions']['injected_definition'] = { 'properties': { 'property': property_spec }, } # Success if no exception are raised validate_spec(default_checks_spec_dict)
def test_read_yaml_specs(): file_path = '../../tests/data/v2.0/test_polymorphic_specs/swagger.json' swagger_dict, _ = get_spec_json_and_url(file_path) swagger_dict['definitions']['BaseObject']['discriminator'] = 'an_other_property' with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(swagger_dict) assert 'discriminator (an_other_property) must be defined in properties' in str(excinfo.value)
def test_build_swagger_json(schema): index, spec = schema app = Mock() app.schemastore._schemas = {index: spec} swagger_spec = build_swagger_json(index, spec) # does not raise validate_spec(swagger_spec)
def test_failure_due_to_wrong_default_type(default_checks_spec_dict, property_spec, validator, instance): default_checks_spec_dict['definitions']['injected_definition'] = { 'properties': {'property': property_spec}, } with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(default_checks_spec_dict) validation_error = excinfo.value.args[1] assert validation_error.instance == instance assert validation_error.validator == validator
def test_validate_server_spec(): plugin_server = server.PluginServer("test") with plugin_server.app.test_request_context(): plugin_server.register_blueprint() plugin_server.register_api_spec() # Create Swagger Spec with open("insightconnect-plugin-swagger.json", "w+") as api_spec: api_spec.write(json.dumps(plugin_server.spec.to_dict(), indent=2)) validate_spec(plugin_server.spec.to_dict())
def _validate_swagger_spec_validator(self, spec_version): # pragma: nocover from swagger_spec_validator.common import SwaggerValidationError as SSVErr from swagger_spec_validator.validator20 import validate_spec try: validate_spec(self.specification) except SSVErr as ex: from .util.exceptions import raise_from raise_from(ValidationError, ex) self.__set_version(BaseParser.SPEC_VERSION_2_PREFIX, spec_version)
def __init__(self, swagger_path=None, swagger_dict=None, swagger_yaml=None, use_example=True): """Run parsing from either a file or a dict. Args: swagger_path: path of the swagger file. swagger_dict: swagger dict. use_example: Define if we use the example from the YAML when we build definitions example (False value can be useful when making test. Problem can happen if set to True, eg POST {'id': 'example'}, GET /string => 404). Raises: - ValueError: if no swagger_path or swagger_dict is specified. Or if the given swagger is not valid. """ try: if swagger_path is not None: # Open yaml file arguments = {} with codecs.open(swagger_path, 'r', 'utf-8') as swagger_yaml: swagger_template = swagger_yaml.read() swagger_string = jinja2.Template(swagger_template).render( **arguments) self.specification = yaml.load(swagger_string) elif swagger_yaml is not None: json_ = yaml.load(swagger_yaml) json_string = json.dumps(json_) # the json must contain all strings in the form of u'some_string'. replaced_json_string = re.sub("'(.*)'", "u'\1'", json_string) self.specification = json.loads(replaced_json_string) elif swagger_dict is not None: self.specification = swagger_dict else: raise ValueError('You must specify a swagger_path or dict') validate_spec(self.specification, '') except Exception as e: six.reraise( ValueError, ValueError('{0} is not a valid swagger2.0 file: {1}'.format( swagger_path, e)), sys.exc_info()[2]) # Run parsing self.use_example = use_example self.base_path = self.specification.get('basePath', '') self.definitions_example = {} self.build_definitions_example() self.paths = {} self.operation = {} self.generated_operation = {} self.get_paths_data()
def test_flattened_spec_provide_valid_specs( flattened_multi_file_recursive_dict, multi_file_recursive_spec, ): flattened_spec = multi_file_recursive_spec.flattened_spec validator20.validate_spec( # Deep copy needed because validate_spec adds x-scope information spec_dict=copy.deepcopy(flattened_spec), spec_url='', http_handlers={}, ) assert flattened_spec == flattened_multi_file_recursive_dict
def test_api_parameters_as_refs(): # Verify issue #29 - instragram.json comes from: # # http://editor.swagger.io/#/ # -> File # -> Open Example... # -> instagram.yaml # # and then export it to a json file. instagram_specs, _ = get_spec_json_and_url('../data/v2.0/instagram.json') validate_spec(instagram_specs)
def test_api_parameters_as_refs(): # Verify issue #29 - instragram.json comes from: # # http://editor.swagger.io/#/ # -> File # -> Open Example... # -> instagram.yaml # # and then export it to a json file. my_dir = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(my_dir, '../data/v2.0/instagram.json')) as f: validate_spec(json.loads(f.read()))
def test_type_array_with_items_succeed_validation(minimal_swagger_dict): minimal_swagger_dict['definitions'] = { 'definition_1': { 'type': 'array', 'items': { 'type': 'string', }, }, } # Success if no exception are raised validate_spec(minimal_swagger_dict)
def test_fails_on_invalid_external_ref_in_list(): # The external ref in petstore.json is valid. # The contents of the external ref (pet.json#/get_all_parameters) is not # - the 'name' key in the parameter is missing. petstore_spec, petstore_url = get_spec_json_and_url( './tests/data/v2.0/test_fails_on_invalid_external_ref_in_list/petstore.json' ) with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(petstore_spec, petstore_url) assert "is not valid under any of the given schemas" in str(excinfo.value)
def generate(destination, swagger_doc, force=False, package=None, template_dir=None, templates='flask', specification=False, ui=False, validate=False): package = package or destination.replace('-', '_') data = spec_load(swagger_doc) if validate: try: validate_spec(data) click.echo("Validation passed") except SwaggerValidationError as e: raise click.ClickException(str(e)) #print 'data ',data swagger = Swagger(data) if templates == 'tornado': generator = TornadoGenerator(swagger) elif templates == 'falcon': generator = FalconGenerator(swagger) elif templates == 'sanic': generator = SanicGenerator(swagger) else: generator = FlaskGenerator(swagger) generator.with_spec = specification generator.with_ui = ui template = Template() if template_dir: template.add_searchpath(template_dir) env = dict(package=package, module=swagger.module_name) if ui: ui_dest = join(destination, '%(package)s/static/swagger-ui' % env) ui_src = join(dirname(__file__), 'templates/ui') status = _copy_ui_dir(ui_dest, ui_src) click.secho('%-12s%s' % (status, ui_dest)) for code in generator.generate(): source = template.render_code(code) dest = join(destination, code.dest(env)) dest_exists = exists(dest) can_override = force or code.override statuses = { (False, False): 'generate', (False, True): 'generate', (True, False): 'skip', (True, True): 'override' } status = statuses[(dest_exists, can_override)] click.secho('%-12s' % status, nl=False) click.secho(dest) if status != 'skip': write(dest, source)
def _validate_spec(self): if self.config['validate_swagger_spec']: self.resolver = validator20.validate_spec( spec_dict=self.spec_dict, spec_url=self.origin_url or '', http_handlers=build_http_handlers(self.http_client), )
def __init__(self, swagger_path=None, swagger_dict=None, swagger_yaml=None, use_example=True): """Run parsing from either a file or a dict. Args: swagger_path: path of the swagger file. swagger_dict: swagger dict. use_example: Define if we use the example from the YAML when we build definitions example (False value can be useful when making test. Problem can happen if set to True, eg POST {'id': 'example'}, GET /string => 404). Raises: - ValueError: if no swagger_path or swagger_dict is specified. Or if the given swagger is not valid. """ try: if swagger_path is not None: # Open yaml file arguments = {} with codecs.open(swagger_path, 'r', 'utf-8') as swagger_yaml: swagger_template = swagger_yaml.read() swagger_string = jinja2.Template(swagger_template).render(**arguments) self.specification = yaml.load(swagger_string) elif swagger_yaml is not None: json_ = yaml.load(swagger_yaml) json_string = json.dumps(json_) # the json must contain all strings in the form of u'some_string'. replaced_json_string = re.sub("'(.*)'", "u'\1'", json_string) self.specification = json.loads(replaced_json_string) elif swagger_dict is not None: self.specification = swagger_dict else: raise ValueError('You must specify a swagger_path or dict') validate_spec(self.specification, '') except Exception as e: raise ValueError('{0} is not a valid swagger2.0 file: {1}'.format(swagger_path, e)) # Run parsing self.use_example = use_example self.base_path = self.specification.get('basePath', '') self.definitions_example = {} self.build_definitions_example() self.paths = {} self.operation = {} self.generated_operation = {} self.get_paths_data()
def test_fails_on_invalid_external_ref(): # The external ref in petstore.json is valid. # The contents of the external ref (pet.json#/getall) is not - the 'name' # key in the parameter is missing. my_dir = os.path.abspath(os.path.dirname(__file__)) petstore_path = os.path.join( my_dir, '../data/v2.0/test_fails_on_invalid_external_ref/petstore.json') with open(petstore_path) as f: petstore_spec = json.load(f) petstore_url = 'file://{0}'.format(petstore_path) with pytest.raises(SwaggerValidationError) as excinfo: validate_spec(petstore_spec, petstore_url) assert 'is not valid under any of the given schemas' in str(excinfo.value)
def load_contract(self, f_swagger): with open(f_swagger) as FIN: raw = FIN.read() js = json.loads(raw) if validate_spec(js) is None: self.data = js return True msg = "Bad swaggerfile {}".format(f_swagger) raise SyntaxError(msg)
def build(self): if self.config['validate_swagger_spec']: self.resolver = validator20.validate_spec( self.spec_dict, spec_url=self.origin_url or '', http_handlers=build_http_handlers(self.http_client)) post_process_spec( self, on_container_callbacks=[ functools.partial( tag_models, visited_models={}, swagger_spec=self), functools.partial( collect_models, models=self.definitions, swagger_spec=self) ]) for format in self.config['formats']: self.register_format(format) self.api_url = build_api_serving_url(self.spec_dict, self.origin_url) self.resources = build_resources(self)
def test_complicated_refs(): def get_spec_json_and_url(rel_url): my_dir = os.path.abspath(os.path.dirname(__file__)) abs_path = os.path.join(my_dir, rel_url) with open(abs_path) as f: return json.loads(f.read()), urlparse.urljoin('file:', abs_path) # Split the swagger spec into a bunch of different json files and use # $refs all over to place to wire stuff together - see the test-data # files or this will make no sense whatsoever. file_path = '../../tests/data/v2.0/test_complicated_refs/swagger.json' swagger_dict, origin_url = get_spec_json_and_url(file_path) resolver = validate_spec(swagger_dict, spec_url=origin_url) # Hokey verification but better than nothing: # If all the files with $refs were ingested and validated and an # exception was not thrown, there should be 8 cached refs in the # resolver's store: # # 6 json files from ../../tests/data/v2.0/tests_complicated_refs/* # 1 draft3 spec # 1 draft4 spec assert len(resolver.store) == 8
def test_failure_on_unresolvable_model_reference_from_param(swagger_spec): param = swagger_spec['paths']['/pet']['post']['parameters'][0] param['schema']['$ref'] = '#/definitions/bla' with pytest.raises(SwaggerValidationError): validate_spec(swagger_spec)
def __init__(self, specification, base_path=None, arguments=None, validate_responses=False, strict_validation=False, resolver=None, auth_all_paths=False, debug=False, resolver_error_handler=None, validator_map=None, pythonic_params=False, options=None, **old_style_options): """ :type specification: pathlib.Path | dict :type base_path: str | None :type arguments: dict | None :type validate_responses: bool :type strict_validation: bool :type auth_all_paths: bool :type debug: bool :param validator_map: Custom validators for the types "parameter", "body" and "response". :type validator_map: dict :param resolver: Callable that maps operationID to a function :param resolver_error_handler: If given, a callable that generates an Operation used for handling ResolveErrors :type resolver_error_handler: callable | None :param pythonic_params: When True CamelCase parameters are converted to snake_case and an underscore is appended to any shadowed built-ins :type pythonic_params: bool :param options: New style options dictionary. :type options: dict | None :param old_style_options: Old style options support for backward compatibility. Preference is what is defined in `options` parameter. """ self.debug = debug self.validator_map = validator_map self.resolver_error_handler = resolver_error_handler self.options = ConnexionOptions(old_style_options) # options is added last to preserve the highest priority self.options = self.options.extend(options) # TODO: Remove this in later versions (Current version is 1.1.9) if base_path is None and 'base_url' in old_style_options: base_path = old_style_options['base_url'] logger.warning("Parameter base_url should be no longer used. Use base_path instead.") logger.debug('Loading specification: %s', specification, extra={'swagger_yaml': specification, 'base_path': base_path, 'arguments': arguments, 'swagger_ui': self.options.openapi_console_ui_available, 'swagger_path': self.options.openapi_console_ui_from_dir, 'swagger_url': self.options.openapi_console_ui_path, 'auth_all_paths': auth_all_paths}) if isinstance(specification, dict): self.specification = specification else: specification_path = pathlib.Path(specification) self.specification = self.load_spec_from_file(arguments, specification_path) self.specification = compatibility_layer(self.specification) logger.debug('Read specification', extra={'spec': self.specification}) # Avoid validator having ability to modify specification spec = copy.deepcopy(self.specification) validate_spec(spec) # https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#fixed-fields # If base_path is not on provided then we try to read it from the swagger.yaml or use / by default self._set_base_path(base_path) # A list of MIME types the APIs can produce. This is global to all APIs but can be overridden on specific # API calls. self.produces = self.specification.get('produces', list()) # type: List[str] # A list of MIME types the APIs can consume. This is global to all APIs but can be overridden on specific # API calls. self.consumes = self.specification.get('consumes', ['application/json']) # type: List[str] self.security = self.specification.get('security') self.security_definitions = self.specification.get('securityDefinitions', dict()) logger.debug('Security Definitions: %s', self.security_definitions) self.definitions = self.specification.get('definitions', {}) self.parameter_definitions = self.specification.get('parameters', {}) self.response_definitions = self.specification.get('responses', {}) self.resolver = resolver or Resolver() logger.debug('Validate Responses: %s', str(validate_responses)) self.validate_responses = validate_responses logger.debug('Strict Request Validation: %s', str(validate_responses)) self.strict_validation = strict_validation logger.debug('Pythonic params: %s', str(pythonic_params)) self.pythonic_params = pythonic_params if self.options.openapi_spec_available: self.add_swagger_json() if self.options.openapi_console_ui_available: self.add_swagger_ui() self.add_paths() if auth_all_paths: self.add_auth_on_not_found(self.security, self.security_definitions)
def test_definitons_not_present_success(minimal_swagger_dict): del minimal_swagger_dict['definitions'] validate_spec(minimal_swagger_dict)
def test_openapi_spec_validity(flask_app_client): raw_openapi_spec = flask_app_client.get('/api/v1/swagger.json').data deserialized_openapi_spec = json.loads(raw_openapi_spec.decode('utf-8')) assert isinstance(validator20.validate_spec(deserialized_openapi_spec), RefResolver)
def test_recursive_ref(minimal_swagger_dict, node_spec): minimal_swagger_dict['definitions']['Node'] = node_spec validate_spec(minimal_swagger_dict)
def test_success(petstore_contents): assert isinstance(validate_spec(json.loads(petstore_contents)), RefResolver)
def test_failure_on_unresolvable_ref_of_props_required_list(swagger_spec): swagger_spec['definitions']['Pet']['required'].append('bla') with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert ("Required list has properties not defined: ['bla']" in str(exc_info.value))
def test_failure_on_path_parameter_used_but_not_defined(swagger_spec): swagger_spec['paths']['/user/{username}']['get']['parameters'][0]['name'] = '_' with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert "Path Parameter used is not defined: username" in str(exc_info.value)
def test_failure_on_unresolvable_path_parameter(swagger_spec): swagger_spec['paths']['/pet/{foo}'] = swagger_spec['paths']['/pet'] with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert "Path Parameter used is not defined: foo" in str(exc_info.value)
def test_success(petstore_contents): validate_spec(json.loads(petstore_contents))
def test_failure_on_unresolvable_model_reference_from_model(swagger_spec): swagger_spec['definitions']['Pet']['properties']['category']['$ref'] = '_' with pytest.raises(SwaggerValidationError): validate_spec(swagger_spec)
def test_failure_on_unresolvable_path_parameter(swagger_spec): swagger_spec['paths']['/pet/{petId}']['get']['parameters'] = [] with pytest.raises(SwaggerValidationError) as exc_info: validate_spec(swagger_spec) assert "Path parameter 'petId' used is not documented on '/pet/{petId}'" in str(exc_info.value)
spec = """ definitions: MySchema: type: object additionalProperties: # patternProperties: # "^[0-9]$": type: object properties: name: {type: string} info: {title: WAF restful, version: 3.6.2.61} parameters: {} paths: /api/waf/v2/web_apps/{oid}: get: operationId: waf_restful.api.v2.web_apps.show_web_app parameters: - {in: path, name: oid, required: true, type: string} produces: [application/json] responses: '200': description: Show web app. schema: {$ref: '#/definitions/MySchema'} swagger: '2.0' tags: [] """ spec = yaml.safe_load(spec) validate_spec(spec)
def __init__(self, swagger_yaml_path, base_url=None, arguments=None, swagger_json=None, swagger_ui=None, swagger_path=None, swagger_url=None, validate_responses=False, resolver=resolver.Resolver(), auth_all_paths=False, debug=False): """ :type swagger_yaml_path: pathlib.Path :type base_url: str | None :type arguments: dict | None :type swagger_json: bool :type swagger_ui: bool :type swagger_path: string | None :type swagger_url: string | None :type auth_all_paths: bool :type debug: bool :param resolver: Callable that maps operationID to a function """ self.debug = debug self.swagger_yaml_path = pathlib.Path(swagger_yaml_path) logger.debug('Loading specification: %s', swagger_yaml_path, extra={'swagger_yaml': swagger_yaml_path, 'base_url': base_url, 'arguments': arguments, 'swagger_ui': swagger_ui, 'swagger_path': swagger_path, 'swagger_url': swagger_url, 'auth_all_paths': auth_all_paths}) arguments = arguments or {} with swagger_yaml_path.open() as swagger_yaml: swagger_template = swagger_yaml.read() swagger_string = jinja2.Template(swagger_template).render(**arguments) self.specification = yaml.load(swagger_string) # type: dict logger.debug('Read specification', extra=self.specification) self.specification = compatibility_layer(self.specification) # Avoid validator having ability to modify specification spec = copy.deepcopy(self.specification) validate_spec(spec) # https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#fixed-fields # If base_url is not on provided then we try to read it from the swagger.yaml or use / by default if base_url is None: self.base_url = self.specification.get('basePath', '') # type: dict else: self.base_url = base_url self.specification['basePath'] = base_url # A list of MIME types the APIs can produce. This is global to all APIs but can be overridden on specific # API calls. self.produces = self.specification.get('produces', list()) # type: List[str] self.security = self.specification.get('security') self.security_definitions = self.specification.get('securityDefinitions', dict()) logger.debug('Security Definitions: %s', self.security_definitions) self.definitions = self.specification.get('definitions', {}) self.parameter_definitions = self.specification.get('parameters', {}) self.response_definitions = self.specification.get('responses', {}) self.swagger_path = swagger_path or SWAGGER_UI_PATH self.swagger_url = swagger_url or SWAGGER_UI_URL self.resolver = resolver logger.debug('Validate Responses: %s', str(validate_responses)) self.validate_responses = validate_responses # Create blueprint and endpoints self.blueprint = self.create_blueprint() if swagger_json: self.add_swagger_json() if swagger_ui: self.add_swagger_ui() self.add_paths() if auth_all_paths: self.add_auth_on_not_found()
def test_failure_on_unresolvable_model_reference_from_resp(swagger_spec): resp = swagger_spec['paths']['/pet/findByStatus']['get']['responses'] resp['200']['schema']['items']['$ref'] = '#/definitions/bla' with pytest.raises(SwaggerValidationError): validate_spec(swagger_spec)
def build(self): if self.config['validate_swagger_spec']: validator20.validate_spec(self.spec_dict) self.api_url = build_api_serving_url(self.spec_dict, self.origin_url) self.resources = build_resources(self)
def test_empty_definitions_success(minimal_swagger_dict): validate_spec(minimal_swagger_dict)