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-02-12 18:15 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
1from typing import Annotated, Optional 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[Optional[list[str]], Header()] = None,
18):
19 return {"p": p} 1efghij
22class HeaderModelOptionalListStr(BaseModel): 1abcd
23 p: Optional[list[str]] = 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} 1efghij
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( 1OPQ
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) 1fhj
62 response = client.get(path) 1fhj
63 assert response.status_code == 200, response.text 1fhj
64 assert response.json() == {"p": None} 1fhj
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) 1egi
73 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1egi
74 assert response.status_code == 200 1egi
75 assert response.json() == {"p": ["hello", "world"]} 1egi
78# =====================================================================================
79# Alias
82@app.get("/optional-list-alias") 1abcd
83async def read_optional_list_alias( 1abcd
84 p: Annotated[Optional[list[str]], Header(alias="p_alias")] = None,
85):
86 return {"p": p} 1klmnopqrs
89class HeaderModelOptionalListAlias(BaseModel): 1abcd
90 p: Optional[list[str]] = 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} 1klmnopqrs
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( 1RST
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) 1mps
129 response = client.get(path) 1mps
130 assert response.status_code == 200 1mps
131 assert response.json() == {"p": None} 1mps
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) 1lor
140 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1lor
141 assert response.status_code == 200 1lor
142 assert response.json() == {"p": None} 1lor
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) 1knq
154 response = client.get(path, headers=[("p_alias", "hello"), ("p_alias", "world")]) 1knq
155 assert response.status_code == 200 1knq
156 assert response.json() == {"p": ["hello", "world"]} 1knq
159# =====================================================================================
160# Validation alias
163@app.get("/optional-list-validation-alias") 1abcd
164def read_optional_list_validation_alias( 1abcd
165 p: Annotated[Optional[list[str]], Header(validation_alias="p_val_alias")] = None,
166):
167 return {"p": p} 1tuvwxyzAB
170class HeaderModelOptionalListValidationAlias(BaseModel): 1abcd
171 p: Optional[list[str]] = 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} 1tuvwxyzAB
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( 1UVW
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) 1vyB
210 response = client.get(path) 1vyB
211 assert response.status_code == 200 1vyB
212 assert response.json() == {"p": None} 1vyB
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) 1twz
224 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1twz
225 assert response.status_code == 200 1twz
226 assert response.json() == {"p": None} 1twz
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) 1uxA
235 response = client.get( 1uxA
236 path, headers=[("p_val_alias", "hello"), ("p_val_alias", "world")]
237 )
238 assert response.status_code == 200, response.text 1uxA
239 assert response.json() == {"p": ["hello", "world"]} 1uxA
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 Optional[list[str]], Header(alias="p_alias", validation_alias="p_val_alias")
250 ] = None,
251):
252 return {"p": p} 1CDEFGHIJKLMN
255class HeaderModelOptionalListAliasAndValidationAlias(BaseModel): 1abcd
256 p: Optional[list[str]] = Field( 1abcd
257 None, alias="p_alias", validation_alias="p_val_alias"
258 )
261@app.get("/model-optional-list-alias-and-validation-alias") 1abcd
262def read_model_optional_list_alias_and_validation_alias( 1abcd
263 p: Annotated[HeaderModelOptionalListAliasAndValidationAlias, Header()],
264):
265 return {"p": p.p} 1CDEFGHIJKLMN
268@pytest.mark.parametrize( 1abcd
269 "path",
270 [
271 "/optional-list-alias-and-validation-alias",
272 "/model-optional-list-alias-and-validation-alias",
273 ],
274)
275def test_optional_list_alias_and_validation_alias_schema(path: str): 1abcd
276 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1XYZ
277 [
278 {
279 "required": False,
280 "schema": {
281 "anyOf": [
282 {"items": {"type": "string"}, "type": "array"},
283 {"type": "null"},
284 ],
285 "title": "P Val Alias",
286 },
287 "name": "p_val_alias",
288 "in": "header",
289 }
290 ]
291 )
294@pytest.mark.parametrize( 1abcd
295 "path",
296 [
297 "/optional-list-alias-and-validation-alias",
298 "/model-optional-list-alias-and-validation-alias",
299 ],
300)
301def test_optional_list_alias_and_validation_alias_missing(path: str): 1abcd
302 client = TestClient(app) 1FJN
303 response = client.get(path) 1FJN
304 assert response.status_code == 200 1FJN
305 assert response.json() == {"p": None} 1FJN
308@pytest.mark.parametrize( 1abcd
309 "path",
310 [
311 "/optional-list-alias-and-validation-alias",
312 "/model-optional-list-alias-and-validation-alias",
313 ],
314)
315def test_optional_list_alias_and_validation_alias_by_name(path: str): 1abcd
316 client = TestClient(app) 1DHL
317 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1DHL
318 assert response.status_code == 200 1DHL
319 assert response.json() == {"p": None} 1DHL
322@pytest.mark.parametrize( 1abcd
323 "path",
324 [
325 "/optional-list-alias-and-validation-alias",
326 "/model-optional-list-alias-and-validation-alias",
327 ],
328)
329def test_optional_list_alias_and_validation_alias_by_alias(path: str): 1abcd
330 client = TestClient(app) 1CGK
331 response = client.get(path, headers=[("p_alias", "hello"), ("p_alias", "world")]) 1CGK
332 assert response.status_code == 200 1CGK
333 assert response.json() == {"p": None} 1CGK
336@pytest.mark.parametrize( 1abcd
337 "path",
338 [
339 "/optional-list-alias-and-validation-alias",
340 "/model-optional-list-alias-and-validation-alias",
341 ],
342)
343def test_optional_list_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
344 client = TestClient(app) 1EIM
345 response = client.get( 1EIM
346 path, headers=[("p_val_alias", "hello"), ("p_val_alias", "world")]
347 )
348 assert response.status_code == 200, response.text 1EIM
349 assert response.json() == { 1EIM
350 "p": [
351 "hello",
352 "world",
353 ]
354 }