def test_consumes_validation_for_valid_mimetype_from_operation_definition():
    """
    Test that when `consumes` is defined in an operation definition, that the
    local value is used in place of any global `consumes` definition.
    """
    request = RequestFactory(content_type='application/json')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['application/xml'],
        paths={
            '/get': {'get': {
                'responses': {200: {'description': 'Success'}},
                'consumes': ['application/json'],
            }},
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    validate_operation(response, validators)
def test_consumes_validation_for_invalid_mimetype_from_operation_definition():
    """
    Test the situation when the operation definition has overridden the global
    allowed mimetypes, that that the local value is used for validation.
    """
    from django.core.exceptions import ValidationError
    request = RequestFactory(content_type='application/xml')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['application/xml'],
        paths={
            '/get': {'get': {
                'responses': {200: {'description': 'Success'}},
                'consumes': ['application/json'],
            }},
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    with pytest.raises(ValidationError):
        validate_operation(response, validators, inner=True)
Exemple #3
0
def test_consumes_validation_invalid_mimetype_from_global_definition():
    """
    Test that a request content_type that is in the global api consumes
    definitions is valid.
    """
    request = RequestFactory(content_type='application/json')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['text/xml', 'application/xml'],
        paths={
            '/get': {
                'get': {
                    'responses': {
                        '200': {
                            'description': 'Success'
                        }
                    }
                }
            },
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    with pytest.raises(ValidationError):
        validate_operation(response.request, validators)
def test_consumes_validation_invalid_mimetype_from_global_definition():
    """
    Test that a request content_type that is in the global api consumes
    definitions is valid.
    """
    from django.core.exceptions import ValidationError

    request = RequestFactory(content_type='application/json')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['text/xml', 'application/xml'],
        paths={
            '/get': {'get': {'responses': {200: {'description': 'Success'}}}},
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    with pytest.raises(ValidationError):
        validate_operation(response, validators, inner=True)
Exemple #5
0
def test_consumes_validation_for_valid_mimetype_from_operation_definition():
    """
    Test that when `consumes` is defined in an operation definition, that the
    local value is used in place of any global `consumes` definition.
    """
    request = RequestFactory(content_type='application/json')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['application/xml'],
        paths={
            '/get': {
                'get': {
                    'responses': {
                        '200': {
                            'description': 'Success'
                        }
                    },
                    'consumes': ['application/json'],
                }
            },
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    validate_operation(response.request, validators)
Exemple #6
0
def test_consumes_validation_for_invalid_mimetype_from_operation_definition():
    """
    Test the situation when the operation definition has overridden the global
    allowed mimetypes, that that the local value is used for validation.
    """
    request = RequestFactory(content_type='application/xml')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['application/xml'],
        paths={
            '/get': {
                'get': {
                    'responses': {
                        '200': {
                            'description': 'Success'
                        }
                    },
                    'consumes': ['application/json'],
                }
            },
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    with pytest.raises(ValidationError):
        validate_operation(response.request, validators)
Exemple #7
0
def validate_request(request, schema):
    """
    Request validation does the following steps.

       1. validate that the path matches one of the defined paths in the schema.
       2. validate that the request method conforms to a supported methods for the given path.
       3. validate that the request parameters conform to the parameter
          definitions for the operation definition.
    """
    with ErrorCollection() as errors:
        # 1
        try:
            api_path = validate_path_to_api_path(
                path=request.path,
                context=schema,
                **schema
            )
        except ValidationError as err:
            errors['path'].add_error(err.detail)
            return  # this causes an exception to be raised since errors is no longer falsy.

        path_definition = schema['paths'][api_path] or {}

        if not path_definition:
            # TODO: is it valid to not have a definition for a path?
            return

        # 2
        try:
            operation_definition = validate_request_method_to_operation(
                request_method=request.method,
                path_definition=path_definition,
            )
        except ValidationError as err:
            errors['method'].add_error(err.detail)
            return

        if operation_definition is None:
            # TODO: is this compliant with swagger, can path operations have a null
            # definition?
            return

        # 3
        operation_validators = construct_operation_validators(
            api_path=api_path,
            path_definition=path_definition,
            operation_definition=operation_definition,
            context=schema,
        )
        try:
            validate_operation(request, operation_validators, context=schema)
        except ValidationError as err:
            errors['method'].add_error(err.detail)
Exemple #8
0
def validate_request(request, schema):
    """
    Request validation does the following steps.

       1. validate that the path matches one of the defined paths in the schema.
       2. validate that the request method conforms to a supported methods for the given path.
       3. validate that the request parameters conform to the parameter
          definitions for the operation definition.
    """
    with ErrorCollection() as errors:
        # 1
        try:
            api_path = validate_path_to_api_path(path=request.path,
                                                 context=schema,
                                                 **schema)
        except ValidationError as err:
            errors['path'].add_error(err.detail)
            return  # this causes an exception to be raised since errors is no longer falsy.

        path_definition = schema['paths'][api_path] or {}

        if not path_definition:
            # TODO: is it valid to not have a definition for a path?
            return

        # 2
        try:
            operation_definition = validate_request_method_to_operation(
                request_method=request.method,
                path_definition=path_definition,
            )
        except ValidationError as err:
            errors['method'].add_error(err.detail)
            return

        if operation_definition is None:
            # TODO: is this compliant with swagger, can path operations have a null
            # definition?
            return

        # 3
        operation_validators = construct_operation_validators(
            api_path=api_path,
            path_definition=path_definition,
            operation_definition=operation_definition,
            context=schema,
        )
        try:
            validate_operation(request, operation_validators, context=schema)
        except ValidationError as err:
            errors['method'].add_error(err.detail)
def test_produces_validation_valid_mimetype_from_global_definition():
    """
    Test that a response content_type that is in the global api produces
    definitions is valid.
    """
    response = ResponseFactory(content_type='application/json')

    schema = SchemaFactory(
        produces=['application/json'],
        paths={
            '/get': {'get': {'responses': {200: {'description': 'Success'}}}},
        },
    )

    validators = construct_operation_validators(
        '/get', schema['paths']['/get'], 'get', schema,
    )
    validate_operation(response, validators)
def test_consumes_validation_valid_mimetype_from_global_definition():
    """
    Test that a request content_type that is in the global api consumes
    definitions is valid.
    """
    request = RequestFactory(content_type="application/json")
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=["application/json"], paths={"/get": {"get": {"responses": {"200": {"description": "Success"}}}}}
    )

    validators = construct_operation_validators(
        api_path="/get",
        path_definition=schema["paths"]["/get"],
        operation_definition=schema["paths"]["/get"]["get"],
        context=schema,
    )
    validate_operation(response.request, validators)
def test_consumes_validation_for_valid_mimetype_from_operation_definition():
    """
    Test that when `consumes` is defined in an operation definition, that the
    local value is used in place of any global `consumes` definition.
    """
    request = RequestFactory(content_type="application/json")
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=["application/xml"],
        paths={"/get": {"get": {"responses": {"200": {"description": "Success"}}, "consumes": ["application/json"]}}},
    )

    validators = construct_operation_validators(
        api_path="/get",
        path_definition=schema["paths"]["/get"],
        operation_definition=schema["paths"]["/get"]["get"],
        context=schema,
    )
    validate_operation(response.request, validators)
def test_consumes_validation_for_invalid_mimetype_from_operation_definition():
    """
    Test the situation when the operation definition has overridden the global
    allowed mimetypes, that that the local value is used for validation.
    """
    request = RequestFactory(content_type="application/xml")
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=["application/xml"],
        paths={"/get": {"get": {"responses": {"200": {"description": "Success"}}, "consumes": ["application/json"]}}},
    )

    validators = construct_operation_validators(
        api_path="/get",
        path_definition=schema["paths"]["/get"],
        operation_definition=schema["paths"]["/get"]["get"],
        context=schema,
    )
    with pytest.raises(ValidationError):
        validate_operation(response.request, validators)
def test_consumes_validation_valid_mimetype_from_global_definition():
    """
    Test that a request content_type that is in the global api consumes
    definitions is valid.
    """
    request = RequestFactory(content_type='application/json')
    response = ResponseFactory(request=request)

    schema = SchemaFactory(
        consumes=['application/json'],
        paths={
            '/get': {'get': {'responses': {200: {'description': 'Success'}}}},
        },
    )

    validators = construct_operation_validators(
        api_path='/get',
        path_definition=schema['paths']['/get'],
        operation_definition=schema['paths']['/get']['get'],
        context=schema,
    )
    validate_operation(response, validators)
Exemple #14
0
def validate_response(response, paths, base_path, context, inner=False):
    """
    Response validation involves the following steps.

       1. validate that the path matches one of the defined paths in the schema.
       2. validate that the request method conforms to a supported methods for the given path.
       3. validate that the request parameters conform to the parameter
          definitions for the operation definition.
       4. validate that the response status_code is in the allowed responses for
          the request method.
       5. validate that the response content validates against any provided
          schemas for the responses.
       6. headers, content-types, etc..., ???
    """
    with ErrorCollection(inner=inner) as errors:
        # 1
        try:
            api_path, path_definition = validate_request_to_path(
                request=response.request,
                paths=paths,
                base_path=base_path,
                context=context,
            )
        except ValidationError as err:
            errors['request'].extend(list(err.messages))
            return  # this causes an exception to be raised since errors is no longer falsy.

        if not path_definition:
            # TODO: is it valid to not have a definition for a path?
            return

        # 2
        try:
            operation = validate_request_method_to_operation(
                request=response.request,
                path_definition=path_definition,
            )
        except ValidationError as err:
            errors['request'].append(err.message)
            return

        if operation is None:
            # TODO: is this compliant with swagger, can path operations have a null
            # definition?
            return

        # 3
        operation_validators = construct_operation_validators(
            api_path=api_path,
            path_definition=path_definition,
            operation=response.request.method,
            context=context,
        )
        try:
            validate_operation(response, operation_validators, inner=True)
        except ValidationError as err:
            errors['request'].append(err.messages)

        # 4
        try:
            response_definition = validate_status_code_to_response_definition(
                response=response,
                operation=operation,
            )
        except ValidationError as err:
            errors['response'].append(err.message)
        else:
            # 5
            response_body_validator = generate_response_body_validator(
                response_definition.get('schema', {}),
                context=context,
                inner=inner,
            )
            try:
                response_body_validator(response)
            except ValidationError as err:
                errors['response_body'].extend(err.messages)
def test_operation_parameter_validation_uses_correct_parameter_definitions():
    """
    Validation of a request's parameters involves merging the parameter
    definitions from the path definition as well as the operation definition.
    Ensure that this merging is happening and with the correct precendence to
    override path level parameters with any defined at the operation level.

    This test also serves as a *smoke* test to see that parameter validation is
    working as expected.
    """
    schema = SchemaFactory(
        produces=['application/json'],
        paths={
            '/get/{username}/posts/{id}/': {
                'parameters': [
                    {
                        'name': 'username',
                        'in': PATH,
                        'description': 'username',
                        'required': True,
                        'type': STRING,
                    },
                    {
                        'name': 'id',
                        'in': PATH,
                        'description': 'id',
                        'required': True,
                        'type': INTEGER,
                    },
                ],
                'get': {
                    'responses': {200: {'description': 'Success'}},
                    'parameters': [
                        {
                            'name': 'id',
                            'in': PATH,
                            'description': 'id',
                            'required': True,
                            'type': STRING,
                            'format': 'uuid',
                        },
                        {
                            'name': 'page',
                            'in': QUERY,
                            'type': INTEGER,
                        },
                    ]
                },
            },
        },
    )


    request = RequestFactory(url='http://www.example.com/get/fernando/posts/45/')

    api_path = '/get/{username}/posts/{id}/'
    path_definition = schema['paths']['/get/{username}/posts/{id}/']
    operation_definition = schema['paths']['/get/{username}/posts/{id}/']['get']

    validators = construct_operation_validators(
        api_path=api_path,
        path_definition=path_definition,
        operation_definition=operation_definition,
        context=schema,
    )

    with pytest.raises(ValidationError) as err:
        validate_operation(request, validators)

    assert_message_in_errors(
        MESSAGES['format']['invalid_uuid'],
        err.value.detail,
        'parameters.path.id.format',
    )