Coverage for tests / test_request_params / test_query / test_optional_list.py: 100%
123 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 1abcd
3import pytest 1abcd
4from fastapi import FastAPI, Query 1abcd
5from fastapi.testclient import TestClient 1abcd
6from inline_snapshot import snapshot 1abcd
7from pydantic import BaseModel, Field 1abcd
9app = FastAPI() 1abcd
11# =====================================================================================
12# Without aliases
15@app.get("/optional-list-str") 1abcd
16async def read_optional_list_str( 1abcd
17 p: Annotated[list[str] | None, Query()] = None,
18):
19 return {"p": p} 1efghijk
22class QueryModelOptionalListStr(BaseModel): 1abcd
23 p: list[str] | None = None 1abcd
26@app.get("/model-optional-list-str") 1abcd
27async def read_model_optional_list_str( 1abcd
28 p: Annotated[QueryModelOptionalListStr, Query()],
29):
30 return {"p": p.p} 1lmnopqr
33@pytest.mark.parametrize( 1abcd
34 "path",
35 ["/optional-list-str", "/model-optional-list-str"],
36)
37def test_optional_list_str_schema(path: str): 1abcd
38 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2lbmbnbobpbqbrbsb
39 [
40 {
41 "required": False,
42 "schema": {
43 "anyOf": [
44 {"items": {"type": "string"}, "type": "array"},
45 {"type": "null"},
46 ],
47 "title": "P",
48 },
49 "name": "p",
50 "in": "query",
51 }
52 ]
53 )
56@pytest.mark.parametrize( 1abcd
57 "path",
58 ["/optional-list-str", "/model-optional-list-str"],
59)
60def test_optional_list_str_missing(path: str): 1abcd
61 client = TestClient(app) 1mfngpirk
62 response = client.get(path) 1mfngpirk
63 assert response.status_code == 200, response.text 1mfngpirk
64 assert response.json() == {"p": None} 1mfngpirk
67@pytest.mark.parametrize( 1abcd
68 "path",
69 ["/optional-list-str", "/model-optional-list-str"],
70)
71def test_optional_list_str(path: str): 1abcd
72 client = TestClient(app) 1le|}ohqj
73 response = client.get(f"{path}?p=hello&p=world") 1le|}ohqj
74 assert response.status_code == 200 1le|}ohqj
75 assert response.json() == {"p": ["hello", "world"]} 1le|}ohqj
78# =====================================================================================
79# Alias
82@app.get("/optional-list-alias") 1abcd
83async def read_optional_list_alias( 1abcd
84 p: Annotated[list[str] | None, Query(alias="p_alias")] = None,
85):
86 return {"p": p} 1stuvwxyzAB
89class QueryModelOptionalListAlias(BaseModel): 1abcd
90 p: list[str] | None = Field(None, alias="p_alias") 1abcd
93@app.get("/model-optional-list-alias") 1abcd
94async def read_model_optional_list_alias( 1abcd
95 p: Annotated[QueryModelOptionalListAlias, Query()],
96):
97 return {"p": p.p} 1CDEFGHIJKL
100@pytest.mark.parametrize( 1abcd
101 "path",
102 ["/optional-list-alias", "/model-optional-list-alias"],
103)
104def test_optional_list_str_alias_schema(path: str): 1abcd
105 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2tbubvbwbxbybzbAb
106 [
107 {
108 "required": False,
109 "schema": {
110 "anyOf": [
111 {"items": {"type": "string"}, "type": "array"},
112 {"type": "null"},
113 ],
114 "title": "P Alias",
115 },
116 "name": "p_alias",
117 "in": "query",
118 }
119 ]
120 )
123@pytest.mark.parametrize( 1abcd
124 "path",
125 ["/optional-list-alias", "/model-optional-list-alias"],
126)
127def test_optional_list_alias_missing(path: str): 1abcd
128 client = TestClient(app) 1EuFvIyLB
129 response = client.get(path) 1EuFvIyLB
130 assert response.status_code == 200 1EuFvIyLB
131 assert response.json() == {"p": None} 1EuFvIyLB
134@pytest.mark.parametrize( 1abcd
135 "path",
136 ["/optional-list-alias", "/model-optional-list-alias"],
137)
138def test_optional_list_alias_by_name(path: str): 1abcd
139 client = TestClient(app) 2D t ~ abH x K A
140 response = client.get(f"{path}?p=hello&p=world") 2D t ~ abH x K A
141 assert response.status_code == 200 2D t ~ abH x K A
142 assert response.json() == {"p": None} 2D t ~ abH x K A
145@pytest.mark.parametrize( 1abcd
146 "path",
147 [
148 "/optional-list-alias",
149 "/model-optional-list-alias",
150 ],
151)
152def test_optional_list_alias_by_alias(path: str): 1abcd
153 client = TestClient(app) 2C s bbcbG w J z
154 response = client.get(f"{path}?p_alias=hello&p_alias=world") 2C s bbcbG w J z
155 assert response.status_code == 200 2C s bbcbG w J z
156 assert response.json() == {"p": ["hello", "world"]} 2C s bbcbG w J z
159# =====================================================================================
160# Validation alias
163@app.get("/optional-list-validation-alias") 1abcd
164def read_optional_list_validation_alias( 1abcd
165 p: Annotated[list[str] | None, Query(validation_alias="p_val_alias")] = None,
166):
167 return {"p": p} 1MNOPQRSTUVW
170class QueryModelOptionalListValidationAlias(BaseModel): 1abcd
171 p: list[str] | None = Field(None, validation_alias="p_val_alias") 1abcd
174@app.get("/model-optional-list-validation-alias") 1abcd
175def read_model_optional_list_validation_alias( 1abcd
176 p: Annotated[QueryModelOptionalListValidationAlias, Query()],
177):
178 return {"p": p.p} 1XYZ01234567
181@pytest.mark.parametrize( 1abcd
182 "path",
183 ["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
184)
185def test_optional_list_validation_alias_schema(path: str): 1abcd
186 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2BbCbDbEbFbGbHb
187 [
188 {
189 "required": False,
190 "schema": {
191 "anyOf": [
192 {"items": {"type": "string"}, "type": "array"},
193 {"type": "null"},
194 ],
195 "title": "P Val Alias",
196 },
197 "name": "p_val_alias",
198 "in": "query",
199 }
200 ]
201 )
204@pytest.mark.parametrize( 1abcd
205 "path",
206 ["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
207)
208def test_optional_list_validation_alias_missing(path: str): 1abcd
209 client = TestClient(app) 1ZO1Q4T7W
210 response = client.get(path) 1ZO1Q4T7W
211 assert response.status_code == 200 1ZO1Q4T7W
212 assert response.json() == {"p": None} 1ZO1Q4T7W
215@pytest.mark.parametrize( 1abcd
216 "path",
217 [
218 "/optional-list-validation-alias",
219 "/model-optional-list-validation-alias",
220 ],
221)
222def test_optional_list_validation_alias_by_name(path: str): 1abcd
223 client = TestClient(app) 2X M dbeb2 R 5 U
224 response = client.get(f"{path}?p=hello&p=world") 2X M dbeb2 R 5 U
225 assert response.status_code == 200 2X M dbeb2 R 5 U
226 assert response.json() == {"p": None} 2X M dbeb2 R 5 U
229@pytest.mark.parametrize( 1abcd
230 "path",
231 ["/optional-list-validation-alias", "/model-optional-list-validation-alias"],
232)
233def test_optional_list_validation_alias_by_validation_alias(path: str): 1abcd
234 client = TestClient(app) 1YN0P3S6V
235 response = client.get(f"{path}?p_val_alias=hello&p_val_alias=world") 1YN0P3S6V
236 assert response.status_code == 200, response.text 1YN0P3S6V
237 assert response.json() == {"p": ["hello", "world"]} 1YN0P3S6V
240# =====================================================================================
241# Alias and validation alias
244@app.get("/optional-list-alias-and-validation-alias") 1abcd
245def read_optional_list_alias_and_validation_alias( 1abcd
246 p: Annotated[
247 list[str] | None, Query(alias="p_alias", validation_alias="p_val_alias")
248 ] = None,
249):
250 return {"p": p} 189!#$%'()*+,-
253class QueryModelOptionalListAliasAndValidationAlias(BaseModel): 1abcd
254 p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias") 1abcd
257@app.get("/model-optional-list-alias-and-validation-alias") 1abcd
258def read_model_optional_list_alias_and_validation_alias( 1abcd
259 p: Annotated[QueryModelOptionalListAliasAndValidationAlias, Query()],
260):
261 return {"p": p.p} 1./:;=?@[]^_`{
264@pytest.mark.parametrize( 1abcd
265 "path",
266 [
267 "/optional-list-alias-and-validation-alias",
268 "/model-optional-list-alias-and-validation-alias",
269 ],
270)
271def test_optional_list_alias_and_validation_alias_schema(path: str): 1abcd
272 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2IbJbKbLbMbNbObPb
273 [
274 {
275 "required": False,
276 "schema": {
277 "anyOf": [
278 {"items": {"type": "string"}, "type": "array"},
279 {"type": "null"},
280 ],
281 "title": "P Val Alias",
282 },
283 "name": "p_val_alias",
284 "in": "query",
285 }
286 ]
287 )
290@pytest.mark.parametrize( 1abcd
291 "path",
292 [
293 "/optional-list-alias-and-validation-alias",
294 "/model-optional-list-alias-and-validation-alias",
295 ],
296)
297def test_optional_list_alias_and_validation_alias_missing(path: str): 1abcd
298 client = TestClient(app) 1;#=$]){-
299 response = client.get(path) 1;#=$]){-
300 assert response.status_code == 200 1;#=$]){-
301 assert response.json() == {"p": None} 1;#=$]){-
304@pytest.mark.parametrize( 1abcd
305 "path",
306 [
307 "/optional-list-alias-and-validation-alias",
308 "/model-optional-list-alias-and-validation-alias",
309 ],
310)
311def test_optional_list_alias_and_validation_alias_by_name(path: str): 1abcd
312 client = TestClient(app) 2/ 9 fbgb@ ' _ +
313 response = client.get(f"{path}?p=hello&p=world") 2/ 9 fbgb@ ' _ +
314 assert response.status_code == 200 2/ 9 fbgb@ ' _ +
315 assert response.json() == {"p": None} 2/ 9 fbgb@ ' _ +
318@pytest.mark.parametrize( 1abcd
319 "path",
320 [
321 "/optional-list-alias-and-validation-alias",
322 "/model-optional-list-alias-and-validation-alias",
323 ],
324)
325def test_optional_list_alias_and_validation_alias_by_alias(path: str): 1abcd
326 client = TestClient(app) 2. 8 hbib? % ^ *
327 response = client.get(f"{path}?p_alias=hello&p_alias=world") 2. 8 hbib? % ^ *
328 assert response.status_code == 200 2. 8 hbib? % ^ *
329 assert response.json() == {"p": None} 2. 8 hbib? % ^ *
332@pytest.mark.parametrize( 1abcd
333 "path",
334 [
335 "/optional-list-alias-and-validation-alias",
336 "/model-optional-list-alias-and-validation-alias",
337 ],
338)
339def test_optional_list_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
340 client = TestClient(app) 2: ! jbkb[ ( ` ,
341 response = client.get(f"{path}?p_val_alias=hello&p_val_alias=world") 2: ! jbkb[ ( ` ,
342 assert response.status_code == 200, response.text 2: ! jbkb[ ( ` ,
343 assert response.json() == { 2: ! jbkb[ ( ` ,
344 "p": [
345 "hello",
346 "world",
347 ]
348 }