예제 #1
0
    def test_rebar_can_be_url_prefixed(self):
        app = Flask(__name__)
        app.testing = True

        rebar = Rebar()
        registry_v1 = rebar.create_handler_registry(prefix='v1')
        registry_v2 = rebar.create_handler_registry(
            prefix='/v2/')  # Slashes shouldn't matter

        # We use the same endpoint to show that the swagger operationId gets set correctly
        # and the Flask endpoint gets prefixed
        register_endpoint(registry=registry_v1, endpoint='get_foo')
        register_endpoint(registry=registry_v2, endpoint='get_foo')

        rebar.init_app(app)

        for prefix in ('v1', 'v2'):
            resp = app.test_client().get(
                prefix_url(prefix=prefix, url='/swagger/ui/'))
            self.assertEqual(resp.status_code, 200)

            swagger = get_swagger(test_client=app.test_client(), prefix=prefix)
            validate_swagger(swagger)

            self.assertEqual(
                swagger['paths'][prefix_url(
                    prefix=prefix,
                    url='/foos/{foo_uid}')]['get']['operationId'], 'get_foo')
            resp = app.test_client().get(
                prefix_url(prefix=prefix, url='/foos/1'))
            self.assertEqual(resp.status_code, 200)
예제 #2
0
    def test_rebar_can_be_url_prefixed(self):
        app = Flask(__name__)
        app.testing = True

        rebar = Rebar()
        registry_v1 = rebar.create_handler_registry(prefix="v1")
        registry_v2 = rebar.create_handler_registry(
            prefix="/v2/")  # Slashes shouldn't matter

        # We use the same endpoint to show that the swagger operationId gets set correctly
        # and the Flask endpoint gets prefixed
        register_endpoint(registry=registry_v1, endpoint="get_foo")
        register_endpoint(registry=registry_v2, endpoint="get_foo")

        rebar.init_app(app)

        for prefix in ("v1", "v2"):
            resp = app.test_client().get(
                prefix_url(prefix=prefix, url="/swagger/ui/"))
            self.assertEqual(resp.status_code, 200)

            swagger = get_swagger(test_client=app.test_client(), prefix=prefix)
            validate_swagger(swagger)

            self.assertEqual(
                swagger["paths"][prefix_url(
                    prefix=prefix,
                    url="/foos/{foo_uid}")]["get"]["operationId"],
                "get_foo",
            )
            resp = app.test_client().get(
                prefix_url(prefix=prefix, url="/foos/1"))
            self.assertEqual(resp.status_code, 200)
예제 #3
0
    def test_swagger_ui_endpoint_is_automatically_created(self):
        rebar = Rebar()
        rebar.create_handler_registry()
        app = create_rebar_app(rebar)

        resp = app.test_client().get("/swagger/ui/")
        self.assertEqual(resp.status_code, 200)
예제 #4
0
    def test_swagger_ui_without_trailing_slash(self):
        rebar = Rebar()
        rebar.create_handler_registry()
        app = create_rebar_app(rebar)

        resp = app.test_client().get("/swagger/ui")
        self.assertEqual(resp.status_code, 200)
예제 #5
0
    def test_swagger_endpoints_can_be_omitted(self):
        rebar = Rebar()
        rebar.create_handler_registry(spec_path=None, swagger_ui_path=None)
        app = create_rebar_app(rebar)

        resp = app.test_client().get("/swagger")
        self.assertEqual(resp.status_code, 404)

        resp = app.test_client().get("/swagger/ui")
        self.assertEqual(resp.status_code, 404)
예제 #6
0
    def test_swagger_endpoint_is_automatically_created(self):
        rebar = Rebar()
        rebar.create_handler_registry()
        app = create_rebar_app(rebar)

        resp = app.test_client().get('/swagger')

        self.assertEqual(resp.status_code, 200)

        validate_swagger(get_json_from_resp(resp))
예제 #7
0
    def test_swagger_can_be_set_to_v3(self):
        rebar = Rebar()
        rebar.create_handler_registry(swagger_generator=SwaggerV3Generator())
        app = create_rebar_app(rebar)

        resp = app.test_client().get("/swagger")
        self.assertEqual(resp.status_code, 200)
        validate_swagger(resp.json, SWAGGER_V3_JSONSCHEMA)

        resp = app.test_client().get("/swagger/ui/")
        self.assertEqual(resp.status_code, 200)
