Coverage for tests / test_request_params / test_file / test_optional.py: 100%
122 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, File, UploadFile 1abcd
5from fastapi.testclient import TestClient 1abcd
7from .utils import get_body_model_name 1abcd
9app = FastAPI() 1abcd
11# =====================================================================================
12# Without aliases
15@app.post("/optional-bytes", operation_id="optional_bytes") 1abcd
16async def read_optional_bytes(p: Annotated[Optional[bytes], File()] = None): 1abcd
17 return {"file_size": len(p) if p else None} 1efghij
20@app.post("/optional-uploadfile", operation_id="optional_uploadfile") 1abcd
21async def read_optional_uploadfile(p: Annotated[Optional[UploadFile], File()] = None): 1abcd
22 return {"file_size": p.size if p else None} 1efghij
25@pytest.mark.parametrize( 1abcd
26 "path",
27 [
28 "/optional-bytes",
29 "/optional-uploadfile",
30 ],
31)
32def test_optional_schema(path: str): 1abcd
33 openapi = app.openapi() 1OPQ
34 body_model_name = get_body_model_name(openapi, path) 1OPQ
36 assert app.openapi()["components"]["schemas"][body_model_name] == { 1OPQ
37 "properties": {
38 "p": {
39 "anyOf": [
40 {"type": "string", "format": "binary"},
41 {"type": "null"},
42 ],
43 "title": "P",
44 }
45 },
46 "title": body_model_name,
47 "type": "object",
48 }
51@pytest.mark.parametrize( 1abcd
52 "path",
53 [
54 "/optional-bytes",
55 "/optional-uploadfile",
56 ],
57)
58def test_optional_missing(path: str): 1abcd
59 client = TestClient(app) 1fhj
60 response = client.post(path) 1fhj
61 assert response.status_code == 200, response.text 1fhj
62 assert response.json() == {"file_size": None} 1fhj
65@pytest.mark.parametrize( 1abcd
66 "path",
67 [
68 "/optional-bytes",
69 "/optional-uploadfile",
70 ],
71)
72def test_optional(path: str): 1abcd
73 client = TestClient(app) 1egi
74 response = client.post(path, files=[("p", b"hello")]) 1egi
75 assert response.status_code == 200 1egi
76 assert response.json() == {"file_size": 5} 1egi
79# =====================================================================================
80# Alias
83@app.post("/optional-bytes-alias", operation_id="optional_bytes_alias") 1abcd
84async def read_optional_bytes_alias( 1abcd
85 p: Annotated[Optional[bytes], File(alias="p_alias")] = None,
86):
87 return {"file_size": len(p) if p else None} 1klmnopqrs
90@app.post("/optional-uploadfile-alias", operation_id="optional_uploadfile_alias") 1abcd
91async def read_optional_uploadfile_alias( 1abcd
92 p: Annotated[Optional[UploadFile], File(alias="p_alias")] = None,
93):
94 return {"file_size": p.size if p else None} 1klmnopqrs
97@pytest.mark.parametrize( 1abcd
98 "path",
99 [
100 "/optional-bytes-alias",
101 "/optional-uploadfile-alias",
102 ],
103)
104def test_optional_alias_schema(path: str): 1abcd
105 openapi = app.openapi() 1RST
106 body_model_name = get_body_model_name(openapi, path) 1RST
108 assert app.openapi()["components"]["schemas"][body_model_name] == { 1RST
109 "properties": {
110 "p_alias": {
111 "anyOf": [
112 {"type": "string", "format": "binary"},
113 {"type": "null"},
114 ],
115 "title": "P Alias",
116 }
117 },
118 "title": body_model_name,
119 "type": "object",
120 }
123@pytest.mark.parametrize( 1abcd
124 "path",
125 [
126 "/optional-bytes-alias",
127 "/optional-uploadfile-alias",
128 ],
129)
130def test_optional_alias_missing(path: str): 1abcd
131 client = TestClient(app) 1mps
132 response = client.post(path) 1mps
133 assert response.status_code == 200 1mps
134 assert response.json() == {"file_size": None} 1mps
137@pytest.mark.parametrize( 1abcd
138 "path",
139 [
140 "/optional-bytes-alias",
141 "/optional-uploadfile-alias",
142 ],
143)
144def test_optional_alias_by_name(path: str): 1abcd
145 client = TestClient(app) 1lor
146 response = client.post(path, files=[("p", b"hello")]) 1lor
147 assert response.status_code == 200 1lor
148 assert response.json() == {"file_size": None} 1lor
151@pytest.mark.parametrize( 1abcd
152 "path",
153 [
154 "/optional-bytes-alias",
155 "/optional-uploadfile-alias",
156 ],
157)
158def test_optional_alias_by_alias(path: str): 1abcd
159 client = TestClient(app) 1knq
160 response = client.post(path, files=[("p_alias", b"hello")]) 1knq
161 assert response.status_code == 200, response.text 1knq
162 assert response.json() == {"file_size": 5} 1knq
165# =====================================================================================
166# Validation alias
169@app.post( 1abcd
170 "/optional-bytes-validation-alias", operation_id="optional_bytes_validation_alias"
171)
172def read_optional_bytes_validation_alias( 1abcd
173 p: Annotated[Optional[bytes], File(validation_alias="p_val_alias")] = None,
174):
175 return {"file_size": len(p) if p else None} 1tuvwxyzAB
178@app.post( 1abcd
179 "/optional-uploadfile-validation-alias",
180 operation_id="optional_uploadfile_validation_alias",
181)
182def read_optional_uploadfile_validation_alias( 1abcd
183 p: Annotated[Optional[UploadFile], File(validation_alias="p_val_alias")] = None,
184):
185 return {"file_size": p.size if p else None} 1tuvwxyzAB
188@pytest.mark.parametrize( 1abcd
189 "path",
190 [
191 "/optional-bytes-validation-alias",
192 "/optional-uploadfile-validation-alias",
193 ],
194)
195def test_optional_validation_alias_schema(path: str): 1abcd
196 openapi = app.openapi() 1UVW
197 body_model_name = get_body_model_name(openapi, path) 1UVW
199 assert app.openapi()["components"]["schemas"][body_model_name] == { 1UVW
200 "properties": {
201 "p_val_alias": {
202 "anyOf": [
203 {"type": "string", "format": "binary"},
204 {"type": "null"},
205 ],
206 "title": "P Val Alias",
207 }
208 },
209 "title": body_model_name,
210 "type": "object",
211 }
214@pytest.mark.parametrize( 1abcd
215 "path",
216 [
217 "/optional-bytes-validation-alias",
218 "/optional-uploadfile-validation-alias",
219 ],
220)
221def test_optional_validation_alias_missing(path: str): 1abcd
222 client = TestClient(app) 1vyB
223 response = client.post(path) 1vyB
224 assert response.status_code == 200 1vyB
225 assert response.json() == {"file_size": None} 1vyB
228@pytest.mark.parametrize( 1abcd
229 "path",
230 [
231 "/optional-bytes-validation-alias",
232 "/optional-uploadfile-validation-alias",
233 ],
234)
235def test_optional_validation_alias_by_name(path: str): 1abcd
236 client = TestClient(app) 1twz
237 response = client.post(path, files=[("p", b"hello")]) 1twz
238 assert response.status_code == 200, response.text 1twz
239 assert response.json() == {"file_size": None} 1twz
242@pytest.mark.parametrize( 1abcd
243 "path",
244 [
245 "/optional-bytes-validation-alias",
246 "/optional-uploadfile-validation-alias",
247 ],
248)
249def test_optional_validation_alias_by_validation_alias(path: str): 1abcd
250 client = TestClient(app) 1uxA
251 response = client.post(path, files=[("p_val_alias", b"hello")]) 1uxA
252 assert response.status_code == 200, response.text 1uxA
253 assert response.json() == {"file_size": 5} 1uxA
256# =====================================================================================
257# Alias and validation alias
260@app.post( 1abcd
261 "/optional-bytes-alias-and-validation-alias",
262 operation_id="optional_bytes_alias_and_validation_alias",
263)
264def read_optional_bytes_alias_and_validation_alias( 1abcd
265 p: Annotated[
266 Optional[bytes], File(alias="p_alias", validation_alias="p_val_alias")
267 ] = None,
268):
269 return {"file_size": len(p) if p else None} 1CDEFGHIJKLMN
272@app.post( 1abcd
273 "/optional-uploadfile-alias-and-validation-alias",
274 operation_id="optional_uploadfile_alias_and_validation_alias",
275)
276def read_optional_uploadfile_alias_and_validation_alias( 1abcd
277 p: Annotated[
278 Optional[UploadFile], File(alias="p_alias", validation_alias="p_val_alias")
279 ] = None,
280):
281 return {"file_size": p.size if p else None} 1CDEFGHIJKLMN
284@pytest.mark.parametrize( 1abcd
285 "path",
286 [
287 "/optional-bytes-alias-and-validation-alias",
288 "/optional-uploadfile-alias-and-validation-alias",
289 ],
290)
291def test_optional_alias_and_validation_alias_schema(path: str): 1abcd
292 openapi = app.openapi() 1XYZ
293 body_model_name = get_body_model_name(openapi, path) 1XYZ
295 assert app.openapi()["components"]["schemas"][body_model_name] == { 1XYZ
296 "properties": {
297 "p_val_alias": {
298 "anyOf": [
299 {"type": "string", "format": "binary"},
300 {"type": "null"},
301 ],
302 "title": "P Val Alias",
303 }
304 },
305 "title": body_model_name,
306 "type": "object",
307 }
310@pytest.mark.parametrize( 1abcd
311 "path",
312 [
313 "/optional-bytes-alias-and-validation-alias",
314 "/optional-uploadfile-alias-and-validation-alias",
315 ],
316)
317def test_optional_alias_and_validation_alias_missing(path: str): 1abcd
318 client = TestClient(app) 1FJN
319 response = client.post(path) 1FJN
320 assert response.status_code == 200 1FJN
321 assert response.json() == {"file_size": None} 1FJN
324@pytest.mark.parametrize( 1abcd
325 "path",
326 [
327 "/optional-bytes-alias-and-validation-alias",
328 "/optional-uploadfile-alias-and-validation-alias",
329 ],
330)
331def test_optional_alias_and_validation_alias_by_name(path: str): 1abcd
332 client = TestClient(app) 1DHL
333 response = client.post(path, files={"p": "hello"}) 1DHL
334 assert response.status_code == 200 1DHL
335 assert response.json() == {"file_size": None} 1DHL
338@pytest.mark.parametrize( 1abcd
339 "path",
340 [
341 "/optional-bytes-alias-and-validation-alias",
342 "/optional-uploadfile-alias-and-validation-alias",
343 ],
344)
345def test_optional_alias_and_validation_alias_by_alias(path: str): 1abcd
346 client = TestClient(app) 1CGK
347 response = client.post(path, files=[("p_alias", b"hello")]) 1CGK
348 assert response.status_code == 200, response.text 1CGK
349 assert response.json() == {"file_size": None} 1CGK
352@pytest.mark.parametrize( 1abcd
353 "path",
354 [
355 "/optional-bytes-alias-and-validation-alias",
356 "/optional-uploadfile-alias-and-validation-alias",
357 ],
358)
359def test_optional_alias_and_validation_alias_by_validation_alias(path: str): 1abcd
360 client = TestClient(app) 1EIM
361 response = client.post(path, files=[("p_val_alias", b"hello")]) 1EIM
362 assert response.status_code == 200, response.text 1EIM
363 assert response.json() == {"file_size": 5} 1EIM