Coverage for tests / test_request_params / test_form / test_optional_str.py: 100%
131 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, Form 1abcd
5from fastapi.testclient import TestClient 1abcd
6from pydantic import BaseModel, Field 1abcd
8from .utils import get_body_model_name 1abcd
10app = FastAPI() 1abcd
12# =====================================================================================
13# Without aliases
16@app.post("/optional-str", operation_id="optional_str") 1abcd
17async def read_optional_str(p: Annotated[str | None, Form()] = None): 1abcd
18 return {"p": p} 1efghijk
21class FormModelOptionalStr(BaseModel): 1abcd
22 p: str | None = None 1abcd
25@app.post("/model-optional-str", operation_id="model_optional_str") 1abcd
26async def read_model_optional_str(p: Annotated[FormModelOptionalStr, Form()]): 1abcd
27 return {"p": p.p} 2l m Mbn o p q r
30@pytest.mark.parametrize( 1abcd
31 "path",
32 ["/optional-str", "/model-optional-str"],
33)
34def test_optional_str_schema(path: str): 1abcd
35 openapi = app.openapi() 2hbibjbkblbmbnbob
36 body_model_name = get_body_model_name(openapi, path) 2hbibjbkblbmbnbob
38 assert app.openapi()["components"]["schemas"][body_model_name] == { 2hbibjbkblbmbnbob
39 "properties": {
40 "p": {
41 "anyOf": [{"type": "string"}, {"type": "null"}],
42 "title": "P",
43 },
44 },
45 "title": body_model_name,
46 "type": "object",
47 }
50@pytest.mark.parametrize( 1abcd
51 "path",
52 ["/optional-str", "/model-optional-str"],
53)
54def test_optional_str_missing(path: str): 1abcd
55 client = TestClient(app) 1mfngpirk
56 response = client.post(path) 1mfngpirk
57 assert response.status_code == 200 1mfngpirk
58 assert response.json() == {"p": None} 1mfngpirk
61@pytest.mark.parametrize( 1abcd
62 "path",
63 ["/optional-str", "/model-optional-str"],
64)
65def test_optional_str(path: str): 1abcd
66 client = TestClient(app) 1le`ohqj
67 response = client.post(path, data={"p": "hello"}) 1le`ohqj
68 assert response.status_code == 200 1le`ohqj
69 assert response.json() == {"p": "hello"} 1le`ohqj
72# =====================================================================================
73# Alias
76@app.post("/optional-alias", operation_id="optional_alias") 1abcd
77async def read_optional_alias( 1abcd
78 p: Annotated[str | None, Form(alias="p_alias")] = None,
79):
80 return {"p": p} 1stuvwxyzAB
83class FormModelOptionalAlias(BaseModel): 1abcd
84 p: str | None = Field(None, alias="p_alias") 1abcd
87@app.post("/model-optional-alias", operation_id="model_optional_alias") 1abcd
88async def read_model_optional_alias(p: Annotated[FormModelOptionalAlias, Form()]): 1abcd
89 return {"p": p.p} 2C D E F NbG H I J K L
92@pytest.mark.parametrize( 1abcd
93 "path",
94 [
95 "/optional-alias",
96 "/model-optional-alias",
97 ],
98)
99def test_optional_str_alias_schema(path: str): 1abcd
100 openapi = app.openapi() 2pbqbrbsbtbubvb
101 body_model_name = get_body_model_name(openapi, path) 2pbqbrbsbtbubvb
103 assert app.openapi()["components"]["schemas"][body_model_name] == { 2pbqbrbsbtbubvb
104 "properties": {
105 "p_alias": {
106 "anyOf": [{"type": "string"}, {"type": "null"}],
107 "title": "P Alias",
108 },
109 },
110 "title": body_model_name,
111 "type": "object",
112 }
115@pytest.mark.parametrize( 1abcd
116 "path",
117 ["/optional-alias", "/model-optional-alias"],
118)
119def test_optional_alias_missing(path: str): 1abcd
120 client = TestClient(app) 1EuvIyLB
121 response = client.post(path) 1EuvIyLB
122 assert response.status_code == 200 1EuvIyLB
123 assert response.json() == {"p": None} 1EuvIyLB
126@pytest.mark.parametrize( 1abcd
127 "path",
128 ["/optional-alias", "/model-optional-alias"],
129)
130def test_optional_alias_by_name(path: str): 1abcd
131 client = TestClient(app) 1Dt{HxKA
132 response = client.post(path, data={"p": "hello"}) 1Dt{HxKA
133 assert response.status_code == 200 1Dt{HxKA
134 assert response.json() == {"p": None} 1Dt{HxKA
137@pytest.mark.parametrize( 1abcd
138 "path",
139 ["/optional-alias", "/model-optional-alias"],
140)
141def test_optional_alias_by_alias(path: str): 1abcd
142 client = TestClient(app) 1CsF|GwJz
143 response = client.post(path, data={"p_alias": "hello"}) 1CsF|GwJz
144 assert response.status_code == 200 1CsF|GwJz
145 assert response.json() == {"p": "hello"} 1CsF|GwJz
148# =====================================================================================
149# Validation alias
152@app.post("/optional-validation-alias", operation_id="optional_validation_alias") 1abcd
153def read_optional_validation_alias( 1abcd
154 p: Annotated[str | None, Form(validation_alias="p_val_alias")] = None,
155):
156 return {"p": p} 1MNOPQRSTUVW
159class FormModelOptionalValidationAlias(BaseModel): 1abcd
160 p: str | None = Field(None, validation_alias="p_val_alias") 1abcd
163@app.post( 1abcd
164 "/model-optional-validation-alias", operation_id="model_optional_validation_alias"
165)
166def read_model_optional_validation_alias( 1abcd
167 p: Annotated[FormModelOptionalValidationAlias, Form()],
168):
169 return {"p": p.p} 2X Y Z Ob0 1 2 3 4 5
172@pytest.mark.parametrize( 1abcd
173 "path",
174 ["/optional-validation-alias", "/model-optional-validation-alias"],
175)
176def test_optional_validation_alias_schema(path: str): 1abcd
177 openapi = app.openapi() 2wbxbybzbAbBbCbDb
178 body_model_name = get_body_model_name(openapi, path) 2wbxbybzbAbBbCbDb
180 assert app.openapi()["components"]["schemas"][body_model_name] == { 2wbxbybzbAbBbCbDb
181 "properties": {
182 "p_val_alias": {
183 "anyOf": [{"type": "string"}, {"type": "null"}],
184 "title": "P Val Alias",
185 },
186 },
187 "title": body_model_name,
188 "type": "object",
189 }
192@pytest.mark.parametrize( 1abcd
193 "path",
194 ["/optional-validation-alias", "/model-optional-validation-alias"],
195)
196def test_optional_validation_alias_missing(path: str): 1abcd
197 client = TestClient(app) 1ZOQ2T5W
198 response = client.post(path) 1ZOQ2T5W
199 assert response.status_code == 200 1ZOQ2T5W
200 assert response.json() == {"p": None} 1ZOQ2T5W
203@pytest.mark.parametrize( 1abcd
204 "path",
205 [
206 "/optional-validation-alias",
207 "/model-optional-validation-alias",
208 ],
209)
210def test_optional_validation_alias_by_name(path: str): 1abcd
211 client = TestClient(app) 1XM}P0R3U
212 response = client.post(path, data={"p": "hello"}) 1XM}P0R3U
213 assert response.status_code == 200 1XM}P0R3U
214 assert response.json() == {"p": None} 1XM}P0R3U
217@pytest.mark.parametrize( 1abcd
218 "path",
219 [
220 "/optional-validation-alias",
221 "/model-optional-validation-alias",
222 ],
223)
224def test_optional_validation_alias_by_validation_alias(path: str): 1abcd
225 client = TestClient(app) 2Y N ~ ab1 S 4 V
226 response = client.post(path, data={"p_val_alias": "hello"}) 2Y N ~ ab1 S 4 V
227 assert response.status_code == 200 2Y N ~ ab1 S 4 V
228 assert response.json() == {"p": "hello"} 2Y N ~ ab1 S 4 V
231# =====================================================================================
232# Alias and validation alias
235@app.post( 1abcd
236 "/optional-alias-and-validation-alias",
237 operation_id="optional_alias_and_validation_alias",
238)
239def read_optional_alias_and_validation_alias( 1abcd
240 p: Annotated[
241 str | None, Form(alias="p_alias", validation_alias="p_val_alias")
242 ] = None,
243):
244 return {"p": p} 16789!#$%'()*+
247class FormModelOptionalAliasAndValidationAlias(BaseModel): 1abcd
248 p: str | None = Field(None, alias="p_alias", validation_alias="p_val_alias") 1abcd
251@app.post( 1abcd
252 "/model-optional-alias-and-validation-alias",
253 operation_id="model_optional_alias_and_validation_alias",
254)
255def read_model_optional_alias_and_validation_alias( 1abcd
256 p: Annotated[FormModelOptionalAliasAndValidationAlias, Form()],
257):
258 return {"p": p.p} 1,-./:;=?@[]^_
261@pytest.mark.parametrize( 1abcd
262 "path",
263 [
264 "/optional-alias-and-validation-alias",
265 "/model-optional-alias-and-validation-alias",
266 ],
267)
268def test_optional_alias_and_validation_alias_schema(path: str): 1abcd
269 openapi = app.openapi() 2EbFbGbHbIbJbKbLb
270 body_model_name = get_body_model_name(openapi, path) 2EbFbGbHbIbJbKbLb
272 assert app.openapi()["components"]["schemas"][body_model_name] == { 2EbFbGbHbIbJbKbLb
273 "properties": {
274 "p_val_alias": {
275 "anyOf": [{"type": "string"}, {"type": "null"}],
276 "title": "P Val Alias",
277 },
278 },
279 "title": body_model_name,
280 "type": "object",
281 }
284@pytest.mark.parametrize( 1abcd
285 "path",
286 [
287 "/optional-alias-and-validation-alias",
288 "/model-optional-alias-and-validation-alias",
289 ],
290)
291def test_optional_alias_and_validation_alias_missing(path: str): 1abcd
292 client = TestClient(app) 1/9:!@'_+
293 response = client.post(path) 1/9:!@'_+
294 assert response.status_code == 200 1/9:!@'_+
295 assert response.json() == {"p": None} 1/9:!@'_+
298@pytest.mark.parametrize( 1abcd
299 "path",
300 [
301 "/optional-alias-and-validation-alias",
302 "/model-optional-alias-and-validation-alias",
303 ],
304)
305def test_optional_alias_and_validation_alias_by_name(path: str): 1abcd
306 client = TestClient(app) 2- 7 bbcb= $ ] )
307 response = client.post(path, data={"p": "hello"}) 2- 7 bbcb= $ ] )
308 assert response.status_code == 200 2- 7 bbcb= $ ] )
309 assert response.json() == {"p": None} 2- 7 bbcb= $ ] )
312@pytest.mark.parametrize( 1abcd
313 "path",
314 [
315 "/optional-alias-and-validation-alias",
316 "/model-optional-alias-and-validation-alias",
317 ],
318)
319def test_optional_alias_and_validation_alias_by_alias(path: str): 1abcd
320 client = TestClient(app) 2, 6 dbeb; # [ (
321 response = client.post(path, data={"p_alias": "hello"}) 2, 6 dbeb; # [ (
322 assert response.status_code == 200 2, 6 dbeb; # [ (
323 assert response.json() == {"p": None} 2, 6 dbeb; # [ (
326@pytest.mark.parametrize( 1abcd
327 "path",
328 [
329 "/optional-alias-and-validation-alias",
330 "/model-optional-alias-and-validation-alias",
331 ],
332)
333def test_optional_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
334 client = TestClient(app) 2. 8 fbgb? % ^ *
335 response = client.post(path, data={"p_val_alias": "hello"}) 2. 8 fbgb? % ^ *
336 assert response.status_code == 200 2. 8 fbgb? % ^ *
337 assert response.json() == {"p": "hello"} 2. 8 fbgb? % ^ *