예제 #8
0
    def test_default_headers(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        registry.set_default_headers_schema(HeadersSchema())

        @registry.handles(rule='/me', method='GET', marshal_schema=MeSchema())
        def get_me():
            return {'user_name': rebar.validated_headers['name']}

        @registry.handles(
            rule='/myself',
            method='GET',
            marshal_schema=MeSchema(),

            # Let's make sure this can be overridden
            headers_schema=None)
        def get_myself():
            return DEFAULT_RESPONSE

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path='/me', headers={'x-name': 'hello'})
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), {'user_name': 'hello'})

        resp = app.test_client().get(path='/me', )
        self.assertEqual(resp.status_code, 400)

        resp = app.test_client().get(path='/myself', )
        self.assertEqual(resp.status_code, 200)

        swagger = get_swagger(test_client=app.test_client())
        self.assertEqual(
            swagger['paths']['/me']['get']['parameters'][0]['name'], 'x-name')
        self.assertNotIn('parameters', swagger['paths']['/myself']['get'])
예제 #9
0
    def test_validate_headers(self, headers_cls, use_model):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        register_default_authenticator(registry)

        @registry.handles(
            rule="/me",
            method="GET",
            response_body_schema={200: MeSchema()},
            headers_schema=headers_cls,
        )
        def get_me():
            name = (rebar.validated_headers.name
                    if use_model else rebar.validated_headers["name"])
            return {"user_name": name}

        app = create_rebar_app(rebar)

        headers = auth_headers()
        headers["x-name"] = "hello"

        resp = app.test_client().get(path="/me", headers=headers)
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, {"user_name": "hello"})

        resp = app.test_client().get(
            path="/me",
            headers=auth_headers()  # Missing the x-name header!
        )
        self.assertEqual(resp.status_code, 400)
예제 #10
0
    def test_validate_query_parameters(self, list_of_foo_cls):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(
            rule="/foos",
            method="GET",
            response_body_schema={200: list_of_foo_cls()},
            query_string_schema=FooListSchema(),
        )
        def list_foos():
            return {
                "data": [{
                    "name": rebar.validated_args["name"],
                    "uid": "1"
                }]
            }

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path="/foos?name=jill")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, {"data": [{"uid": "1", "name": "jill"}]})

        resp = app.test_client().get(
            path="/foos?foo=bar")  # missing required parameter
        self.assertEqual(resp.status_code, 400)
예제 #11
0
    def test_validate_body_parameters(self, foo_cls, foo_update_cls,
                                      use_model):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(
            rule="/foos/<foo_uid>",
            method="PATCH",
            response_body_schema={200: foo_cls()},
            request_body_schema=foo_update_cls(),
        )
        def update_foo(foo_uid):
            if use_model:
                # Here we can also verify that in handler we get our expected FooModel type object
                self.assertIsInstance(rebar.validated_body, foo_update_cls)
                return foo_cls(name=rebar.validated_body.name, uid=foo_uid)
            else:
                return {"uid": foo_uid, "name": rebar.validated_body["name"]}

        app = create_rebar_app(rebar)

        resp = app.test_client().patch(
            path="/foos/1",
            data=json.dumps({"name": "jill"}),
            headers={"Content-Type": "application/json"},
        )
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, {"uid": "1", "name": "jill"})

        resp = app.test_client().patch(
            path="/foos/1",
            data=json.dumps({"name": 123}),  # Name should be string, not int
            headers={"Content-Type": "application/json"},
        )
        self.assertEqual(resp.status_code, 400)
예제 #12
0
    def test_clone_rebar(self):
        rebar = Rebar()
        app = Flask(__name__)
        app.testing = True

        registry = rebar.create_handler_registry()

        register_default_authenticator(registry)
        register_endpoint(registry)

        cloned = registry.clone()
        cloned.prefix = 'v1'
        rebar.add_handler_registry(registry=cloned)

        rebar.init_app(app)

        resp = app.test_client().get('/swagger/ui/')
        self.assertEqual(resp.status_code, 200)

        resp = app.test_client().get(path='/foos/1', headers=auth_headers())
        self.assertEqual(resp.status_code, 200)

        resp = app.test_client().get('/v1/swagger/ui/')
        self.assertEqual(resp.status_code, 200)

        resp = app.test_client().get(path='/v1/foos/1', headers=auth_headers())
        self.assertEqual(resp.status_code, 200)
