Coverage for tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py: 100%
48 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-05-05 00:03 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-05-05 00:03 +0000
1import importlib 1abcdef
3import pytest 1abcdef
4from dirty_equals import IsDict 1abcdef
5from fastapi import FastAPI 1abcdef
6from fastapi.testclient import TestClient 1abcdef
8from ...utils import needs_py39 1abcdef
11@pytest.fixture( 1abcdef
12 name="app",
13 params=[
14 "tutorial001",
15 "tutorial001_an",
16 pytest.param("tutorial001_an_py39", marks=needs_py39),
17 ],
18)
19def get_app(request: pytest.FixtureRequest): 1abcdef
20 mod = importlib.import_module(f"docs_src.request_forms_and_files.{request.param}") 1abcdef
22 return mod.app 1abcdef
25@pytest.fixture(name="client") 1abcdef
26def get_client(app: FastAPI): 1abcdef
27 client = TestClient(app) 1abcdef
28 return client 1abcdef
31def test_post_form_no_body(client: TestClient): 1abcdef
32 response = client.post("/files/") 1stuvwx
33 assert response.status_code == 422, response.text 1stuvwx
34 assert response.json() == IsDict( 1stuvwx
35 {
36 "detail": [
37 {
38 "type": "missing",
39 "loc": ["body", "file"],
40 "msg": "Field required",
41 "input": None,
42 },
43 {
44 "type": "missing",
45 "loc": ["body", "fileb"],
46 "msg": "Field required",
47 "input": None,
48 },
49 {
50 "type": "missing",
51 "loc": ["body", "token"],
52 "msg": "Field required",
53 "input": None,
54 },
55 ]
56 }
57 ) | IsDict(
58 # TODO: remove when deprecating Pydantic v1
59 {
60 "detail": [
61 {
62 "loc": ["body", "file"],
63 "msg": "field required",
64 "type": "value_error.missing",
65 },
66 {
67 "loc": ["body", "fileb"],
68 "msg": "field required",
69 "type": "value_error.missing",
70 },
71 {
72 "loc": ["body", "token"],
73 "msg": "field required",
74 "type": "value_error.missing",
75 },
76 ]
77 }
78 )
81def test_post_form_no_file(client: TestClient): 1abcdef
82 response = client.post("/files/", data={"token": "foo"}) 1yzABCD
83 assert response.status_code == 422, response.text 1yzABCD
84 assert response.json() == IsDict( 1yzABCD
85 {
86 "detail": [
87 {
88 "type": "missing",
89 "loc": ["body", "file"],
90 "msg": "Field required",
91 "input": None,
92 },
93 {
94 "type": "missing",
95 "loc": ["body", "fileb"],
96 "msg": "Field required",
97 "input": None,
98 },
99 ]
100 }
101 ) | IsDict(
102 # TODO: remove when deprecating Pydantic v1
103 {
104 "detail": [
105 {
106 "loc": ["body", "file"],
107 "msg": "field required",
108 "type": "value_error.missing",
109 },
110 {
111 "loc": ["body", "fileb"],
112 "msg": "field required",
113 "type": "value_error.missing",
114 },
115 ]
116 }
117 )
120def test_post_body_json(client: TestClient): 1abcdef
121 response = client.post("/files/", json={"file": "Foo", "token": "Bar"}) 1EFGHIJ
122 assert response.status_code == 422, response.text 1EFGHIJ
123 assert response.json() == IsDict( 1EFGHIJ
124 {
125 "detail": [
126 {
127 "type": "missing",
128 "loc": ["body", "file"],
129 "msg": "Field required",
130 "input": None,
131 },
132 {
133 "type": "missing",
134 "loc": ["body", "fileb"],
135 "msg": "Field required",
136 "input": None,
137 },
138 {
139 "type": "missing",
140 "loc": ["body", "token"],
141 "msg": "Field required",
142 "input": None,
143 },
144 ]
145 }
146 ) | IsDict(
147 # TODO: remove when deprecating Pydantic v1
148 {
149 "detail": [
150 {
151 "loc": ["body", "file"],
152 "msg": "field required",
153 "type": "value_error.missing",
154 },
155 {
156 "loc": ["body", "fileb"],
157 "msg": "field required",
158 "type": "value_error.missing",
159 },
160 {
161 "loc": ["body", "token"],
162 "msg": "field required",
163 "type": "value_error.missing",
164 },
165 ]
166 }
167 )
170def test_post_file_no_token(tmp_path, app: FastAPI): 1abcdef
171 path = tmp_path / "test.txt" 1mnopqr
172 path.write_bytes(b"<file content>") 1mnopqr
174 client = TestClient(app) 1mnopqr
175 with path.open("rb") as file: 1mnopqr
176 response = client.post("/files/", files={"file": file}) 1mnopqr
177 assert response.status_code == 422, response.text 1mnopqr
178 assert response.json() == IsDict( 1mnopqr
179 {
180 "detail": [
181 {
182 "type": "missing",
183 "loc": ["body", "fileb"],
184 "msg": "Field required",
185 "input": None,
186 },
187 {
188 "type": "missing",
189 "loc": ["body", "token"],
190 "msg": "Field required",
191 "input": None,
192 },
193 ]
194 }
195 ) | IsDict(
196 # TODO: remove when deprecating Pydantic v1
197 {
198 "detail": [
199 {
200 "loc": ["body", "fileb"],
201 "msg": "field required",
202 "type": "value_error.missing",
203 },
204 {
205 "loc": ["body", "token"],
206 "msg": "field required",
207 "type": "value_error.missing",
208 },
209 ]
210 }
211 )
214def test_post_files_and_token(tmp_path, app: FastAPI): 1abcdef
215 patha = tmp_path / "test.txt" 1ghijkl
216 pathb = tmp_path / "testb.txt" 1ghijkl
217 patha.write_text("<file content>") 1ghijkl
218 pathb.write_text("<file b content>") 1ghijkl
220 client = TestClient(app) 1ghijkl
221 with patha.open("rb") as filea, pathb.open("rb") as fileb: 1ghijkl
222 response = client.post( 1ghijkl
223 "/files/",
224 data={"token": "foo"},
225 files={"file": filea, "fileb": ("testb.txt", fileb, "text/plain")},
226 )
227 assert response.status_code == 200, response.text 1ghijkl
228 assert response.json() == { 1ghijkl
229 "file_size": 14,
230 "token": "foo",
231 "fileb_content_type": "text/plain",
232 }
235def test_openapi_schema(client: TestClient): 1abcdef
236 response = client.get("/openapi.json") 1KLMNOP
237 assert response.status_code == 200, response.text 1KLMNOP
238 assert response.json() == { 1KLMNOP
239 "openapi": "3.1.0",
240 "info": {"title": "FastAPI", "version": "0.1.0"},
241 "paths": {
242 "/files/": {
243 "post": {
244 "responses": {
245 "200": {
246 "description": "Successful Response",
247 "content": {"application/json": {"schema": {}}},
248 },
249 "422": {
250 "description": "Validation Error",
251 "content": {
252 "application/json": {
253 "schema": {
254 "$ref": "#/components/schemas/HTTPValidationError"
255 }
256 }
257 },
258 },
259 },
260 "summary": "Create File",
261 "operationId": "create_file_files__post",
262 "requestBody": {
263 "content": {
264 "multipart/form-data": {
265 "schema": {
266 "$ref": "#/components/schemas/Body_create_file_files__post"
267 }
268 }
269 },
270 "required": True,
271 },
272 }
273 }
274 },
275 "components": {
276 "schemas": {
277 "Body_create_file_files__post": {
278 "title": "Body_create_file_files__post",
279 "required": ["file", "fileb", "token"],
280 "type": "object",
281 "properties": {
282 "file": {"title": "File", "type": "string", "format": "binary"},
283 "fileb": {
284 "title": "Fileb",
285 "type": "string",
286 "format": "binary",
287 },
288 "token": {"title": "Token", "type": "string"},
289 },
290 },
291 "ValidationError": {
292 "title": "ValidationError",
293 "required": ["loc", "msg", "type"],
294 "type": "object",
295 "properties": {
296 "loc": {
297 "title": "Location",
298 "type": "array",
299 "items": {
300 "anyOf": [{"type": "string"}, {"type": "integer"}]
301 },
302 },
303 "msg": {"title": "Message", "type": "string"},
304 "type": {"title": "Error Type", "type": "string"},
305 },
306 },
307 "HTTPValidationError": {
308 "title": "HTTPValidationError",
309 "type": "object",
310 "properties": {
311 "detail": {
312 "title": "Detail",
313 "type": "array",
314 "items": {"$ref": "#/components/schemas/ValidationError"},
315 }
316 },
317 },
318 }
319 },
320 }