Coverage for tests / test_request_params / test_header / test_required_str.py: 100%
124 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 1abcd
3import pytest 1abcd
4from dirty_equals import AnyThing, IsOneOf, IsPartialDict 1abcd
5from fastapi import FastAPI, Header 1abcd
6from fastapi.testclient import TestClient 1abcd
7from inline_snapshot import snapshot 1abcd
8from pydantic import BaseModel, Field 1abcd
10app = FastAPI() 1abcd
12# =====================================================================================
13# Without aliases
16@app.get("/required-str") 1abcd
17async def read_required_str(p: Annotated[str, Header()]): 1abcd
18 return {"p": p} 1efg
21class HeaderModelRequiredStr(BaseModel): 1abcd
22 p: str 1abcd
25@app.get("/model-required-str") 1abcd
26async def read_model_required_str(p: Annotated[HeaderModelRequiredStr, Header()]): 1abcd
27 return {"p": p.p} 1efg
30@pytest.mark.parametrize( 1abcd
31 "path",
32 ["/required-str", "/model-required-str"],
33)
34def test_required_str_schema(path: str): 1abcd
35 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1OPQ
36 [
37 {
38 "required": True,
39 "schema": {"title": "P", "type": "string"},
40 "name": "p",
41 "in": "header",
42 }
43 ]
44 )
47@pytest.mark.parametrize( 1abcd
48 "path",
49 ["/required-str", "/model-required-str"],
50)
51def test_required_str_missing(path: str): 1abcd
52 client = TestClient(app) 1qrs
53 response = client.get(path) 1qrs
54 assert response.status_code == 422 1qrs
55 assert response.json() == { 1qrs
56 "detail": [
57 {
58 "type": "missing",
59 "loc": ["header", "p"],
60 "msg": "Field required",
61 "input": AnyThing,
62 }
63 ]
64 }
67@pytest.mark.parametrize( 1abcd
68 "path",
69 ["/required-str", "/model-required-str"],
70)
71def test_required_str(path: str): 1abcd
72 client = TestClient(app) 1efg
73 response = client.get(path, headers={"p": "hello"}) 1efg
74 assert response.status_code == 200 1efg
75 assert response.json() == {"p": "hello"} 1efg
78# =====================================================================================
79# Alias
82@app.get("/required-alias") 1abcd
83async def read_required_alias(p: Annotated[str, Header(alias="p_alias")]): 1abcd
84 return {"p": p} 1hij
87class HeaderModelRequiredAlias(BaseModel): 1abcd
88 p: str = Field(alias="p_alias") 1abcd
91@app.get("/model-required-alias") 1abcd
92async def read_model_required_alias(p: Annotated[HeaderModelRequiredAlias, Header()]): 1abcd
93 return {"p": p.p} 1hij
96@pytest.mark.parametrize( 1abcd
97 "path",
98 ["/required-alias", "/model-required-alias"],
99)
100def test_required_str_alias_schema(path: str): 1abcd
101 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1RST
102 [
103 {
104 "required": True,
105 "schema": {"title": "P Alias", "type": "string"},
106 "name": "p_alias",
107 "in": "header",
108 }
109 ]
110 )
113@pytest.mark.parametrize( 1abcd
114 "path",
115 ["/required-alias", "/model-required-alias"],
116)
117def test_required_alias_missing(path: str): 1abcd
118 client = TestClient(app) 1tuv
119 response = client.get(path) 1tuv
120 assert response.status_code == 422 1tuv
121 assert response.json() == { 1tuv
122 "detail": [
123 {
124 "type": "missing",
125 "loc": ["header", "p_alias"],
126 "msg": "Field required",
127 "input": AnyThing,
128 }
129 ]
130 }
133@pytest.mark.parametrize( 1abcd
134 "path",
135 [
136 "/required-alias",
137 "/model-required-alias",
138 ],
139)
140def test_required_alias_by_name(path: str): 1abcd
141 client = TestClient(app) 1wxy
142 response = client.get(path, headers={"p": "hello"}) 1wxy
143 assert response.status_code == 422 1wxy
144 assert response.json() == { 1wxy
145 "detail": [
146 {
147 "type": "missing",
148 "loc": ["header", "p_alias"],
149 "msg": "Field required",
150 "input": IsOneOf(None, IsPartialDict({"p": "hello"})),
151 }
152 ]
153 }
156@pytest.mark.parametrize( 1abcd
157 "path",
158 [
159 "/required-alias",
160 "/model-required-alias",
161 ],
162)
163def test_required_alias_by_alias(path: str): 1abcd
164 client = TestClient(app) 1hij
165 response = client.get(path, headers={"p_alias": "hello"}) 1hij
166 assert response.status_code == 200, response.text 1hij
167 assert response.json() == {"p": "hello"} 1hij
170# =====================================================================================
171# Validation alias
174@app.get("/required-validation-alias") 1abcd
175def read_required_validation_alias( 1abcd
176 p: Annotated[str, Header(validation_alias="p_val_alias")],
177):
178 return {"p": p} 1klm
181class HeaderModelRequiredValidationAlias(BaseModel): 1abcd
182 p: str = Field(validation_alias="p_val_alias") 1abcd
185@app.get("/model-required-validation-alias") 1abcd
186def read_model_required_validation_alias( 1abcd
187 p: Annotated[HeaderModelRequiredValidationAlias, Header()],
188):
189 return {"p": p.p} 1klm
192@pytest.mark.parametrize( 1abcd
193 "path",
194 ["/required-validation-alias", "/model-required-validation-alias"],
195)
196def test_required_validation_alias_schema(path: str): 1abcd
197 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1UVW
198 [
199 {
200 "required": True,
201 "schema": {"title": "P Val Alias", "type": "string"},
202 "name": "p_val_alias",
203 "in": "header",
204 }
205 ]
206 )
209@pytest.mark.parametrize( 1abcd
210 "path",
211 [
212 "/required-validation-alias",
213 "/model-required-validation-alias",
214 ],
215)
216def test_required_validation_alias_missing(path: str): 1abcd
217 client = TestClient(app) 1zAB
218 response = client.get(path) 1zAB
219 assert response.status_code == 422 1zAB
220 assert response.json() == { 1zAB
221 "detail": [
222 {
223 "type": "missing",
224 "loc": [
225 "header",
226 "p_val_alias",
227 ],
228 "msg": "Field required",
229 "input": AnyThing,
230 }
231 ]
232 }
235@pytest.mark.parametrize( 1abcd
236 "path",
237 [
238 "/required-validation-alias",
239 "/model-required-validation-alias",
240 ],
241)
242def test_required_validation_alias_by_name(path: str): 1abcd
243 client = TestClient(app) 1CDE
244 response = client.get(path, headers={"p": "hello"}) 1CDE
245 assert response.status_code == 422, response.text 1CDE
247 assert response.json() == { 1CDE
248 "detail": [
249 {
250 "type": "missing",
251 "loc": ["header", "p_val_alias"],
252 "msg": "Field required",
253 "input": IsOneOf(None, IsPartialDict({"p": "hello"})),
254 }
255 ]
256 }
259@pytest.mark.parametrize( 1abcd
260 "path",
261 [
262 "/required-validation-alias",
263 "/model-required-validation-alias",
264 ],
265)
266def test_required_validation_alias_by_validation_alias(path: str): 1abcd
267 client = TestClient(app) 1klm
268 response = client.get(path, headers={"p_val_alias": "hello"}) 1klm
269 assert response.status_code == 200, response.text 1klm
271 assert response.json() == {"p": "hello"} 1klm
274# =====================================================================================
275# Alias and validation alias
278@app.get("/required-alias-and-validation-alias") 1abcd
279def read_required_alias_and_validation_alias( 1abcd
280 p: Annotated[str, Header(alias="p_alias", validation_alias="p_val_alias")],
281):
282 return {"p": p} 1nop
285class HeaderModelRequiredAliasAndValidationAlias(BaseModel): 1abcd
286 p: str = Field(alias="p_alias", validation_alias="p_val_alias") 1abcd
289@app.get("/model-required-alias-and-validation-alias") 1abcd
290def read_model_required_alias_and_validation_alias( 1abcd
291 p: Annotated[HeaderModelRequiredAliasAndValidationAlias, Header()],
292):
293 return {"p": p.p} 1nop
296@pytest.mark.parametrize( 1abcd
297 "path",
298 [
299 "/required-alias-and-validation-alias",
300 "/model-required-alias-and-validation-alias",
301 ],
302)
303def test_required_alias_and_validation_alias_schema(path: str): 1abcd
304 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 1XYZ
305 [
306 {
307 "required": True,
308 "schema": {"title": "P Val Alias", "type": "string"},
309 "name": "p_val_alias",
310 "in": "header",
311 }
312 ]
313 )
316@pytest.mark.parametrize( 1abcd
317 "path",
318 [
319 "/required-alias-and-validation-alias",
320 "/model-required-alias-and-validation-alias",
321 ],
322)
323def test_required_alias_and_validation_alias_missing(path: str): 1abcd
324 client = TestClient(app) 1FGH
325 response = client.get(path) 1FGH
326 assert response.status_code == 422 1FGH
327 assert response.json() == { 1FGH
328 "detail": [
329 {
330 "type": "missing",
331 "loc": [
332 "header",
333 "p_val_alias",
334 ],
335 "msg": "Field required",
336 "input": AnyThing,
337 }
338 ]
339 }
342@pytest.mark.parametrize( 1abcd
343 "path",
344 [
345 "/required-alias-and-validation-alias",
346 "/model-required-alias-and-validation-alias",
347 ],
348)
349def test_required_alias_and_validation_alias_by_name(path: str): 1abcd
350 client = TestClient(app) 1IJK
351 response = client.get(path, headers={"p": "hello"}) 1IJK
352 assert response.status_code == 422 1IJK
354 assert response.json() == { 1IJK
355 "detail": [
356 {
357 "type": "missing",
358 "loc": [
359 "header",
360 "p_val_alias",
361 ],
362 "msg": "Field required",
363 "input": IsOneOf(
364 None,
365 IsPartialDict({"p": "hello"}),
366 ),
367 }
368 ]
369 }
372@pytest.mark.parametrize( 1abcd
373 "path",
374 [
375 "/required-alias-and-validation-alias",
376 "/model-required-alias-and-validation-alias",
377 ],
378)
379def test_required_alias_and_validation_alias_by_alias(path: str): 1abcd
380 client = TestClient(app) 1LMN
381 response = client.get(path, headers={"p_alias": "hello"}) 1LMN
382 assert response.status_code == 422 1LMN
384 assert response.json() == { 1LMN
385 "detail": [
386 {
387 "type": "missing",
388 "loc": ["header", "p_val_alias"],
389 "msg": "Field required",
390 "input": IsOneOf(
391 None,
392 IsPartialDict({"p_alias": "hello"}),
393 ),
394 }
395 ]
396 }
399@pytest.mark.parametrize( 1abcd
400 "path",
401 [
402 "/required-alias-and-validation-alias",
403 "/model-required-alias-and-validation-alias",
404 ],
405)
406def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
407 client = TestClient(app) 1nop
408 response = client.get(path, headers={"p_val_alias": "hello"}) 1nop
409 assert response.status_code == 200, response.text 1nop
411 assert response.json() == {"p": "hello"} 1nop