예제 #13
0
    def test_default_headers(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        registry.set_default_headers_schema(HeadersSchema())

        @registry.handles(rule="/me", method="GET", marshal_schema=MeSchema())
        def get_me():
            return {"user_name": rebar.validated_headers["name"]}

        @registry.handles(
            rule="/myself",
            method="GET",
            marshal_schema=MeSchema(),
            # Let's make sure this can be overridden
            headers_schema=None,
        )
        def get_myself():
            return DEFAULT_RESPONSE

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path="/me", headers={"x-name": "hello"})
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), {"user_name": "hello"})

        resp = app.test_client().get(path="/me")
        self.assertEqual(resp.status_code, 400)

        resp = app.test_client().get(path="/myself")
        self.assertEqual(resp.status_code, 200)

        swagger = get_swagger(test_client=app.test_client())
        self.assertEqual(
            swagger["paths"]["/me"]["get"]["parameters"][0]["name"], "x-name")
        self.assertNotIn("parameters", swagger["paths"]["/myself"]["get"])
예제 #14
0
    def test_validate_headers(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        register_default_authenticator(registry)

        @registry.handles(
            rule="/me",
            method="GET",
            marshal_schema={200: MeSchema()},
            headers_schema=HeadersSchema(),
        )
        def get_me():
            return {"user_name": rebar.validated_headers["name"]}

        app = create_rebar_app(rebar)

        headers = auth_headers()
        headers["x-name"] = "hello"

        resp = app.test_client().get(path="/me", headers=headers)
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), {"user_name": "hello"})

        resp = app.test_client().get(
            path="/me",
            headers=auth_headers()  # Missing the x-name header!
        )
        self.assertEqual(resp.status_code, 400)
예제 #15
0
    def test_validate_body_parameters(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(
            rule="/foos/<foo_uid>",
            method="PATCH",
            marshal_schema={200: FooSchema()},
            request_body_schema=FooUpdateSchema(),
        )
        def update_foo(foo_uid):
            return {"uid": foo_uid, "name": rebar.validated_body["name"]}

        app = create_rebar_app(rebar)

        resp = app.test_client().patch(
            path="/foos/1",
            data=json.dumps({"name": "jill"}),
            headers={"Content-Type": "application/json"},
        )
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), {
            "uid": "1",
            "name": "jill"
        })

        resp = app.test_client().patch(
            path="/foos/1",
            data=json.dumps({"name": 123}),  # Name should be string, not int
            headers={"Content-Type": "application/json"},
        )
        self.assertEqual(resp.status_code, 400)
예제 #16
0
    def test_register_multiple_methods(self, foo_definition):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        common_kwargs = {
            "rule": "/foos/<foo_uid>",
            "response_body_schema": {
                200: foo_definition
            },
        }

        @registry.handles(method="GET", endpoint="get_foo", **common_kwargs)
        @registry.handles(method="PATCH",
                          endpoint="update_foo",
                          **common_kwargs)
        def handler_func(foo_uid):
            return DEFAULT_RESPONSE

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path="/foos/1")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, DEFAULT_RESPONSE)

        resp = app.test_client().patch(path="/foos/1")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, DEFAULT_RESPONSE)

        resp = app.test_client().post(path="/foos/1")
        self.assertEqual(resp.status_code, 405)

        swagger = get_swagger(test_client=app.test_client())
        self.assertIn("get", swagger["paths"]["/foos/{foo_uid}"])
        self.assertIn("patch", swagger["paths"]["/foos/{foo_uid}"])
