Coverage for tests/test_openapi_separate_input_output_schemas.py: 100%
72 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-01-13 13:38 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-01-13 13:38 +0000
1from typing import List, Optional 1abcde
3from fastapi import FastAPI 1abcde
4from fastapi.testclient import TestClient 1abcde
5from pydantic import BaseModel 1abcde
7from .utils import PYDANTIC_V2, needs_pydanticv2 1abcde
10class SubItem(BaseModel): 1abcde
11 subname: str 1abcde
12 sub_description: Optional[str] = None 1abcde
13 tags: List[str] = [] 1abcde
14 if PYDANTIC_V2: 1abcde
15 model_config = {"json_schema_serialization_defaults_required": True} 1abcde
18class Item(BaseModel): 1abcde
19 name: str 1abcde
20 description: Optional[str] = None 1abcde
21 sub: Optional[SubItem] = None 1abcde
22 if PYDANTIC_V2: 1abcde
23 model_config = {"json_schema_serialization_defaults_required": True} 1abcde
26def get_app_client(separate_input_output_schemas: bool = True) -> TestClient: 1abcde
27 app = FastAPI(separate_input_output_schemas=separate_input_output_schemas) 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
29 @app.post("/items/", responses={402: {"model": Item}}) 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
30 def create_item(item: Item) -> Item: 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
31 return item 1pgritkvmxo
33 @app.post("/items-list/") 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
34 def create_item_list(item: List[Item]): 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
35 return item 1fhjln
37 @app.get("/items/") 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
38 def read_items() -> List[Item]: 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
39 return [ 1qsuwy
40 Item(
41 name="Portal Gun",
42 description="Device to travel through the multi-rick-verse",
43 sub=SubItem(subname="subname"),
44 ),
45 Item(name="Plumbus"),
46 ]
48 client = TestClient(app) 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
49 return client 1pfgzAqrhiBCstjkDEuvlmFGwxnoHIy
52def test_create_item(): 1abcde
53 client = get_app_client() 1prtvx
54 client_no = get_app_client(separate_input_output_schemas=False) 1prtvx
55 response = client.post("/items/", json={"name": "Plumbus"}) 1prtvx
56 response2 = client_no.post("/items/", json={"name": "Plumbus"}) 1prtvx
57 assert response.status_code == response2.status_code == 200, response.text 1prtvx
58 assert ( 1prtvx
59 response.json()
60 == response2.json()
61 == {"name": "Plumbus", "description": None, "sub": None}
62 )
65def test_create_item_with_sub(): 1abcde
66 client = get_app_client() 1gikmo
67 client_no = get_app_client(separate_input_output_schemas=False) 1gikmo
68 data = { 1gikmo
69 "name": "Plumbus",
70 "sub": {"subname": "SubPlumbus", "sub_description": "Sub WTF"},
71 }
72 response = client.post("/items/", json=data) 1gikmo
73 response2 = client_no.post("/items/", json=data) 1gikmo
74 assert response.status_code == response2.status_code == 200, response.text 1gikmo
75 assert ( 1gikmo
76 response.json()
77 == response2.json()
78 == {
79 "name": "Plumbus",
80 "description": None,
81 "sub": {"subname": "SubPlumbus", "sub_description": "Sub WTF", "tags": []},
82 }
83 )
86def test_create_item_list(): 1abcde
87 client = get_app_client() 1fhjln
88 client_no = get_app_client(separate_input_output_schemas=False) 1fhjln
89 data = [ 1fhjln
90 {"name": "Plumbus"},
91 {
92 "name": "Portal Gun",
93 "description": "Device to travel through the multi-rick-verse",
94 },
95 ]
96 response = client.post("/items-list/", json=data) 1fhjln
97 response2 = client_no.post("/items-list/", json=data) 1fhjln
98 assert response.status_code == response2.status_code == 200, response.text 1fhjln
99 assert ( 1fhjln
100 response.json()
101 == response2.json()
102 == [
103 {"name": "Plumbus", "description": None, "sub": None},
104 {
105 "name": "Portal Gun",
106 "description": "Device to travel through the multi-rick-verse",
107 "sub": None,
108 },
109 ]
110 )
113def test_read_items(): 1abcde
114 client = get_app_client() 1qsuwy
115 client_no = get_app_client(separate_input_output_schemas=False) 1qsuwy
116 response = client.get("/items/") 1qsuwy
117 response2 = client_no.get("/items/") 1qsuwy
118 assert response.status_code == response2.status_code == 200, response.text 1qsuwy
119 assert ( 1qsuwy
120 response.json()
121 == response2.json()
122 == [
123 {
124 "name": "Portal Gun",
125 "description": "Device to travel through the multi-rick-verse",
126 "sub": {"subname": "subname", "sub_description": None, "tags": []},
127 },
128 {"name": "Plumbus", "description": None, "sub": None},
129 ]
130 )
133@needs_pydanticv2 1abcde
134def test_openapi_schema(): 1abcde
135 client = get_app_client() 1zBDFH
136 response = client.get("/openapi.json") 1zBDFH
137 assert response.status_code == 200, response.text 1zBDFH
138 assert response.json() == { 1zBDFH
139 "openapi": "3.1.0",
140 "info": {"title": "FastAPI", "version": "0.1.0"},
141 "paths": {
142 "/items/": {
143 "get": {
144 "summary": "Read Items",
145 "operationId": "read_items_items__get",
146 "responses": {
147 "200": {
148 "description": "Successful Response",
149 "content": {
150 "application/json": {
151 "schema": {
152 "items": {
153 "$ref": "#/components/schemas/Item-Output"
154 },
155 "type": "array",
156 "title": "Response Read Items Items Get",
157 }
158 }
159 },
160 }
161 },
162 },
163 "post": {
164 "summary": "Create Item",
165 "operationId": "create_item_items__post",
166 "requestBody": {
167 "content": {
168 "application/json": {
169 "schema": {"$ref": "#/components/schemas/Item-Input"}
170 }
171 },
172 "required": True,
173 },
174 "responses": {
175 "200": {
176 "description": "Successful Response",
177 "content": {
178 "application/json": {
179 "schema": {
180 "$ref": "#/components/schemas/Item-Output"
181 }
182 }
183 },
184 },
185 "402": {
186 "description": "Payment Required",
187 "content": {
188 "application/json": {
189 "schema": {
190 "$ref": "#/components/schemas/Item-Output"
191 }
192 }
193 },
194 },
195 "422": {
196 "description": "Validation Error",
197 "content": {
198 "application/json": {
199 "schema": {
200 "$ref": "#/components/schemas/HTTPValidationError"
201 }
202 }
203 },
204 },
205 },
206 },
207 },
208 "/items-list/": {
209 "post": {
210 "summary": "Create Item List",
211 "operationId": "create_item_list_items_list__post",
212 "requestBody": {
213 "content": {
214 "application/json": {
215 "schema": {
216 "items": {
217 "$ref": "#/components/schemas/Item-Input"
218 },
219 "type": "array",
220 "title": "Item",
221 }
222 }
223 },
224 "required": True,
225 },
226 "responses": {
227 "200": {
228 "description": "Successful Response",
229 "content": {"application/json": {"schema": {}}},
230 },
231 "422": {
232 "description": "Validation Error",
233 "content": {
234 "application/json": {
235 "schema": {
236 "$ref": "#/components/schemas/HTTPValidationError"
237 }
238 }
239 },
240 },
241 },
242 }
243 },
244 },
245 "components": {
246 "schemas": {
247 "HTTPValidationError": {
248 "properties": {
249 "detail": {
250 "items": {"$ref": "#/components/schemas/ValidationError"},
251 "type": "array",
252 "title": "Detail",
253 }
254 },
255 "type": "object",
256 "title": "HTTPValidationError",
257 },
258 "Item-Input": {
259 "properties": {
260 "name": {"type": "string", "title": "Name"},
261 "description": {
262 "anyOf": [{"type": "string"}, {"type": "null"}],
263 "title": "Description",
264 },
265 "sub": {
266 "anyOf": [
267 {"$ref": "#/components/schemas/SubItem-Input"},
268 {"type": "null"},
269 ]
270 },
271 },
272 "type": "object",
273 "required": ["name"],
274 "title": "Item",
275 },
276 "Item-Output": {
277 "properties": {
278 "name": {"type": "string", "title": "Name"},
279 "description": {
280 "anyOf": [{"type": "string"}, {"type": "null"}],
281 "title": "Description",
282 },
283 "sub": {
284 "anyOf": [
285 {"$ref": "#/components/schemas/SubItem-Output"},
286 {"type": "null"},
287 ]
288 },
289 },
290 "type": "object",
291 "required": ["name", "description", "sub"],
292 "title": "Item",
293 },
294 "SubItem-Input": {
295 "properties": {
296 "subname": {"type": "string", "title": "Subname"},
297 "sub_description": {
298 "anyOf": [{"type": "string"}, {"type": "null"}],
299 "title": "Sub Description",
300 },
301 "tags": {
302 "items": {"type": "string"},
303 "type": "array",
304 "title": "Tags",
305 "default": [],
306 },
307 },
308 "type": "object",
309 "required": ["subname"],
310 "title": "SubItem",
311 },
312 "SubItem-Output": {
313 "properties": {
314 "subname": {"type": "string", "title": "Subname"},
315 "sub_description": {
316 "anyOf": [{"type": "string"}, {"type": "null"}],
317 "title": "Sub Description",
318 },
319 "tags": {
320 "items": {"type": "string"},
321 "type": "array",
322 "title": "Tags",
323 "default": [],
324 },
325 },
326 "type": "object",
327 "required": ["subname", "sub_description", "tags"],
328 "title": "SubItem",
329 },
330 "ValidationError": {
331 "properties": {
332 "loc": {
333 "items": {
334 "anyOf": [{"type": "string"}, {"type": "integer"}]
335 },
336 "type": "array",
337 "title": "Location",
338 },
339 "msg": {"type": "string", "title": "Message"},
340 "type": {"type": "string", "title": "Error Type"},
341 },
342 "type": "object",
343 "required": ["loc", "msg", "type"],
344 "title": "ValidationError",
345 },
346 }
347 },
348 }
351@needs_pydanticv2 1abcde
352def test_openapi_schema_no_separate(): 1abcde
353 client = get_app_client(separate_input_output_schemas=False) 1ACEGI
354 response = client.get("/openapi.json") 1ACEGI
355 assert response.status_code == 200, response.text 1ACEGI
356 assert response.json() == { 1ACEGI
357 "openapi": "3.1.0",
358 "info": {"title": "FastAPI", "version": "0.1.0"},
359 "paths": {
360 "/items/": {
361 "get": {
362 "summary": "Read Items",
363 "operationId": "read_items_items__get",
364 "responses": {
365 "200": {
366 "description": "Successful Response",
367 "content": {
368 "application/json": {
369 "schema": {
370 "items": {"$ref": "#/components/schemas/Item"},
371 "type": "array",
372 "title": "Response Read Items Items Get",
373 }
374 }
375 },
376 }
377 },
378 },
379 "post": {
380 "summary": "Create Item",
381 "operationId": "create_item_items__post",
382 "requestBody": {
383 "content": {
384 "application/json": {
385 "schema": {"$ref": "#/components/schemas/Item"}
386 }
387 },
388 "required": True,
389 },
390 "responses": {
391 "200": {
392 "description": "Successful Response",
393 "content": {
394 "application/json": {
395 "schema": {"$ref": "#/components/schemas/Item"}
396 }
397 },
398 },
399 "402": {
400 "description": "Payment Required",
401 "content": {
402 "application/json": {
403 "schema": {"$ref": "#/components/schemas/Item"}
404 }
405 },
406 },
407 "422": {
408 "description": "Validation Error",
409 "content": {
410 "application/json": {
411 "schema": {
412 "$ref": "#/components/schemas/HTTPValidationError"
413 }
414 }
415 },
416 },
417 },
418 },
419 },
420 "/items-list/": {
421 "post": {
422 "summary": "Create Item List",
423 "operationId": "create_item_list_items_list__post",
424 "requestBody": {
425 "content": {
426 "application/json": {
427 "schema": {
428 "items": {"$ref": "#/components/schemas/Item"},
429 "type": "array",
430 "title": "Item",
431 }
432 }
433 },
434 "required": True,
435 },
436 "responses": {
437 "200": {
438 "description": "Successful Response",
439 "content": {"application/json": {"schema": {}}},
440 },
441 "422": {
442 "description": "Validation Error",
443 "content": {
444 "application/json": {
445 "schema": {
446 "$ref": "#/components/schemas/HTTPValidationError"
447 }
448 }
449 },
450 },
451 },
452 }
453 },
454 },
455 "components": {
456 "schemas": {
457 "HTTPValidationError": {
458 "properties": {
459 "detail": {
460 "items": {"$ref": "#/components/schemas/ValidationError"},
461 "type": "array",
462 "title": "Detail",
463 }
464 },
465 "type": "object",
466 "title": "HTTPValidationError",
467 },
468 "Item": {
469 "properties": {
470 "name": {"type": "string", "title": "Name"},
471 "description": {
472 "anyOf": [{"type": "string"}, {"type": "null"}],
473 "title": "Description",
474 },
475 "sub": {
476 "anyOf": [
477 {"$ref": "#/components/schemas/SubItem"},
478 {"type": "null"},
479 ]
480 },
481 },
482 "type": "object",
483 "required": ["name"],
484 "title": "Item",
485 },
486 "SubItem": {
487 "properties": {
488 "subname": {"type": "string", "title": "Subname"},
489 "sub_description": {
490 "anyOf": [{"type": "string"}, {"type": "null"}],
491 "title": "Sub Description",
492 },
493 "tags": {
494 "items": {"type": "string"},
495 "type": "array",
496 "title": "Tags",
497 "default": [],
498 },
499 },
500 "type": "object",
501 "required": ["subname"],
502 "title": "SubItem",
503 },
504 "ValidationError": {
505 "properties": {
506 "loc": {
507 "items": {
508 "anyOf": [{"type": "string"}, {"type": "integer"}]
509 },
510 "type": "array",
511 "title": "Location",
512 },
513 "msg": {"type": "string", "title": "Message"},
514 "type": {"type": "string", "title": "Error Type"},
515 },
516 "type": "object",
517 "required": ["loc", "msg", "type"],
518 "title": "ValidationError",
519 },
520 }
521 },
522 }