async def test_wrong_item_in_array(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request): """ --- parameters: - name: array in: query required: true schema: type: array items: type: integer responses: '200': description: OK. """ return web.json_response() s.add_route("POST", "/r", handler) client = await aiohttp_client(app) params = {"array": ",".join(str(x) for x in [1, "abc", 3, True, 5])} resp = await client.post(f"/r", params=params) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"array": {"1": "value should be type of int"}}
async def test_missing_query_parameter(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request): """ --- parameters: - name: variable in: query required: true schema: type: integer responses: '200': description: OK. """ return web.json_response() s.add_route("GET", "/r", handler) client = await aiohttp_client(app) resp = await client.get("/r") assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"variable": "is required"}
async def test_decorated_routes(aiohttp_client, loop): app = web.Application(loop=loop) routes = web.RouteTableDef() @routes.get("/r") async def handler(request, int32: int): """ --- parameters: - name: int32 in: query required: true schema: type: integer responses: '200': description: OK. """ return web.json_response({"int32": int32}) s = SwaggerDocs(app, "/docs") s.add_routes(routes) client = await aiohttp_client(app) params = {"int32": 15} resp = await client.get("/r", params=params) assert resp.status == 200 assert await resp.json() == params
async def test_array_in_object(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object required: - array properties: array: type: array items: type: integer responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) body = {"array": []} resp = await client.post("/r", json=body) assert resp.status == 200 assert await resp.json() == body body = {"array": [1, 2, 3]} resp = await client.post("/r", json=body) assert resp.status == 200 assert await resp.json() == body body = {"array": ["1", 2, 3]} resp = await client.post("/r", json=body) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"body": {"array": {"0": "value should be type of int"}}} body = {"array": [1, 2.2, 3]} resp = await client.post("/r", json=body) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"body": {"array": {"1": "value should be type of int"}}} body = {"array": [1, 2, True]} resp = await client.post("/r", json=body) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"body": {"array": {"2": "value should be type of int"}}}
async def test_validation_false(aiohttp_client, loop): app = web.Application(loop=loop) routes = web.RouteTableDef() @routes.post("/r") async def handler(request): """ --- parameters: - name: query in: query required: true schema: type: string responses: '200': description: OK. """ assert "data" not in request assert request.rel_url.query["query"] == "str" return web.json_response() s = SwaggerDocs(app, "/docs", validate=False) s.add_routes(routes) client = await aiohttp_client(app) params = {"query": "str"} resp = await client.post("/r", params=params) assert resp.status == 200 resp = await client.get("/docs/") assert resp.status == 200 resp = await client.get("/docs/swagger.json") assert resp.status == 200 spec = await resp.json() assert spec["paths"] == { "/r": { "post": { "parameters": [{ "name": "query", "in": "query", "required": True, "schema": { "type": "string" }, }], "responses": { "200": { "description": "OK." } }, } } }
def main(): app = web.Application() s = SwaggerDocs( app, components="components.yaml", swagger_ui_settings=SwaggerUiSettings(path="/docs"), ) s.add_routes([web.get("/", handler, allow_head=False)]) web.run_app(app)
async def test_one_of_auth(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs", components="tests/testdata/components.yaml") async def handler(request): """ --- security: - bearerAuth: [] - apiKeyCookieAuth: [] responses: '200': description: OK. """ assert not ("C-API-KEY" in request["data"] and "authorization" in request["data"]) r = {} if "C-API-KEY" in request["data"]: assert "authorization" not in request["data"] r["api_key"] = request["data"]["C-API-KEY"] else: assert "authorization" in request["data"] assert "C-API-KEY" not in request["data"] r["authorization"] = request["data"]["authorization"] return web.json_response(r) s.add_route("GET", "/r", handler) client = await aiohttp_client(app) api_key = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ4" cookies = {"C-API-KEY": api_key} resp = await client.get("/r", cookies=cookies) assert resp.status == 200 assert await resp.json() == {"api_key": api_key} authorization = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ1" headers = {"Authorization": f"Bearer {authorization}"} resp = await client.get("/r", headers=headers) assert resp.status == 200 assert await resp.json() == {"authorization": authorization} resp = await client.get("/r", cookies=cookies, headers=headers) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == "Only one auth must be provided" resp = await client.get("/r") assert resp.status == 400 error = error_to_json(await resp.text()) assert error == "One auth must be provided"
def main(): app = web.Application() s = SwaggerDocs( app, swagger_ui_settings=SwaggerUiSettings(path="/swagger"), redoc_ui_settings=ReDocUiSettings(path="/redoc"), rapidoc_ui_settings=RapiDocUiSettings(path="/rapidoc"), ) s.add_routes([web.get("/", handler, allow_head=True)]) web.run_app(app)
async def test_no_docs(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request): return web.json_response() s.add_route("POST", "/r", handler) client = await aiohttp_client(app) resp = await client.post("/r", json={"array": "whatever"}) assert resp.status == 200
async def test_swagger_json(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs( app, "/docs", title="test app", version="2.2.2", description="test description" ) async def handler(request, param_id: int): """ --- parameters: - name: param_id in: path required: true schema: type: integer responses: '200': description: OK. """ return web.json_response({"param_id": param_id}) s.add_route("GET", "/r/{param_id}", handler) client = await aiohttp_client(app) resp = await client.get("/docs/swagger.json") assert resp.status == 200 assert await resp.json() == { "openapi": "3.0.0", "info": { "title": "test app", "version": "2.2.2", "description": "test description", }, "paths": { "/r/{param_id}": { "get": { "parameters": [ { "in": "path", "name": "param_id", "required": True, "schema": {"type": "integer"}, } ], "responses": {"200": {"description": "OK."}}, } } }, }
async def test_form_data(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object properties: integer: type: integer number: type: number string: type: string boolean: type: boolean responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) integer = 15 number = 15.5 string = "string" boolean = True data = { "integer": integer, "number": number, "string": string, "boolean": str(boolean).lower(), } resp = await client.post("/r", data=data) assert resp.status == 200 assert await resp.json() == { "integer": integer, "number": number, "string": string, "boolean": boolean, }
async def test_named_resources(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request): return web.json_response() s.add_routes( [web.get("/", handler, name="get"), web.post("/", handler, name="post")] ) assert "get" in app.router assert "post" in app.router
async def test_all_of_auth(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs", components="tests/testdata/components.yaml") async def handler(request): """ --- security: - basicAuth: [] apiKeyCookieAuth: [] responses: '200': description: OK. """ assert "C-API-KEY" in request["data"] assert "authorization" in request["data"] return web.json_response({ "api_key": request["data"]["C-API-KEY"], "authorization": request["data"]["authorization"], }) s.add_route("GET", "/r", handler) client = await aiohttp_client(app) api_key = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ4" cookies = {"C-API-KEY": api_key} authorization = "ZGVtbzpwQDU1dzByZA==" headers = {"Authorization": f"Basic {authorization}"} resp = await client.get("/r", headers=headers, cookies=cookies) assert resp.status == 200 assert await resp.json() == { "api_key": api_key, "authorization": authorization } resp = await client.get("/r", cookies=cookies) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"authorization": "is required"} resp = await client.get("/r", headers=headers) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"C-API-KEY": "is required"}
async def test_min_max_properties(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object minProperties: 2 maxProperties: 5 responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) body = {"str1": "str1", "str2": "str1", "str3": "str1"} resp = await client.post(f"/r", json=body) assert resp.status == 200 assert await resp.json() == body body = {"str1": "str1"} resp = await client.post(f"/r", json=body) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"body": "number or properties must be more than 2"} body = { "str1": "str1", "str2": "str1", "str3": "str1", "str4": "str1", "str5": "str1", "str6": "str1", } resp = await client.post(f"/r", json=body) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == {"body": "number or properties must be less than 5"}
def main(): app = web.Application() s = SwaggerDocs(app, '/docs', title="Swagger Petstore", version="1.0.0", components="components.yaml") s.add_routes([ web.get("/pets", get_all_pets), web.get("/pets/{pet_id}", get_one_pet), web.delete("/pets/{pet_id}", delete_one_pet), web.post("/pets", create_pet), ]) app['storage'] = {} web.run_app(app)
def main(): app = web.Application() s = SwaggerDocs( app, title="Example", version="1.0.0", swagger_ui_settings=SwaggerUiSettings(path="/docs"), ) s.add_routes( [ web.get("/docstring", docstring_handler, allow_head=False), web.get("/decorator", decorator_handler, allow_head=False), ] ) web.run_app(app)
def _swagger_docs_with_components(**kwargs): app = web.Application() return SwaggerDocs( app, components="tests/testdata/components.yaml", **kwargs, )
async def test_two_uis_one_path(swagger_ui_settings, redoc_ui_settings): app = web.Application() with pytest.raises(Exception) as exc_info: SwaggerDocs( app, swagger_ui_settings=swagger_ui_settings(), redoc_ui_settings=redoc_ui_settings(), ) assert str(exc_info.value) == "cannot bind two UIs on the same path"
async def test_query_array(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, query1: List[int], query2: List[int] = None): """ --- parameters: - name: query1 in: query required: true schema: type: array items: type: integer uniqueItems: true minItems: 1 - name: query2 in: query schema: type: array items: type: integer uniqueItems: true minItems: 1 responses: '200': description: OK. """ return web.json_response({"query1": query1, "query2": query2}) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) query1 = [1, 2, 3, 4, 5] params = {"query1": ",".join(str(x) for x in query1)} resp = await client.post(f"/r", params=params) assert resp.status == 200 assert await resp.json() == {"query1": query1, "query2": None}
def main(): app = web.Application() s = SwaggerDocs( app, title="Swagger Petstore", version="1.0.0", components="components.yaml", swagger_ui_settings=SwaggerUiSettings(path="/docs"), ) s.add_routes( [ web.get("/pets", get_all_pets), web.get("/pets/{pet_id}", get_one_pet), web.delete("/pets/{pet_id}", delete_one_pet), web.post("/pets", create_pet), ] ) app["storage"] = {} web.run_app(app)
async def test_body_with_no_additional_properties(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - required properties: required: type: integer optional: type: integer responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) body = {"required": 10, "optional": 15, "str": "str", "int": 10} resp = await client.post("/r", json=body) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == { "body": { "int": "additional property not allowed", "str": "additional property not allowed", } }
async def test_float_as_int(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object required: - int_float - int_double properties: int_float: type: number format: float int_double: type: number format: double responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) int_float = 10 int_double = 20 body = {"int_float": int_float, "int_double": int_double} resp = await client.post(f"/r", json=body) assert resp.status == 200 assert await resp.json() == body
async def test_object_can_have_optional_props(aiohttp_client, loop): app = web.Application(loop=loop) routes = web.RouteTableDef() @routes.post("/r") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object properties: integer: type: integer string: type: string array: type: array items: type: string object: type: object responses: '200': description: OK. """ return web.json_response(body) s = SwaggerDocs(app, "/docs") s.add_routes(routes) client = await aiohttp_client(app) resp = await client.post("/r", json={}) assert resp.status == 200 assert await resp.json() == {}
async def test_incorrect_json_body(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object required: - required properties: required: type: integer optional: type: integer responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) resp = await client.post("/r", data="{{", headers={"content-type": "application/json"}) assert resp.status == 400 error = error_to_json(await resp.text()) assert error == { "body": "Expecting property name enclosed in double quotes: line 1 column 2 (char 1)" }
async def test_unknown_security(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs", components="tests/testdata/components.yaml") async def handler(request): """ --- security: - wrongAuth: [] responses: '200': description: OK. """ return web.json_response() with pytest.raises(Exception) as exc_info: s.add_route("GET", "/r", handler) assert "security schema wrongAuth must be defined in components" == str( exc_info.value)
def main() -> None: settings = config.get_config() app = web.Application( client_max_size=5 * 1024**2, middlewares=[handler.response_time, handler.request_counter], ) swagger = SwaggerDocs( app, swagger_ui_settings=SwaggerUiSettings(path="/api/docs/"), title="{{cookiecutter.project_name}}", version=__version__, ) config.init_config(app, settings) app.on_startup.append(startup_handler) app.on_cleanup.append(shutdown_handler) swagger.add_routes(handler.routing_table(app)) web.run_app( app, host=settings["app"]["host"], port=settings["app"]["port"], # access_log=None, )
async def test_media_type_with_charset(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object required: - required properties: required: type: integer optional: type: integer responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) body = {"required": 10} resp = await client.post( "/r", data=json.dumps(body), headers={"content-type": "application/json; charset=UTF-8"}, ) assert resp.status == 200 assert await resp.json() == body
async def test_body_with_optional_properties(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def handler(request, body: Dict): """ --- requestBody: required: true content: application/json: schema: type: object required: - required properties: required: type: integer optional: type: integer responses: '200': description: OK. """ return web.json_response(body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) body = {"required": 10} resp = await client.post("/r", json=body) assert resp.status == 200 assert await resp.json() == body body = {"required": 10, "optional": 15} resp = await client.post("/r", json=body) assert resp.status == 200 assert await resp.json() == body
async def test_file_upload(aiohttp_client, loop): app = web.Application(loop=loop) s = SwaggerDocs(app, "/docs") async def octet_stream_handler(request: web.Request) -> Tuple[bytes, bool]: return await request.read(), True s.register_media_type_handler("application/octet-stream", octet_stream_handler) async def handler(request, body: bytes): """ --- requestBody: required: true content: application/octet-stream: schema: type: string format: binary responses: '200': description: OK. """ return web.Response(body=body) s.add_route("POST", "/r", handler) client = await aiohttp_client(app) data = b"\x00Binary-data\x00" resp = await client.post("/r", data=data) assert resp.status == 200 assert await resp.read() == data
def main(): app = web.Application() s = SwaggerDocs(app) # register your custom string format validator s.register_string_format_validator("my_custom_sf", my_custom_validator) s.add_routes([web.get("/p", handler)]) web.run_app(app)