Example #1
0
def test_add_param():
    @doc.add_param(Param.query('foo'))
    @api.Operation
    def a():
        pass

    assert len(a.parameters) == 1
    assert Param.query('foo') in a.parameters

    @api.Operation
    @doc.add_param(Param.query('foo'))
    def b():
        pass

    assert len(b.parameters) == 1
    assert Param.query('foo') in b.parameters

    @doc.add_param(Param.query('foo'))
    @api.Operation
    @doc.add_param(Param.form('bar'))
    def c():
        pass

    assert len(c.parameters) == 2
    assert Param.query('foo') in c.parameters
    assert Param.form('bar') in c.parameters
Example #2
0
    def test_repr(self):
        target = Param('foo', In.Query, Type.Integer, foo='bar')

        assert (
            repr(target) ==
            "Param('foo', <In.Query: 'query'>, <Type.Integer: 'integer:int32'>, None, {'foo': 'bar'})"
        )
Example #3
0
    def test_hash(self):
        a = Param('foo', In.Query)
        b = Param('foo', In.Query)
        assert hash(a) == hash(b)

        a = Param('foo', In.Query)
        b = Param('bar', In.Query)
        assert hash(a) != hash(b)

        a = Param('foo', In.Query)
        b = Param('foo', In.Path)
        assert hash(a) != hash(b)
Example #4
0
 def test_eq(self, other, expected):
     assert Param('foo', In.Path).__eq__(other) == expected
Example #5
0
    def test_str(self):
        target = Param('foo', In.Query)

        assert str(target) == 'Query param foo'
Example #6
0
class TestParam(object):
    @pytest.mark.parametrize(
        'method, args, expected',
        (
            # Path
            (Param.path, ('foo', ), {
                'name': 'foo',
                'in': 'path',
                'type': 'string',
                'required': True
            }),
            (Param.path, ('foo', Type.Boolean, 'eek'), {
                'name': 'foo',
                'in': 'path',
                'type': 'boolean',
                'description': 'eek',
                'required': True
            }),
            (Param.path, ('foo', Type.Integer, None, 1, 0, 2), {
                'name': 'foo',
                'in': 'path',
                'type': 'integer',
                'default': 1,
                'minimum': 0,
                'maximum': 2,
                'required': True
            }),
            (Param.path, ('foo', Type.Float, None, None, None, None,
                          ('a', 'b')), {
                              'name': 'foo',
                              'in': 'path',
                              'type': 'number',
                              'enum': ('a', 'b'),
                              'required': True
                          }),
            # Query
            (Param.query, ('foo', ), {
                'name': 'foo',
                'in': 'query',
                'type': 'string'
            }),
            (Param.query, ('foo', Type.Boolean), {
                'name': 'foo',
                'in': 'query',
                'type': 'boolean'
            }),
            (Param.query, ('foo', Type.Integer), {
                'name': 'foo',
                'in': 'query',
                'type': 'integer'
            }),
            (Param.query, ('foo', Type.Float, 'eek'), {
                'name': 'foo',
                'in': 'query',
                'type': 'number',
                'description': 'eek'
            }),
            (Param.query, ('foo', Type.String, None, False), {
                'name': 'foo',
                'in': 'query',
                'type': 'string',
                'required': False
            }),
            (Param.query, ('foo', Type.String, None, None, 1, 0, 2), {
                'name': 'foo',
                'in': 'query',
                'type': 'string',
                'default': 1,
                'minimum': 0,
                'maximum': 2
            }),
            (Param.query, ('foo', Type.String, None, None, None, None, None,
                           ('a', 'b')), {
                               'name': 'foo',
                               'in': 'query',
                               'type': 'string',
                               'enum': ('a', 'b')
                           }),
            # Header
            (Param.header, ('foo', ), {
                'name': 'foo',
                'in': 'header',
                'type': 'string'
            }),
            (Param.header, ('foo', Type.Boolean, 'eek'), {
                'name': 'foo',
                'in': 'header',
                'type': 'boolean',
                'description': 'eek'
            }),
            (Param.header, ('foo', Type.Integer, None, 'eek'), {
                'name': 'foo',
                'in': 'header',
                'type': 'integer',
                'default': 'eek'
            }),
            (Param.header, ('foo', Type.Integer, None, None, True), {
                'name': 'foo',
                'in': 'header',
                'type': 'integer',
                'required': True
            }),
            # Body
            (Param.body, (), {
                'name': 'body',
                'in': 'body',
                'required': True
            }),
            (Param.body, ('foo', ), {
                'name': 'body',
                'in': 'body',
                'description': 'foo',
                'required': True
            }),
            (Param.body, ('foo', 'eek'), {
                'name': 'body',
                'in': 'body',
                'description': 'foo',
                'default': 'eek',
                'required': True
            }),
            (Param.body, (None, None, User), {
                'name': 'body',
                'in': 'body',
                'required': True,
                'schema': {
                    '$ref': '#/definitions/tests.User'
                }
            }),
            # Form
            (Param.form, ('foo', ), {
                'name': 'foo',
                'in': 'formData',
                'type': 'string'
            }),
            (Param.form, ('foo', Type.Boolean), {
                'name': 'foo',
                'in': 'formData',
                'type': 'boolean'
            }),
            (Param.form, ('foo', Type.Integer), {
                'name': 'foo',
                'in': 'formData',
                'type': 'integer'
            }),
            (Param.form, ('foo', Type.Float, 'eek'), {
                'name': 'foo',
                'in': 'formData',
                'type': 'number',
                'description': 'eek'
            }),
            (Param.form, ('foo', Type.String, None, False), {
                'name': 'foo',
                'in': 'formData',
                'type': 'string',
                'required': False
            }),
            (Param.form, ('foo', Type.String, None, None, 1, 0, 2), {
                'name': 'foo',
                'in': 'formData',
                'type': 'string',
                'default': 1,
                'minimum': 0,
                'maximum': 2
            }),
            (Param.form, ('foo', Type.String, None, None, None, None, None,
                          ('a', 'b')), {
                              'name': 'foo',
                              'in': 'formData',
                              'type': 'string',
                              'enum': ('a', 'b')
                          }),
        ))
    def test_constructors(self, method, args, expected):
        target = method(*args)
        actual = target.to_swagger()
        assert actual == expected

    @pytest.mark.parametrize('method, args, expected', (
        (Param.path, ('foo', Type.String, None, None, 2, 1), ValueError),
        (Param.query,
         ('foo', Type.String, None, None, None, 2, 1), ValueError),
        (Param.form, ('foo', Type.String, None, None, None, 2, 1), ValueError),
    ))
    def test_constructors__errors(self, method, args, expected):
        with pytest.raises(expected):
            method(*args)

    def test_hash(self):
        a = Param('foo', In.Query)
        b = Param('foo', In.Query)
        assert hash(a) == hash(b)

        a = Param('foo', In.Query)
        b = Param('bar', In.Query)
        assert hash(a) != hash(b)

        a = Param('foo', In.Query)
        b = Param('foo', In.Path)
        assert hash(a) != hash(b)

    def test_str(self):
        target = Param('foo', In.Query)

        assert str(target) == 'Query param foo'

    def test_repr(self):
        target = Param('foo', In.Query, Type.Integer, foo='bar')

        assert (
            repr(target) ==
            "Param('foo', <In.Query: 'query'>, <Type.Integer: 'integer:int32'>, None, {'foo': 'bar'})"
        )

    @pytest.mark.parametrize('other, expected', (
        (Param('foo', In.Path), True),
        (Param('bar', In.Path), False),
        (Param('foo', In.Body), False),
        (123, NotImplemented),
    ))
    def test_eq(self, other, expected):
        assert Param('foo', In.Path).__eq__(other) == expected