예제 #17
0
    def test_register_multiple_methods(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        common_kwargs = {
            'rule': '/foos/<foo_uid>',
            'marshal_schema': {
                200: FooSchema()
            },
        }

        @registry.handles(method='GET', endpoint='get_foo', **common_kwargs)
        @registry.handles(method='PATCH',
                          endpoint='update_foo',
                          **common_kwargs)
        def handler_func(foo_uid):
            return DEFAULT_RESPONSE

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path='/foos/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), DEFAULT_RESPONSE)

        resp = app.test_client().patch(path='/foos/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), DEFAULT_RESPONSE)

        resp = app.test_client().post(path='/foos/1')
        self.assertEqual(resp.status_code, 405)

        swagger = get_swagger(test_client=app.test_client())
        self.assertIn('get', swagger['paths']['/foos/{foo_uid}'])
        self.assertIn('patch', swagger['paths']['/foos/{foo_uid}'])
예제 #18
0
    def test_validate_query_parameters(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(
            rule='/foos',
            method='GET',
            marshal_schema={200: ListOfFooSchema()},
            query_string_schema=FooListSchema(),
        )
        def list_foos():
            return {
                'data': [{
                    'name': rebar.validated_args['name'],
                    'uid': '1'
                }]
            }

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path='/foos?name=jill')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp),
                         {'data': [{
                             'uid': '1',
                             'name': 'jill'
                         }]})

        resp = app.test_client().get(
            path='/foos?foo=bar'  # missing required parameter
        )
        self.assertEqual(resp.status_code, 400)
예제 #19
0
    def test_register_multiple_paths(self, foo_definition):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        common_kwargs = {
            "method": "GET",
            "response_body_schema": {
                200: foo_definition
            }
        }

        @registry.handles(rule="/bars/<foo_uid>",
                          endpoint="bar",
                          **common_kwargs)
        @registry.handles(rule="/foos/<foo_uid>",
                          endpoint="foo",
                          **common_kwargs)
        def handler_func(foo_uid):
            return DEFAULT_RESPONSE

        app = create_rebar_app(rebar)

        resp = app.test_client().get(path="/foos/1")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, DEFAULT_RESPONSE)

        resp = app.test_client().get(path="/bars/1")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.json, DEFAULT_RESPONSE)

        swagger = get_swagger(test_client=app.test_client())
        self.assertIn("/bars/{foo_uid}", swagger["paths"])
        self.assertIn("/foos/{foo_uid}", swagger["paths"])
예제 #20
0
    def test_validate_headers(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        register_default_authenticator(registry)

        @registry.handles(rule='/me',
                          method='GET',
                          marshal_schema={
                              200: MeSchema(),
                          },
                          headers_schema=HeadersSchema())
        def get_me():
            return {'user_name': rebar.validated_headers['name']}

        app = create_rebar_app(rebar)

        headers = auth_headers()
        headers['x-name'] = 'hello'

        resp = app.test_client().get(path='/me', headers=headers)
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), {'user_name': 'hello'})

        resp = app.test_client().get(
            path='/me',
            headers=auth_headers()  # Missing the x-name header!
        )
        self.assertEqual(resp.status_code, 400)
예제 #21
0
    def test_validate_body_parameters(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(
            rule='/foos/<foo_uid>',
            method='PATCH',
            marshal_schema={200: FooSchema()},
            request_body_schema=FooUpdateSchema(),
        )
        def update_foo(foo_uid):
            return {'uid': foo_uid, 'name': rebar.validated_body['name']}

        app = create_rebar_app(rebar)

        resp = app.test_client().patch(
            path='/foos/1',
            data=json.dumps({'name': 'jill'}),
            headers={'Content-Type': 'application/json'})
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), {
            'uid': '1',
            'name': 'jill'
        })

        resp = app.test_client().patch(
            path='/foos/1',
            data=json.dumps({'name': 123}),  # Name should be string, not int
            headers={'Content-Type': 'application/json'})
        self.assertEqual(resp.status_code, 400)
