diff --git a/ninja/openapi/schema.py b/ninja/openapi/schema.py index 7bc65e2fa..139579999 100644 --- a/ninja/openapi/schema.py +++ b/ninja/openapi/schema.py @@ -1,14 +1,14 @@ import itertools import re from http.client import responses -from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Set, Tuple +from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Set, Tuple, Union from django.utils.termcolors import make_style from ninja.constants import NOT_SET from ninja.operation import Operation from ninja.params.models import TModel, TModels -from ninja.schema import NinjaGenerateJsonSchema +from ninja.schema import Schema, NinjaGenerateJsonSchema from ninja.types import DictStrAny from ninja.utils import normalize_path @@ -23,6 +23,17 @@ "file": "multipart/form-data", } +http422 = 422 + + +class DefaultValidationError(Schema): + class ValidationError(Schema): + loc: List[Union[str, int]] + msg: str + type: str + + detail: List[ValidationError] + def get_schema(api: "NinjaAPI", path_prefix: str = "") -> "OpenAPISchema": openapi = OpenAPISchema(api, path_prefix) @@ -88,13 +99,13 @@ def methods(self, operations: list) -> DictStrAny: return result def deep_dict_update( - self, main_dict: Dict[Any, Any], update_dict: Dict[Any, Any] + self, main_dict: Dict[Any, Any], update_dict: Dict[Any, Any] ) -> None: for key in update_dict: if ( - key in main_dict - and isinstance(main_dict[key], dict) - and isinstance(update_dict[key], dict) + key in main_dict + and isinstance(main_dict[key], dict) + and isinstance(update_dict[key], dict) ): self.deep_dict_update( main_dict[key], update_dict[key] @@ -167,7 +178,7 @@ def _extract_parameters(self, model: TModel) -> List[DictStrAny]: p_schema: DictStrAny p_required: bool for p_name, p_schema, p_required in flatten_properties( - name, details, is_required, schema.get("$defs", {}) + name, details, is_required, schema.get("$defs", {}) ): if not p_schema.get("include_in_schema", True): continue @@ -206,10 +217,10 @@ def _flatten_schema(self, model: TModel) -> DictStrAny: return flattened def _create_schema_from_model( - self, - model: TModel, - by_alias: bool = True, - remove_level: bool = True, + self, + model: TModel, + by_alias: bool = True, + remove_level: bool = True, ) -> Tuple[DictStrAny, bool]: if hasattr(model, "__ninja_flatten_map__"): schema = self._flatten_schema(model) @@ -234,7 +245,7 @@ def _create_schema_from_model( return schema, True def _create_multipart_schema_from_models( - self, models: TModels + self, models: TModels ) -> Tuple[DictStrAny, str]: # We have File and Form or Body, so we need to use multipart (File) content_type = BODY_CONTENT_TYPES["file"] @@ -291,7 +302,13 @@ def responses(self, operation: Operation) -> Dict[int, DictStrAny]: self.api.renderer.media_type: {"schema": schema} } result.update(details) - + if http422 not in result: + model = operation._create_response_model_multiple({http422: DefaultValidationError})[http422] + schema = self._create_schema_from_model(model)[0] + result[http422] = { + "description": "Validation error", + "content": {self.api.renderer.media_type: {"schema": schema}}, + } return result def operation_security(self, operation: Operation) -> Optional[List[DictStrAny]]: @@ -322,10 +339,10 @@ def add_schema_definitions(self, definitions: dict) -> None: def flatten_properties( - prop_name: str, - prop_details: DictStrAny, - prop_required: bool, - definitions: DictStrAny, + prop_name: str, + prop_details: DictStrAny, + prop_required: bool, + definitions: DictStrAny, ) -> Generator[Tuple[str, DictStrAny, bool], None, None]: """ extracts all nested model's properties into flat properties diff --git a/tests/test_alias.py b/tests/test_alias.py index 3430ed6b4..d3250636f 100644 --- a/tests/test_alias.py +++ b/tests/test_alias.py @@ -15,19 +15,36 @@ def alias_operation(request): def test_alias(): schema = api.get_openapi_schema()["components"] - print(schema) - assert schema == { - "schemas": { - "SchemaWithAlias": { - "type": "object", - "properties": { - "foo": {"type": "string", "default": "", "title": "Foo"} - }, - "title": "SchemaWithAlias", - } - } + assert schema['schemas']['SchemaWithAlias'] == { + "type": "object", + "properties": { + "foo": {"type": "string", "default": "", "title": "Foo"} + }, + "title": "SchemaWithAlias", } + assert schema['schemas']['DefaultValidationError'] == { + 'properties': { + 'detail': { + 'items': {'$ref': '#/components/schemas/ValidationError'}, + 'title': 'Detail', 'type': 'array' + } + }, + 'required': ['detail'], + 'title': 'DefaultValidationError', 'type': 'object' + } + assert schema['schemas']['ValidationError'] == { + 'properties': { + 'loc': { + 'items': { + 'anyOf': [{'type': 'string'}, {'type': 'integer'}] + }, 'title': 'Loc', 'type': 'array' + }, + 'msg': {'title': 'Msg', 'type': 'string'}, + 'type': {'title': 'Type', 'type': 'string'} + }, + 'required': ['loc', 'msg', 'type'], 'title': 'ValidationError', 'type': 'object' + } # TODO: check the conflicting approach # when alias is used both for response and request schema diff --git a/tests/test_annotated.py b/tests/test_annotated.py index b2265fa0f..927ccc97c 100644 --- a/tests/test_annotated.py +++ b/tests/test_annotated.py @@ -21,19 +21,19 @@ class Payload(Schema): @api.post("/multi/{p}") def multi_op( - request, - q: Annotated[str, Query(description="Query param")], - p: Annotated[int, Path(description="Path param")], - f: Annotated[FormData, Form(description="Form params")], - c: Annotated[str, Cookie(description="Cookie params")], + request, + q: Annotated[str, Query(description="Query param")], + p: Annotated[int, Path(description="Path param")], + f: Annotated[FormData, Form(description="Form params")], + c: Annotated[str, Cookie(description="Cookie params")], ): return {"q": q, "p": p, "f": f.dict(), "c": c} @api.post("/query_list") def query_list( - request, - q: Annotated[List[str], Query(description="User ID")], + request, + q: Annotated[List[str], Query(description="User ID")], ): return {"q": q} @@ -45,7 +45,7 @@ def headers(request, h: Annotated[str, Header()] = "some-default"): @api.post("/body") def body_op( - request, payload: Annotated[Payload, Body(examples=[{"t": 42, "p": "test"}])] + request, payload: Annotated[Payload, Body(examples=[{"t": 42, "p": "test"}])] ): return {"payload": payload} @@ -84,7 +84,6 @@ def test_headers(): def test_openapi_schema(): schema = api.get_openapi_schema()["paths"] - print(schema) assert schema == { "/api/multi/{p}": { "post": { @@ -125,7 +124,21 @@ def test_openapi_schema(): "description": "Cookie params", }, ], - "responses": {200: {"description": "OK"}}, + "responses": { + 200: { + "description": "OK" + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" + } + }, "requestBody": { "content": { "application/x-www-form-urlencoded": { @@ -162,7 +175,21 @@ def test_openapi_schema(): "description": "User ID", } ], - "responses": {200: {"description": "OK"}}, + "responses": { + 200: { + "description": "OK" + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" + } + }, } }, "/api/headers": { @@ -181,7 +208,21 @@ def test_openapi_schema(): "required": False, } ], - "responses": {200: {"description": "OK"}}, + "responses": { + 200: { + "description": "OK" + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" + } + }, } }, "/api/body": { @@ -189,7 +230,21 @@ def test_openapi_schema(): "operationId": "test_annotated_body_op", "summary": "Body Op", "parameters": [], - "responses": {200: {"description": "OK"}}, + "responses": { + 200: { + "description": "OK" + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" + } + }, "requestBody": { "content": { "application/json": { diff --git a/tests/test_openapi_schema.py b/tests/test_openapi_schema.py index f7bf5d627..030586f29 100644 --- a/tests/test_openapi_schema.py +++ b/tests/test_openapi_schema.py @@ -92,9 +92,9 @@ def method_form_file(request, files: List[UploadedFile], data: Payload = Form(.. @api.post("/test-body-file", response=Response) def method_body_file( - request, - files: List[UploadedFile], - body: Payload = Body(...), + request, + files: List[UploadedFile], + body: Payload = Body(...), ): return dict(i=body.i, f=body.f) @@ -124,35 +124,35 @@ def method_new_union_payload(request, data: "TypeA | TypeB"): response=Response, ) def method_test_title_description( - request, - param1: int = Query(..., title="param 1 title"), - param2: str = Query("A Default", description="param 2 desc"), - file: UploadedFile = File(..., description="file param desc"), + request, + param1: int = Query(..., title="param 1 title"), + param2: str = Query("A Default", description="param 2 desc"), + file: UploadedFile = File(..., description="file param desc"), ): return dict(i=param1, f=param2) @api.post("/test-deprecated-example-examples/") def method_test_deprecated_example_examples( - request, - param1: int = Query(None, deprecated=True), - param2: str = Query(..., example="Example Value"), - param3: str = Query( - ..., - max_length=5, - examples={ - "normal": { - "summary": "A normal example", - "description": "A **normal** string works correctly.", - "value": "Foo", - }, - "invalid": { - "summary": "Invalid data is rejected with an error", - "value": "MoreThan5Length", - }, - }, - ), - param4: int = Query(None, deprecated=True, include_in_schema=False), + request, + param1: int = Query(None, deprecated=True), + param2: str = Query(..., example="Example Value"), + param3: str = Query( + ..., + max_length=5, + examples={ + "normal": { + "summary": "A normal example", + "description": "A **normal** string works correctly.", + "value": "Foo", + }, + "invalid": { + "summary": "Invalid data is rejected with an error", + "value": "MoreThan5Length", + }, + }, + ), + param4: int = Query(None, deprecated=True, include_in_schema=False), ): return dict(i=param2, f=param3) @@ -199,6 +199,16 @@ def test_schema(schema): } }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } assert schema.schemas == { @@ -211,6 +221,55 @@ def test_schema(schema): }, "required": ["i", "f"], }, + "DefaultValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array" + } + }, + "required": [ + "detail" + ], + "title": "DefaultValidationError", + "type": "object" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "title": "Loc", + "type": "array" + }, + "msg": { + "title": "Msg", + "type": "string" + }, + "type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError", + "type": "object" + }, "Payload": { "title": "Payload", "type": "object", @@ -256,7 +315,18 @@ def test_schema_alias(schema): } }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } + } # ::TODO:: this is currently broken if not all responses for same schema use the same by_alias """ @@ -310,6 +380,16 @@ def test_schema_list(schema): } }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -348,6 +428,55 @@ def test_schema_list(schema): "title": "Response", "type": "object", }, + "DefaultValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "title": "Detail", + "type": "array" + } + }, + "required": [ + "detail" + ], + "title": "DefaultValidationError", + "type": "object" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "title": "Loc", + "type": "array" + }, + "msg": { + "title": "Msg", + "type": "string" + }, + "type": { + "title": "Type", + "type": "string" + } + }, + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError", + "type": "object" + } } @@ -378,6 +507,16 @@ def test_schema_body(schema): } }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -399,6 +538,16 @@ def test_schema_body_schema(schema): } }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -431,6 +580,16 @@ def test_schema_path(schema): }, }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -462,6 +621,16 @@ def test_schema_form(schema): "schema": {"$ref": "#/components/schemas/Response"} } }, + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -490,6 +659,16 @@ def test_schema_single(schema): "schema": {"$ref": "#/components/schemas/Response"} } }, + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -520,6 +699,16 @@ def test_schema_form_body(schema): "schema": {"$ref": "#/components/schemas/Response"} } }, + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -556,6 +745,16 @@ def test_schema_form_file(schema): "schema": {"$ref": "#/components/schemas/Response"} } }, + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -591,6 +790,16 @@ def test_schema_body_file(schema): "schema": {"$ref": "#/components/schemas/Response"} } }, + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -651,6 +860,16 @@ def test_schema_title_description(schema): } }, "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -710,6 +929,16 @@ def test_schema_deprecated_example_examples(schema): assert method_list["responses"] == { 200: { "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -736,7 +965,6 @@ def test_union_payload_type(schema): def test_union_payload_simple(schema): method = schema["paths"]["/api/test-union-type-with-simple"]["post"] - print(method["requestBody"]) assert method["requestBody"] == { "content": { "application/json": { @@ -787,7 +1015,7 @@ def test_get_openapi_urls(): api = NinjaAPI(openapi_url="/path", docs_url="/path") with pytest.raises( - AssertionError, match="Please use different urls for openapi_url and docs_url" + AssertionError, match="Please use different urls for openapi_url and docs_url" ): get_openapi_urls(api) @@ -824,6 +1052,57 @@ def test_docs_decorator(): assert result.status_code == 302 +def test_default_error_schema(): + api = NinjaAPI() + + @api.get("/1") + def some_name(request): + pass + + schema = api.get_openapi_schema() + responses = schema['paths']['/api/1']['get']['responses'] + assert responses == { + 200: { + "description": "OK", + }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" + } + } + + +def test_override_default_error_schema(): + api = NinjaAPI() + + class ValidationError(Schema): + error: str + + @api.get("/1", response={422: ValidationError}) + def some_name(request): + pass + + schema = api.get_openapi_schema() + responses = schema['paths']['/api/1']['get']['responses'] + assert responses == { + 422:{ + 'content': { + 'application/json': { + 'schema': { + '$ref': '#/components/schemas/ValidationError' + } + } + }, 'description': 'Unprocessable Entity' + } + } + + class TestRenderer(JSONRenderer): media_type = "custom/type" @@ -833,7 +1112,7 @@ def test_renderer_media_type(): @api.get("/1", response=TypeA) def same_name( - request, + request, ): pass @@ -845,6 +1124,16 @@ def same_name( "custom/type": {"schema": {"$ref": "#/components/schemas/TypeA"}} }, "description": "OK", + }, + 422: { + "content": { + "custom/type": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } @@ -854,13 +1143,13 @@ def test_all_paths_rendered(): @api.post("/1") def some_name_create( - request, + request, ): pass @api.get("/1") def some_name_list( - request, + request, ): pass @@ -884,13 +1173,13 @@ def test_all_paths_typed_params_rendered(): @api.post("/1") def some_name_create( - request, + request, ): pass @api.get("/1") def some_name_list( - request, + request, ): pass diff --git a/tests/test_response_multiple.py b/tests/test_response_multiple.py index f9c643fe2..6de24d587 100644 --- a/tests/test_response_multiple.py +++ b/tests/test_response_multiple.py @@ -115,13 +115,13 @@ def test_responses(path, expected_status, expected_response): def test_schema(): checks = [ - ("/api/check_int", {200}), - ("/api/check_int2", {200}), - ("/api/check_single_with_status", {200}), - ("/api/check_response_schema", {400}), - ("/api/check_model", {200, 202}), - ("/api/check_list_model", {200}), - ("/api/check_union", {200, 400}), + ("/api/check_int", {200, 422}), + ("/api/check_int2", {200, 422}), + ("/api/check_single_with_status", {200, 422}), + ("/api/check_response_schema", {400, 422}), + ("/api/check_model", {200, 202, 422}), + ("/api/check_list_model", {200, 422}), + ("/api/check_union", {200, 400, 422}), ] schema = api.get_openapi_schema() @@ -151,6 +151,16 @@ def test_schema(): }, "description": "Accepted", }, + 422: { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" + } } @@ -165,7 +175,11 @@ def test_no_content(): schema = api.get_openapi_schema() details = schema["paths"]["/api/check_no_content"]["get"]["responses"] - assert details == {204: {"description": "No Content"}} + assert details[204] == {"description": "No Content"} + assert details[422] == { + 'content': {'application/json': {'schema': {'$ref': '#/components/schemas/DefaultValidationError'}}}, + 'description': 'Validation error' + } def test_validates(): diff --git a/tests/test_with_django/schema_fixtures/test-multi-body-file.json b/tests/test_with_django/schema_fixtures/test-multi-body-file.json index bb5deeeb0..04b1933ed 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-body-file.json +++ b/tests/test_with_django/schema_fixtures/test-multi-body-file.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-body-form-file.json b/tests/test_with_django/schema_fixtures/test-multi-body-form-file.json index 9a610c616..ca7fc4201 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-body-form-file.json +++ b/tests/test_with_django/schema_fixtures/test-multi-body-form-file.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-body-form.json b/tests/test_with_django/schema_fixtures/test-multi-body-form.json index 7ec66f433..7f109d8a7 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-body-form.json +++ b/tests/test_with_django/schema_fixtures/test-multi-body-form.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-body.json b/tests/test_with_django/schema_fixtures/test-multi-body.json index 1b1d40d23..0dc3b9155 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-body.json +++ b/tests/test_with_django/schema_fixtures/test-multi-body.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-cookie.json b/tests/test_with_django/schema_fixtures/test-multi-cookie.json index faac3b90d..66c596827 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-cookie.json +++ b/tests/test_with_django/schema_fixtures/test-multi-cookie.json @@ -116,6 +116,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "description": "Testing w/ Cookies requires setting the cookies by hand in the browser inspector" diff --git a/tests/test_with_django/schema_fixtures/test-multi-form-body-file.json b/tests/test_with_django/schema_fixtures/test-multi-form-body-file.json index 2c9dea2d9..c02317a84 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-form-body-file.json +++ b/tests/test_with_django/schema_fixtures/test-multi-form-body-file.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-form-body.json b/tests/test_with_django/schema_fixtures/test-multi-form-body.json index c7c4c24b8..93abd45de 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-form-body.json +++ b/tests/test_with_django/schema_fixtures/test-multi-form-body.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-form-file.json b/tests/test_with_django/schema_fixtures/test-multi-form-file.json index f7392dd2f..3b37735b8 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-form-file.json +++ b/tests/test_with_django/schema_fixtures/test-multi-form-file.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-form.json b/tests/test_with_django/schema_fixtures/test-multi-form.json index c2b81828e..87e9214f0 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-form.json +++ b/tests/test_with_django/schema_fixtures/test-multi-form.json @@ -13,6 +13,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } }, "requestBody": { diff --git a/tests/test_with_django/schema_fixtures/test-multi-header.json b/tests/test_with_django/schema_fixtures/test-multi-header.json index 8c1610b20..20ef94970 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-header.json +++ b/tests/test_with_django/schema_fixtures/test-multi-header.json @@ -116,6 +116,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } } diff --git a/tests/test_with_django/schema_fixtures/test-multi-path.json b/tests/test_with_django/schema_fixtures/test-multi-path.json index d549c9b65..4ee1c9195 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-path.json +++ b/tests/test_with_django/schema_fixtures/test-multi-path.json @@ -116,6 +116,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } } diff --git a/tests/test_with_django/schema_fixtures/test-multi-query.json b/tests/test_with_django/schema_fixtures/test-multi-query.json index 7ad57b263..baf74ea9f 100644 --- a/tests/test_with_django/schema_fixtures/test-multi-query.json +++ b/tests/test_with_django/schema_fixtures/test-multi-query.json @@ -116,6 +116,16 @@ } } } + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultValidationError" + } + } + }, + "description": "Validation error" } } }