Example #7
0
    def test_documentation_applied(self):
        @decorators.ResourceOperation(resource=User)
        def my_func(request, user):
            pass

        assert Param.body() in my_func.parameters
Example #8
0
class TestSwaggerSpec(object):
    @pytest.mark.parametrize(
        'options, title, enabled, enable_ui, host, schemes', (
            ({
                'title': 'Test'
            }, 'Test', True, False, None, set()),
            ({
                'title': 'Test',
                'enabled': False
            }, 'Test', False, False, None, set()),
            ({
                'title': 'Test',
                'enable_ui': True
            }, 'Test', True, True, None, set()),
            ({
                'title': 'Test',
                'enabled': False,
                'enable_ui': True
            }, 'Test', False, False, None, set()),
            ({
                'title': 'Test',
                'host': 'localhost'
            }, 'Test', True, False, 'localhost', set()),
            ({
                'title': 'Test',
                'schemes': ('http', 'https')
            }, 'Test', True, False, None, {'http', 'https'}),
            ({
                'title': 'Test',
                'schemes': 'http'
            }, 'Test', True, False, None, {'http'}),
        ))
    def test_configure(self, options, title, enabled, enable_ui, host,
                       schemes):
        target = swagger.SwaggerSpec(**options)

        assert target.title == title
        assert target.enabled == enabled
        assert target.enable_ui == enable_ui
        assert target.host == host
        assert target.schemes == schemes

    def test_base_path(self):
        target = swagger.SwaggerSpec(title="")

        ApiInterfaceBase(
            ApiContainer(ApiContainer(ApiContainer(target), name='b'),
                         name='a'))

        assert UrlPath.parse("/api/a/b") == target.base_path
        assert UrlPath.parse("/api/a/b/swagger") == target.swagger_path

    def test_cenancestor(self):
        target = swagger.SwaggerSpec(title="")

        expected = ApiInterfaceBase(
            ApiContainer(ApiContainer(ApiContainer(), target, name='b'),
                         name='a'))

        assert target.cenancestor is expected

    def test_generate_parameters(self):
        actual = swagger.SwaggerSpec.generate_parameters(
            UrlPath.parse('/api/a/{b}/c/{d:String}'))
        assert actual == [{
            'name': 'b',
            'in': 'path',
            'type': 'integer',
            'required': True,
        }, {
            'name': 'd',
            'in': 'path',
            'type': 'string',
            'required': True,
        }]

    @pytest.mark.parametrize('node, expected', (
        (Param.path('a'), '{a}'),
        (Param.path('a', Type.String), '{a}'),
    ))
    def test_swagger_node_formatter(self, node, expected):
        actual = swagger.SwaggerSpec.swagger_node_formatter(node)
        assert actual == expected

    def test_parse_operations(self):
        @Operation(path="a/{b:String}", methods=Method.POST, resource=User)
        def my_func(request, b):
            pass

        target = swagger.SwaggerSpec("Example", schemes='http')

        ApiInterfaceBase(ApiVersion(
            target,
            my_func,
        ), )

        actual = target.parse_operations()
        assert len(actual) == 2
        actual_paths, actual_resources = actual

        # Paths
        assert len(actual_paths) == 1
        assert "/a/{b}" in actual_paths
        actual_path = actual_paths['/a/{b}']
        assert actual_path['parameters'] == [{
            'in': 'path',
            'type': 'string',
            'name': 'b',
            'required': True
        }]

        assert 'post' in actual_path
        actual_operation = actual_path['post']
        assert actual_operation == my_func.to_swagger()

        # Resources
        assert len(actual_resources) == 3
        assert 'tests.User' in actual_resources

    def test_get_swagger(self, monkeypatch):
        monkeypatch.setattr(
            swagger,
            'CODECS',
            {
                'application/json': None  # Only the Keys are used.
            })

        request = MockRequest()
        target = swagger.SwaggerSpec("Example", schemes='http')

        base = ApiInterfaceBase(ApiVersion(target, ), )

        base.registered_codecs.clear()
        base.registered_codecs[
            'application/yaml'] = None  # Only the keys are used.

        actual = target.get_swagger(request)
        expected = {
            'swagger': '2.0',
            'info': {
                'title': 'Example',
                'version': '1'
            },
            'host': '127.0.0.1',
            'schemes': ['http'],
            'basePath': '/api/v1',
            'consumes': ['application/yaml'],
            'produces': ['application/yaml'],
            'paths': {},
            'definitions': {
                'Error': {
                    'type': 'object',
                    'properties': {
                        'code': {
                            'description':
                            'Custom application specific error code that references into the application.',
                            'type': 'integer',
                            'format': 'int64',
                        },
                        'developer_message': {
                            'description':
                            'An error message suitable for the application developer',
                            'type': 'string'
                        },
                        'message': {
                            'description':
                            'A message that can be displayed to an end user',
                            'type': 'string'
                        },
                        'meta': {
                            'description':
                            'Additional meta information that can help solve errors.',
                        },
                        'status': {
                            'description': 'HTTP status code of the response.',
                            'type': 'integer',
                            'format': 'int64',
                        }
                    },
                },
                'Listing': {
                    'type': 'object',
                    'properties': {
                        'limit': {
                            'description':
                            'Limit or page size of the result set',
                            'type': 'integer',
                            'format': 'int64',
                        },
                        'offset': {
                            'description': 'Offset within the result set.',
                            'type': 'integer',
                            'format': 'int64',
                        },
                        'results': {
                            'description': 'List of resources.',
                        },
                        'total_count': {
                            'description':
                            'The total number of items in the result set.',
                            'type': 'integer',
                            'format': 'int64',
                        }
                    },
                }
            }
        }
        assert actual == expected

    def test_load_static(self):
        target = swagger.SwaggerSpec("", enable_ui=True)

        actual = target.load_static('ui.html')
        if _compat.PY2:
            assert actual.startswith('<!DOCTYPE html>')
        else:
            assert actual.startswith(b'<!DOCTYPE html>')

    def test_load_static__not_found_if_not_found(self):
        target = swagger.SwaggerSpec("")

        with pytest.raises(HttpError) as ex:
            target.load_static('eek.html')

        assert ex.value.status == HTTPStatus.NOT_FOUND

    def test_load_static__not_found_if_path_breakout_attempted(self):
        target = swagger.SwaggerSpec("")

        with pytest.raises(HttpError) as ex:
            target.load_static('/etc/passwd')

        assert ex.value.status == HTTPStatus.NOT_FOUND

    def test_get_ui(self):
        target = swagger.SwaggerSpec("")

        actual = target.get_ui(None)

        assert actual.body.startswith("<!DOCTYPE html>")
        assert actual.status == HTTPStatus.OK
        assert actual['Content-Type'] == 'text/html'

    @pytest.mark.parametrize('file_name, content_type', (
        ("ui.css", 'text/css'),
        ("bundle.js", 'application/javascript'),
    ))
    def test_get_static(self, file_name, content_type):
        target = swagger.SwaggerSpec("")

        actual = target.get_static(None, file_name)

        # Can't check the body as it is pre-gzipped
        assert actual.status == HTTPStatus.OK
        assert actual['Content-Type'] == content_type
        assert actual['Content-Encoding'] == 'gzip'

    def test_get_static__not_found_if_unknown_content_type(self):
        target = swagger.SwaggerSpec("")

        with pytest.raises(HttpError) as ex:
            target.get_static(None, 'ui.html')

        assert ex.value.status == HTTPStatus.NOT_FOUND