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'])
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)
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)
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"])
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}"])
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)
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)
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)
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}'])
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)
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)
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"])
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)
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)
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)
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)
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)
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))
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)
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)
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")
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)
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)
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)
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")
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)
def test_redirects_for_missing_trailing_slash(self): rebar = Rebar() registry = rebar.create_handler_registry() register_endpoint(registry=registry, path="/with_trailing_slash/") app = create_rebar_app(rebar) app.debug = False resp = app.test_client().get(path="/with_trailing_slash") self.assertIn(resp.status_code, (301, 308)) self.assertTrue(resp.headers["Location"].endswith("/with_trailing_slash/")) app.debug = True resp = app.test_client().get(path="/with_trailing_slash") self.assertIn(resp.status_code, (301, 308)) self.assertTrue(resp.headers["Location"].endswith("/with_trailing_slash/"))
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)
def test_uncaught_errors_are_not_jsonified_in_debug_mode(self): rebar = Rebar() registry = rebar.create_handler_registry() @registry.handles("/force_500") def force_500(): raise ArithmeticError() app = create_rebar_app(rebar) app.debug = False resp = app.test_client().get(path="/force_500") self.assertEqual(resp.status_code, 500) self.assertEqual(resp.content_type, "application/json") app.debug = True with self.assertRaises(ArithmeticError): app.test_client().get(path="/force_500")