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

1import importlib 1abcdef

2 

3import pytest 1abcdef

4from dirty_equals import IsDict 1abcdef

5from fastapi import FastAPI 1abcdef

6from fastapi.testclient import TestClient 1abcdef

7 

8from ...utils import needs_py39 1abcdef

9 

10 

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

21 

22 return mod.app 1abcdef

23 

24 

25@pytest.fixture(name="client") 1abcdef

26def get_client(app: FastAPI): 1abcdef

27 client = TestClient(app) 1abcdef

28 return client 1abcdef

29 

30 

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 ) 

79 

80 

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 ) 

118 

119 

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 ) 

168 

169 

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

173 

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 ) 

212 

213 

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

219 

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 } 

233 

234 

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 }