Coverage for tests / test_request_params / test_body / test_list.py: 100%
136 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1from typing import Annotated 1adbc
3import pytest 1adbc
4from dirty_equals import IsOneOf, IsPartialDict 1adbc
5from fastapi import Body, FastAPI 1adbc
6from fastapi.testclient import TestClient 1adbc
7from pydantic import BaseModel, Field 1adbc
9from .utils import get_body_model_name 1adbc
11app = FastAPI() 1adbc
13# =====================================================================================
14# Without aliases
17@app.post("/required-list-str", operation_id="required_list_str") 1adbc
18async def read_required_list_str(p: Annotated[list[str], Body(embed=True)]): 1adbc
19 return {"p": p} 1efgh
22class BodyModelRequiredListStr(BaseModel): 1adbc
23 p: list[str] 1abc
26@app.post("/model-required-list-str", operation_id="model_required_list_str") 1adbc
27def read_model_required_list_str(p: BodyModelRequiredListStr): 1adbc
28 return {"p": p.p} 1ijkl
31@pytest.mark.parametrize( 1adbc
32 "path",
33 ["/required-list-str", "/model-required-list-str"],
34)
35def test_required_list_str_schema(path: str): 1adbc
36 openapi = app.openapi() 2HbIbJbKbLbMbNb
37 body_model_name = get_body_model_name(openapi, path) 2HbIbJbKbLbMbNb
39 assert app.openapi()["components"]["schemas"][body_model_name] == { 2HbIbJbKbLbMbNb
40 "properties": {
41 "p": {
42 "items": {"type": "string"},
43 "title": "P",
44 "type": "array",
45 },
46 },
47 "required": ["p"],
48 "title": body_model_name,
49 "type": "object",
50 }
53@pytest.mark.parametrize("json", [None, {}]) 1adbc
54@pytest.mark.parametrize( 1adbc
55 "path",
56 ["/required-list-str", "/model-required-list-str"],
57)
58def test_required_list_str_missing(path: str, json: dict | None): 1adbc
59 client = TestClient(app) 1KLMNOPQRSTUVWX
60 response = client.post(path, json=json) 1KLMNOPQRSTUVWX
61 assert response.status_code == 422 1KLMNOPQRSTUVWX
62 assert response.json() == { 1KLMNOPQRSTUVWX
63 "detail": [
64 {
65 "type": "missing",
66 "loc": IsOneOf(["body", "p"], ["body"]),
67 "msg": "Field required",
68 "input": IsOneOf(None, {}),
69 }
70 ]
71 }
74@pytest.mark.parametrize( 1adbc
75 "path",
76 ["/required-list-str", "/model-required-list-str"],
77)
78def test_required_list_str(path: str): 1adbc
79 client = TestClient(app) 1iejfkglh
80 response = client.post(path, json={"p": ["hello", "world"]}) 1iejfkglh
81 assert response.status_code == 200 1iejfkglh
82 assert response.json() == {"p": ["hello", "world"]} 1iejfkglh
85# =====================================================================================
86# Alias
89@app.post("/required-list-alias", operation_id="required_list_alias") 1adbc
90async def read_required_list_alias( 1adbc
91 p: Annotated[list[str], Body(embed=True, alias="p_alias")],
92):
93 return {"p": p} 1mnop
96class BodyModelRequiredListAlias(BaseModel): 1adbc
97 p: list[str] = Field(alias="p_alias") 1adbc
100@app.post("/model-required-list-alias", operation_id="model_required_list_alias") 1adbc
101async def read_model_required_list_alias(p: BodyModelRequiredListAlias): 1adbc
102 return {"p": p.p} 1qrst
105@pytest.mark.parametrize( 1adbc
106 "path",
107 [
108 "/required-list-alias",
109 "/model-required-list-alias",
110 ],
111)
112def test_required_list_str_alias_schema(path: str): 1adbc
113 openapi = app.openapi() 2ObPbQbRbSbTbUbVb
114 body_model_name = get_body_model_name(openapi, path) 2ObPbQbRbSbTbUbVb
116 assert app.openapi()["components"]["schemas"][body_model_name] == { 2ObPbQbRbSbTbUbVb
117 "properties": {
118 "p_alias": {
119 "items": {"type": "string"},
120 "title": "P Alias",
121 "type": "array",
122 },
123 },
124 "required": ["p_alias"],
125 "title": body_model_name,
126 "type": "object",
127 }
130@pytest.mark.parametrize("json", [None, {}]) 1adbc
131@pytest.mark.parametrize( 1adbc
132 "path",
133 ["/required-list-alias", "/model-required-list-alias"],
134)
135def test_required_list_alias_missing(path: str, json: dict | None): 1adbc
136 client = TestClient(app) 1YZ0123456789!#
137 response = client.post(path, json=json) 1YZ0123456789!#
138 assert response.status_code == 422 1YZ0123456789!#
139 assert response.json() == { 1YZ0123456789!#
140 "detail": [
141 {
142 "type": "missing",
143 "loc": IsOneOf(["body", "p_alias"], ["body"]),
144 "msg": "Field required",
145 "input": IsOneOf(None, {}),
146 }
147 ]
148 }
151@pytest.mark.parametrize( 1adbc
152 "path",
153 ["/required-list-alias", "/model-required-list-alias"],
154)
155def test_required_list_alias_by_name(path: str): 1adbc
156 client = TestClient(app) 1$%'()*+
157 response = client.post(path, json={"p": ["hello", "world"]}) 1$%'()*+
158 assert response.status_code == 422 1$%'()*+
159 assert response.json() == { 1$%'()*+
160 "detail": [
161 {
162 "type": "missing",
163 "loc": ["body", "p_alias"],
164 "msg": "Field required",
165 "input": IsOneOf(None, {"p": ["hello", "world"]}),
166 }
167 ]
168 }
171@pytest.mark.parametrize( 1adbc
172 "path",
173 ["/required-list-alias", "/model-required-list-alias"],
174)
175def test_required_list_alias_by_alias(path: str): 1adbc
176 client = TestClient(app) 1qmrnsotp
177 response = client.post(path, json={"p_alias": ["hello", "world"]}) 1qmrnsotp
178 assert response.status_code == 200, response.text 1qmrnsotp
179 assert response.json() == {"p": ["hello", "world"]} 1qmrnsotp
182# =====================================================================================
183# Validation alias
186@app.post( 1adbc
187 "/required-list-validation-alias", operation_id="required_list_validation_alias"
188)
189def read_required_list_validation_alias( 1adbc
190 p: Annotated[list[str], Body(embed=True, validation_alias="p_val_alias")],
191):
192 return {"p": p} 1uvwx
195class BodyModelRequiredListValidationAlias(BaseModel): 1adbc
196 p: list[str] = Field(validation_alias="p_val_alias") 1adbc
199@app.post( 1adbc
200 "/model-required-list-validation-alias",
201 operation_id="model_required_list_validation_alias",
202)
203async def read_model_required_list_validation_alias( 1adbc
204 p: BodyModelRequiredListValidationAlias,
205):
206 return {"p": p.p} 1yzAB
209@pytest.mark.parametrize( 1adbc
210 "path",
211 ["/required-list-validation-alias", "/model-required-list-validation-alias"],
212)
213def test_required_list_validation_alias_schema(path: str): 1adbc
214 openapi = app.openapi() 2WbXbYbZb0b1b2b3b
215 body_model_name = get_body_model_name(openapi, path) 2WbXbYbZb0b1b2b3b
217 assert app.openapi()["components"]["schemas"][body_model_name] == { 2WbXbYbZb0b1b2b3b
218 "properties": {
219 "p_val_alias": {
220 "items": {"type": "string"},
221 "title": "P Val Alias",
222 "type": "array",
223 },
224 },
225 "required": ["p_val_alias"],
226 "title": body_model_name,
227 "type": "object",
228 }
231@pytest.mark.parametrize("json", [None, {}]) 1adbc
232@pytest.mark.parametrize( 1adbc
233 "path",
234 [
235 "/required-list-validation-alias",
236 "/model-required-list-validation-alias",
237 ],
238)
239def test_required_list_validation_alias_missing(path: str, json: dict | None): 1adbc
240 client = TestClient(app) 1,-./:;=?@[]^_`
241 response = client.post(path, json=json) 1,-./:;=?@[]^_`
242 assert response.status_code == 422 1,-./:;=?@[]^_`
243 assert response.json() == { 1,-./:;=?@[]^_`
244 "detail": [
245 {
246 "type": "missing",
247 "loc": IsOneOf(["body"], ["body", "p_val_alias"]),
248 "msg": "Field required",
249 "input": IsOneOf(None, {}),
250 }
251 ]
252 }
255@pytest.mark.parametrize( 1adbc
256 "path",
257 [
258 "/required-list-validation-alias",
259 "/model-required-list-validation-alias",
260 ],
261)
262def test_required_list_validation_alias_by_name(path: str): 1adbc
263 client = TestClient(app) 2{ | } ~ abbbcb
264 response = client.post(path, json={"p": ["hello", "world"]}) 2{ | } ~ abbbcb
265 assert response.status_code == 422, response.text 2{ | } ~ abbbcb
267 assert response.json() == { 2{ | } ~ abbbcb
268 "detail": [
269 {
270 "type": "missing",
271 "loc": ["body", "p_val_alias"],
272 "msg": "Field required",
273 "input": IsOneOf(None, IsPartialDict({"p": ["hello", "world"]})),
274 }
275 ]
276 }
279@pytest.mark.parametrize( 1adbc
280 "path",
281 [
282 "/required-list-validation-alias",
283 "/model-required-list-validation-alias",
284 ],
285)
286def test_required_list_validation_alias_by_validation_alias(path: str): 1adbc
287 client = TestClient(app) 1yuzvAwBx
288 response = client.post(path, json={"p_val_alias": ["hello", "world"]}) 1yuzvAwBx
289 assert response.status_code == 200, response.text 1yuzvAwBx
290 assert response.json() == {"p": ["hello", "world"]} 1yuzvAwBx
293# =====================================================================================
294# Alias and validation alias
297@app.post( 1adbc
298 "/required-list-alias-and-validation-alias",
299 operation_id="required_list_alias_and_validation_alias",
300)
301def read_required_list_alias_and_validation_alias( 1adbc
302 p: Annotated[
303 list[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
304 ],
305):
306 return {"p": p} 1CDEF
309class BodyModelRequiredListAliasAndValidationAlias(BaseModel): 1adbc
310 p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias") 1adbc
313@app.post( 1adbc
314 "/model-required-list-alias-and-validation-alias",
315 operation_id="model_required_list_alias_and_validation_alias",
316)
317def read_model_required_list_alias_and_validation_alias( 1adbc
318 p: BodyModelRequiredListAliasAndValidationAlias,
319):
320 return {"p": p.p} 1GHIJ
323@pytest.mark.parametrize( 1adbc
324 "path",
325 [
326 "/required-list-alias-and-validation-alias",
327 "/model-required-list-alias-and-validation-alias",
328 ],
329)
330def test_required_list_alias_and_validation_alias_schema(path: str): 1adbc
331 openapi = app.openapi() 24b5b6b7b8b9b!b#b
332 body_model_name = get_body_model_name(openapi, path) 24b5b6b7b8b9b!b#b
334 assert app.openapi()["components"]["schemas"][body_model_name] == { 24b5b6b7b8b9b!b#b
335 "properties": {
336 "p_val_alias": {
337 "items": {"type": "string"},
338 "title": "P Val Alias",
339 "type": "array",
340 },
341 },
342 "required": ["p_val_alias"],
343 "title": body_model_name,
344 "type": "object",
345 }
348@pytest.mark.parametrize("json", [None, {}]) 1adbc
349@pytest.mark.parametrize( 1adbc
350 "path",
351 [
352 "/required-list-alias-and-validation-alias",
353 "/model-required-list-alias-and-validation-alias",
354 ],
355)
356def test_required_list_alias_and_validation_alias_missing(path: str, json): 1adbc
357 client = TestClient(app) 2dbebfbgbhbibjbkblbmbnbobpbqb
358 response = client.post(path, json=json) 2dbebfbgbhbibjbkblbmbnbobpbqb
359 assert response.status_code == 422 2dbebfbgbhbibjbkblbmbnbobpbqb
360 assert response.json() == { 2dbebfbgbhbibjbkblbmbnbobpbqb
361 "detail": [
362 {
363 "type": "missing",
364 "loc": IsOneOf(["body"], ["body", "p_val_alias"]),
365 "msg": "Field required",
366 "input": IsOneOf(None, {}),
367 }
368 ]
369 }
372@pytest.mark.parametrize( 1adbc
373 "path",
374 [
375 "/required-list-alias-and-validation-alias",
376 "/model-required-list-alias-and-validation-alias",
377 ],
378)
379def test_required_list_alias_and_validation_alias_by_name(path: str): 1adbc
380 client = TestClient(app) 2rbsbtbubvbwbxbyb
381 response = client.post(path, json={"p": ["hello", "world"]}) 2rbsbtbubvbwbxbyb
382 assert response.status_code == 422 2rbsbtbubvbwbxbyb
383 assert response.json() == { 2rbsbtbubvbwbxbyb
384 "detail": [
385 {
386 "type": "missing",
387 "loc": [
388 "body",
389 "p_val_alias",
390 ],
391 "msg": "Field required",
392 "input": IsOneOf(None, {"p": ["hello", "world"]}),
393 }
394 ]
395 }
398@pytest.mark.parametrize( 1adbc
399 "path",
400 [
401 "/required-list-alias-and-validation-alias",
402 "/model-required-list-alias-and-validation-alias",
403 ],
404)
405def test_required_list_alias_and_validation_alias_by_alias(path: str): 1adbc
406 client = TestClient(app) 2zbAbBbCbDbEbFbGb
407 response = client.post(path, json={"p_alias": ["hello", "world"]}) 2zbAbBbCbDbEbFbGb
408 assert response.status_code == 422, response.text 2zbAbBbCbDbEbFbGb
410 assert response.json() == { 2zbAbBbCbDbEbFbGb
411 "detail": [
412 {
413 "type": "missing",
414 "loc": ["body", "p_val_alias"],
415 "msg": "Field required",
416 "input": IsOneOf(None, {"p_alias": ["hello", "world"]}),
417 }
418 ]
419 }
422@pytest.mark.parametrize( 1adbc
423 "path",
424 [
425 "/required-list-alias-and-validation-alias",
426 "/model-required-list-alias-and-validation-alias",
427 ],
428)
429def test_required_list_alias_and_validation_alias_by_validation_alias(path: str): 1adbc
430 client = TestClient(app) 1GCHDIEJF
431 response = client.post(path, json={"p_val_alias": ["hello", "world"]}) 1GCHDIEJF
432 assert response.status_code == 200, response.text 1GCHDIEJF
433 assert response.json() == {"p": ["hello", "world"]} 1GCHDIEJF