예제 #22
0
    def test_view_function_tuple_response(self):
        header_key = "X-Foo"
        header_value = "bar"
        headers = {header_key: header_value}

        for marshal_schema, rv, expected_status, expected_body, expected_headers in [
            (FooSchema(), DEFAULT_RESPONSE, 200, DEFAULT_RESPONSE, {}),
            ({
                201: FooSchema()
            }, (DEFAULT_RESPONSE, 201), 201, DEFAULT_RESPONSE, {}),
            ({
                201: FooSchema()
            }, (DEFAULT_RESPONSE, 200), 500, DEFAULT_ERROR, {}),
            ({
                204: None
            }, (None, 204), 204, "", {}),
            (
                {
                    200: FooSchema()
                },
                (DEFAULT_RESPONSE, headers),
                200,
                DEFAULT_RESPONSE,
                headers,
            ),
            (
                {
                    201: FooSchema()
                },
                (DEFAULT_RESPONSE, 201, headers),
                201,
                DEFAULT_RESPONSE,
                headers,
            ),
            ({
                201: None
            }, (None, 201, headers), 201, "", headers),
        ]:
            rebar = Rebar()
            registry = rebar.create_handler_registry()

            @registry.handles(rule="/foo", marshal_schema=marshal_schema)
            def foo():
                return rv

            app = create_rebar_app(rebar)

            resp = app.test_client().get("/foo")

            body = get_json_from_resp(
                resp) if resp.data else resp.data.decode()
            self.assertEqual(body, expected_body)
            self.assertEqual(resp.status_code, expected_status)

            for key, value in expected_headers.items():
                self.assertEqual(resp.headers[key], value)
예제 #23
0
    def test_override_with_no_authenticator(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        register_default_authenticator(registry)
        register_endpoint(registry, authenticator=None)
        app = create_rebar_app(rebar)

        resp = app.test_client().get(path='/foos/1')
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), DEFAULT_RESPONSE)
예제 #24
0
    def test_flask_response_instance_interop_body_does_not_match_schema(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        schema = FooUpdateSchema()

        @registry.handles(rule="/foo",
                          method="PUT",
                          response_body_schema=schema)
        def foo():
            return make_response(json.dumps({"does not match": "foo schema"}))

        app = create_rebar_app(rebar)
        resp = app.test_client().put(path="/foo")
        self.assertEqual(resp.status_code, 500)
예제 #25
0
    def test_default_authentication(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        register_default_authenticator(registry)
        register_endpoint(registry)
        app = create_rebar_app(rebar)

        resp = app.test_client().get(path='/foos/1', headers=auth_headers())
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), DEFAULT_RESPONSE)

        resp = app.test_client().get(path='/foos/1',
                                     headers=auth_headers(secret='LIES!'))
        self.assertEqual(resp.status_code, 401)
예제 #26
0
    def test_flask_response_instance_interop_no_schema(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(rule="/foo", response_body_schema={302: None})
        def foo():
            return make_response(("Redirecting", 302, {
                "Location": "http://foo.com"
            }))

        app = create_rebar_app(rebar)
        resp = app.test_client().get(path="/foo")
        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp.headers["Location"], "http://foo.com")
예제 #27
0
def test_path_parameter_types_must_be_the_same_for_same_path(generator):
    rebar = Rebar()
    registry = rebar.create_handler_registry()

    @registry.handles(rule="/foos/<string:foo_uid>", method="GET")
    def get_foo(foo_uid):
        pass

    @registry.handles(rule="/foos/<int:foo_uid>", method="PATCH")
    def update_foo(foo_uid):
        pass

    with pytest.raises(ValueError):
        generator.generate(registry)
예제 #28
0
    def test_default_mimetype_for_null_response_schema(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry(default_mimetype="content/type")

        @registry.handles(rule="/me", method="DELETE", response_body_schema={204: None})
        def delete_me():
            return None, 204

        app = create_rebar_app(rebar)
        resp = app.test_client().delete(path="/me")

        self.assertEqual(resp.status_code, 204)
        self.assertEqual(resp.data.decode("utf-8"), "")
        self.assertEqual(resp.headers["Content-Type"], "content/type")
예제 #29
0
    def test_flask_response_instance_interop_body_matches_schema(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()
        schema = FooUpdateSchema()

        @registry.handles(rule="/foo",
                          method="PUT",
                          response_body_schema=schema)
        def foo():
            return make_response((json.dumps({"name": "foo"}), {"foo": "bar"}))

        app = create_rebar_app(rebar)
        resp = app.test_client().put(path="/foo")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.headers["foo"], "bar")
    def test_path_parameter_types_must_be_the_same_for_same_path(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        @registry.handles(rule='/foos/<string:foo_uid>', method='GET')
        def get_foo(foo_uid):
            pass

        @registry.handles(rule='/foos/<int:foo_uid>', method='PATCH')
        def update_foo(foo_uid):
            pass

        generator = SwaggerV2Generator()

        with self.assertRaises(ValueError):
            generator.generate(registry)