Coverage for tests / test_request_params / test_header / 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, Header 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, Header()] = None,
18):
19 return {"p": p} 1efghijkl
22class HeaderModelOptionalListStr(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[HeaderModelOptionalListStr, Header()],
29):
30 return {"p": p.p} 1mnopqrst
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( 2kblbmbnbobpbqbrb
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": "header",
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) 1nfphrjtl
62 response = client.get(path) 1nfphrjtl
63 assert response.status_code == 200, response.text 1nfphrjtl
64 assert response.json() == {"p": None} 1nfphrjtl
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) 1meogqisk
73 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1meogqisk
74 assert response.status_code == 200 1meogqisk
75 assert response.json() == {"p": ["hello", "world"]} 1meogqisk
78# =====================================================================================
79# Alias
82@app.get("/optional-list-alias") 1abcd
83async def read_optional_list_alias( 1abcd
84 p: Annotated[list[str] | None, Header(alias="p_alias")] = None,
85):
86 return {"p": p} 1uvwxyzABCDE
89class HeaderModelOptionalListAlias(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[HeaderModelOptionalListAlias, Header()],
96):
97 return {"p": p.p} 1FGHIJKLMNOP
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( 2sbtbubvbwbxbybzb
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": "header",
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) 1HwJyMBPE
129 response = client.get(path) 1HwJyMBPE
130 assert response.status_code == 200 1HwJyMBPE
131 assert response.json() == {"p": None} 1HwJyMBPE
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) 2G v abbbL A O D
140 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 2G v abbbL A O D
141 assert response.status_code == 200 2G v abbbL A O D
142 assert response.json() == {"p": None} 2G v abbbL A O D
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) 1FuIxKzNC
154 response = client.get(path, headers=[("p_alias", "hello"), ("p_alias", "world")]) 1FuIxKzNC
155 assert response.status_code == 200 1FuIxKzNC
156 assert response.json() == {"p": ["hello", "world"]} 1FuIxKzNC
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, Header(validation_alias="p_val_alias")] = None,
166):
167 return {"p": p} 1QRSTUVWXYZ0
170class HeaderModelOptionalListValidationAlias(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[HeaderModelOptionalListValidationAlias, Header()],
177):
178 return {"p": p.p} 21 2 3 Ab4 5 6 7 8 9 !
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( 2BbCbDbEbFbGbHbIb
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": "header",
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) 13S4U7X!0
210 response = client.get(path) 13S4U7X!0
211 assert response.status_code == 200 13S4U7X!0
212 assert response.json() == {"p": None} 13S4U7X!0
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) 21 Q cb5 V 8 Y
224 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 21 Q cb5 V 8 Y
225 assert response.status_code == 200 21 Q cb5 V 8 Y
226 assert response.json() == {"p": None} 21 Q cb5 V 8 Y
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) 22 R dbT 6 W 9 Z
235 response = client.get( 22 R dbT 6 W 9 Z
236 path, headers=[("p_val_alias", "hello"), ("p_val_alias", "world")]
237 )
238 assert response.status_code == 200, response.text 22 R dbT 6 W 9 Z
239 assert response.json() == {"p": ["hello", "world"]} 22 R dbT 6 W 9 Z
242# =====================================================================================
243# Alias and validation alias
246@app.get("/optional-list-alias-and-validation-alias") 1abcd
247def read_optional_list_alias_and_validation_alias( 1abcd
248 p: Annotated[
249 list[str] | None, Header(alias="p_alias", validation_alias="p_val_alias")
250 ] = None,
251):
252 return {"p": p} 1#$%'()*+,-./:
255class HeaderModelOptionalListAliasAndValidationAlias(BaseModel): 1abcd
256 p: list[str] | None = Field(None, alias="p_alias", validation_alias="p_val_alias") 1abcd
259@app.get("/model-optional-list-alias-and-validation-alias") 1abcd
260def read_model_optional_list_alias_and_validation_alias( 1abcd
261 p: Annotated[HeaderModelOptionalListAliasAndValidationAlias, Header()],
262):
263 return {"p": p.p} 1;=?@[]^_`{|}~
266@pytest.mark.parametrize( 1abcd
267 "path",
268 [
269 "/optional-list-alias-and-validation-alias",
270 "/model-optional-list-alias-and-validation-alias",
271 ],
272)
273def test_optional_list_alias_and_validation_alias_schema(path: str): 1abcd
274 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2JbKbLbMbNbObPbQb
275 [
276 {
277 "required": False,
278 "schema": {
279 "anyOf": [
280 {"items": {"type": "string"}, "type": "array"},
281 {"type": "null"},
282 ],
283 "title": "P Val Alias",
284 },
285 "name": "p_val_alias",
286 "in": "header",
287 }
288 ]
289 )
292@pytest.mark.parametrize( 1abcd
293 "path",
294 [
295 "/optional-list-alias-and-validation-alias",
296 "/model-optional-list-alias-and-validation-alias",
297 ],
298)
299def test_optional_list_alias_and_validation_alias_missing(path: str): 1abcd
300 client = TestClient(app) 1@'[(`,~:
301 response = client.get(path) 1@'[(`,~:
302 assert response.status_code == 200 1@'[(`,~:
303 assert response.json() == {"p": None} 1@'[(`,~:
306@pytest.mark.parametrize( 1abcd
307 "path",
308 [
309 "/optional-list-alias-and-validation-alias",
310 "/model-optional-list-alias-and-validation-alias",
311 ],
312)
313def test_optional_list_alias_and_validation_alias_by_name(path: str): 1abcd
314 client = TestClient(app) 2= $ ebfb^ * | .
315 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 2= $ ebfb^ * | .
316 assert response.status_code == 200 2= $ ebfb^ * | .
317 assert response.json() == {"p": None} 2= $ ebfb^ * | .
320@pytest.mark.parametrize( 1abcd
321 "path",
322 [
323 "/optional-list-alias-and-validation-alias",
324 "/model-optional-list-alias-and-validation-alias",
325 ],
326)
327def test_optional_list_alias_and_validation_alias_by_alias(path: str): 1abcd
328 client = TestClient(app) 2; # gbhb] ) { -
329 response = client.get(path, headers=[("p_alias", "hello"), ("p_alias", "world")]) 2; # gbhb] ) { -
330 assert response.status_code == 200 2; # gbhb] ) { -
331 assert response.json() == {"p": None} 2; # gbhb] ) { -
334@pytest.mark.parametrize( 1abcd
335 "path",
336 [
337 "/optional-list-alias-and-validation-alias",
338 "/model-optional-list-alias-and-validation-alias",
339 ],
340)
341def test_optional_list_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
342 client = TestClient(app) 2? % ibjb_ + } /
343 response = client.get( 2? % ibjb_ + } /
344 path, headers=[("p_val_alias", "hello"), ("p_val_alias", "world")]
345 )
346 assert response.status_code == 200, response.text 2? % ibjb_ + } /
347 assert response.json() == { 2? % ibjb_ + } /
348 "p": [
349 "hello",
350 "world",
351 ]
352 }