Coverage for tests/test_multi_body_errors.py: 100%
30 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-08 03:53 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-08 03:53 +0000
1from decimal import Decimal 1abcde
2from typing import List 1abcde
4from dirty_equals import IsDict, IsOneOf 1abcde
5from fastapi import FastAPI 1abcde
6from fastapi.testclient import TestClient 1abcde
7from pydantic import BaseModel, condecimal 1abcde
9app = FastAPI() 1abcde
12class Item(BaseModel): 1abcde
13 name: str 1abcde
14 age: condecimal(gt=Decimal(0.0)) # type: ignore 1abcde
17@app.post("/items/") 1abcde
18def save_item_no_body(item: List[Item]): 1abcde
19 return {"item": item} 1abcde
22client = TestClient(app) 1abcde
25def test_put_correct_body(): 1abcde
26 response = client.post("/items/", json=[{"name": "Foo", "age": 5}]) 1abcde
27 assert response.status_code == 200, response.text 1abcde
28 assert response.json() == { 1abcde
29 "item": [
30 {
31 "name": "Foo",
32 "age": IsOneOf(
33 5,
34 # TODO: remove when deprecating Pydantic v1
35 "5",
36 ),
37 }
38 ]
39 }
42def test_jsonable_encoder_requiring_error(): 1abcde
43 response = client.post("/items/", json=[{"name": "Foo", "age": -1.0}]) 1abcde
44 assert response.status_code == 422, response.text 1abcde
45 assert response.json() == IsDict( 1abcde
46 {
47 "detail": [
48 {
49 "type": "greater_than",
50 "loc": ["body", 0, "age"],
51 "msg": "Input should be greater than 0",
52 "input": -1.0,
53 "ctx": {"gt": 0},
54 }
55 ]
56 }
57 ) | IsDict(
58 # TODO: remove when deprecating Pydantic v1
59 {
60 "detail": [
61 {
62 "ctx": {"limit_value": 0.0},
63 "loc": ["body", 0, "age"],
64 "msg": "ensure this value is greater than 0",
65 "type": "value_error.number.not_gt",
66 }
67 ]
68 }
69 )
72def test_put_incorrect_body_multiple(): 1abcde
73 response = client.post("/items/", json=[{"age": "five"}, {"age": "six"}]) 1abcde
74 assert response.status_code == 422, response.text 1abcde
75 assert response.json() == IsDict( 1abcde
76 {
77 "detail": [
78 {
79 "type": "missing",
80 "loc": ["body", 0, "name"],
81 "msg": "Field required",
82 "input": {"age": "five"},
83 },
84 {
85 "type": "decimal_parsing",
86 "loc": ["body", 0, "age"],
87 "msg": "Input should be a valid decimal",
88 "input": "five",
89 },
90 {
91 "type": "missing",
92 "loc": ["body", 1, "name"],
93 "msg": "Field required",
94 "input": {"age": "six"},
95 },
96 {
97 "type": "decimal_parsing",
98 "loc": ["body", 1, "age"],
99 "msg": "Input should be a valid decimal",
100 "input": "six",
101 },
102 ]
103 }
104 ) | IsDict(
105 # TODO: remove when deprecating Pydantic v1
106 {
107 "detail": [
108 {
109 "loc": ["body", 0, "name"],
110 "msg": "field required",
111 "type": "value_error.missing",
112 },
113 {
114 "loc": ["body", 0, "age"],
115 "msg": "value is not a valid decimal",
116 "type": "type_error.decimal",
117 },
118 {
119 "loc": ["body", 1, "name"],
120 "msg": "field required",
121 "type": "value_error.missing",
122 },
123 {
124 "loc": ["body", 1, "age"],
125 "msg": "value is not a valid decimal",
126 "type": "type_error.decimal",
127 },
128 ]
129 }
130 )
133def test_openapi_schema(): 1abcde
134 response = client.get("/openapi.json") 1abcde
135 assert response.status_code == 200, response.text 1abcde
136 assert response.json() == { 1abcde
137 "openapi": "3.1.0",
138 "info": {"title": "FastAPI", "version": "0.1.0"},
139 "paths": {
140 "/items/": {
141 "post": {
142 "responses": {
143 "200": {
144 "description": "Successful Response",
145 "content": {"application/json": {"schema": {}}},
146 },
147 "422": {
148 "description": "Validation Error",
149 "content": {
150 "application/json": {
151 "schema": {
152 "$ref": "#/components/schemas/HTTPValidationError"
153 }
154 }
155 },
156 },
157 },
158 "summary": "Save Item No Body",
159 "operationId": "save_item_no_body_items__post",
160 "requestBody": {
161 "content": {
162 "application/json": {
163 "schema": {
164 "title": "Item",
165 "type": "array",
166 "items": {"$ref": "#/components/schemas/Item"},
167 }
168 }
169 },
170 "required": True,
171 },
172 }
173 }
174 },
175 "components": {
176 "schemas": {
177 "Item": {
178 "title": "Item",
179 "required": ["name", "age"],
180 "type": "object",
181 "properties": {
182 "name": {"title": "Name", "type": "string"},
183 "age": IsDict(
184 {
185 "title": "Age",
186 "anyOf": [
187 {"exclusiveMinimum": 0.0, "type": "number"},
188 {"type": "string"},
189 ],
190 }
191 )
192 | IsDict(
193 # TODO: remove when deprecating Pydantic v1
194 {
195 "title": "Age",
196 "exclusiveMinimum": 0.0,
197 "type": "number",
198 }
199 ),
200 },
201 },
202 "ValidationError": {
203 "title": "ValidationError",
204 "required": ["loc", "msg", "type"],
205 "type": "object",
206 "properties": {
207 "loc": {
208 "title": "Location",
209 "type": "array",
210 "items": {
211 "anyOf": [{"type": "string"}, {"type": "integer"}]
212 },
213 },
214 "msg": {"title": "Message", "type": "string"},
215 "type": {"title": "Error Type", "type": "string"},
216 },
217 },
218 "HTTPValidationError": {
219 "title": "HTTPValidationError",
220 "type": "object",
221 "properties": {
222 "detail": {
223 "title": "Detail",
224 "type": "array",
225 "items": {"$ref": "#/components/schemas/ValidationError"},
226 }
227 },
228 },
229 }
230 },
231 }