Coverage for tests/test_tutorial/test_request_forms_and_files/test_tutorial001_an.py: 100%

46 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-08 03:53 +0000

1import pytest 1abcde

2from dirty_equals import IsDict 1abcde

3from fastapi import FastAPI 1abcde

4from fastapi.testclient import TestClient 1abcde

5 

6 

7@pytest.fixture(name="app") 1abcde

8def get_app(): 1abcde

9 from docs_src.request_forms_and_files.tutorial001_an import app 1abcde

10 

11 return app 1abcde

12 

13 

14@pytest.fixture(name="client") 1abcde

15def get_client(app: FastAPI): 1abcde

16 client = TestClient(app) 1abcde

17 return client 1abcde

18 

19 

20def test_post_form_no_body(client: TestClient): 1abcde

21 response = client.post("/files/") 1abcde

22 assert response.status_code == 422, response.text 1abcde

23 assert response.json() == IsDict( 1abcde

24 { 

25 "detail": [ 

26 { 

27 "type": "missing", 

28 "loc": ["body", "file"], 

29 "msg": "Field required", 

30 "input": None, 

31 }, 

32 { 

33 "type": "missing", 

34 "loc": ["body", "fileb"], 

35 "msg": "Field required", 

36 "input": None, 

37 }, 

38 { 

39 "type": "missing", 

40 "loc": ["body", "token"], 

41 "msg": "Field required", 

42 "input": None, 

43 }, 

44 ] 

45 } 

46 ) | IsDict( 

47 # TODO: remove when deprecating Pydantic v1 

48 { 

49 "detail": [ 

50 { 

51 "loc": ["body", "file"], 

52 "msg": "field required", 

53 "type": "value_error.missing", 

54 }, 

55 { 

56 "loc": ["body", "fileb"], 

57 "msg": "field required", 

58 "type": "value_error.missing", 

59 }, 

60 { 

61 "loc": ["body", "token"], 

62 "msg": "field required", 

63 "type": "value_error.missing", 

64 }, 

65 ] 

66 } 

67 ) 

68 

69 

70def test_post_form_no_file(client: TestClient): 1abcde

71 response = client.post("/files/", data={"token": "foo"}) 1abcde

72 assert response.status_code == 422, response.text 1abcde

73 assert response.json() == IsDict( 1abcde

74 { 

75 "detail": [ 

76 { 

77 "type": "missing", 

78 "loc": ["body", "file"], 

79 "msg": "Field required", 

80 "input": None, 

81 }, 

82 { 

83 "type": "missing", 

84 "loc": ["body", "fileb"], 

85 "msg": "Field required", 

86 "input": None, 

87 }, 

88 ] 

89 } 

90 ) | IsDict( 

91 # TODO: remove when deprecating Pydantic v1 

92 { 

93 "detail": [ 

94 { 

95 "loc": ["body", "file"], 

96 "msg": "field required", 

97 "type": "value_error.missing", 

98 }, 

99 { 

100 "loc": ["body", "fileb"], 

101 "msg": "field required", 

102 "type": "value_error.missing", 

103 }, 

104 ] 

105 } 

106 ) 

107 

108 

109def test_post_body_json(client: TestClient): 1abcde

110 response = client.post("/files/", json={"file": "Foo", "token": "Bar"}) 1abcde

111 assert response.status_code == 422, response.text 1abcde

112 assert response.json() == IsDict( 1abcde

113 { 

114 "detail": [ 

115 { 

116 "type": "missing", 

117 "loc": ["body", "file"], 

118 "msg": "Field required", 

119 "input": None, 

120 }, 

121 { 

122 "type": "missing", 

123 "loc": ["body", "fileb"], 

124 "msg": "Field required", 

125 "input": None, 

126 }, 

127 { 

128 "type": "missing", 

129 "loc": ["body", "token"], 

130 "msg": "Field required", 

131 "input": None, 

132 }, 

133 ] 

134 } 

135 ) | IsDict( 

136 # TODO: remove when deprecating Pydantic v1 

137 { 

138 "detail": [ 

139 { 

140 "loc": ["body", "file"], 

141 "msg": "field required", 

142 "type": "value_error.missing", 

143 }, 

144 { 

145 "loc": ["body", "fileb"], 

146 "msg": "field required", 

147 "type": "value_error.missing", 

148 }, 

149 { 

150 "loc": ["body", "token"], 

151 "msg": "field required", 

152 "type": "value_error.missing", 

153 }, 

154 ] 

155 } 

156 ) 

157 

158 

159def test_post_file_no_token(tmp_path, app: FastAPI): 1abcde

160 path = tmp_path / "test.txt" 1abcde

161 path.write_bytes(b"<file content>") 1abcde

162 

163 client = TestClient(app) 1abcde

164 with path.open("rb") as file: 1abcde

165 response = client.post("/files/", files={"file": file}) 1abcde

166 assert response.status_code == 422, response.text 1abcde

167 assert response.json() == IsDict( 1abcde

168 { 

169 "detail": [ 

170 { 

171 "type": "missing", 

172 "loc": ["body", "fileb"], 

173 "msg": "Field required", 

174 "input": None, 

175 }, 

176 { 

177 "type": "missing", 

178 "loc": ["body", "token"], 

179 "msg": "Field required", 

180 "input": None, 

181 }, 

182 ] 

183 } 

184 ) | IsDict( 

185 # TODO: remove when deprecating Pydantic v1 

186 { 

187 "detail": [ 

188 { 

189 "loc": ["body", "fileb"], 

190 "msg": "field required", 

191 "type": "value_error.missing", 

192 }, 

193 { 

194 "loc": ["body", "token"], 

195 "msg": "field required", 

196 "type": "value_error.missing", 

197 }, 

198 ] 

199 } 

200 ) 

201 

202 

203def test_post_files_and_token(tmp_path, app: FastAPI): 1abcde

204 patha = tmp_path / "test.txt" 1abcde

205 pathb = tmp_path / "testb.txt" 1abcde

206 patha.write_text("<file content>") 1abcde

207 pathb.write_text("<file b content>") 1abcde

208 

209 client = TestClient(app) 1abcde

210 with patha.open("rb") as filea, pathb.open("rb") as fileb: 1abcde

211 response = client.post( 1abcde

212 "/files/", 

213 data={"token": "foo"}, 

214 files={"file": filea, "fileb": ("testb.txt", fileb, "text/plain")}, 

215 ) 

216 assert response.status_code == 200, response.text 1abcde

217 assert response.json() == { 1abcde

218 "file_size": 14, 

219 "token": "foo", 

220 "fileb_content_type": "text/plain", 

221 } 

222 

223 

224def test_openapi_schema(client: TestClient): 1abcde

225 response = client.get("/openapi.json") 1abcde

226 assert response.status_code == 200, response.text 1abcde

227 assert response.json() == { 1abcde

228 "openapi": "3.1.0", 

229 "info": {"title": "FastAPI", "version": "0.1.0"}, 

230 "paths": { 

231 "/files/": { 

232 "post": { 

233 "responses": { 

234 "200": { 

235 "description": "Successful Response", 

236 "content": {"application/json": {"schema": {}}}, 

237 }, 

238 "422": { 

239 "description": "Validation Error", 

240 "content": { 

241 "application/json": { 

242 "schema": { 

243 "$ref": "#/components/schemas/HTTPValidationError" 

244 } 

245 } 

246 }, 

247 }, 

248 }, 

249 "summary": "Create File", 

250 "operationId": "create_file_files__post", 

251 "requestBody": { 

252 "content": { 

253 "multipart/form-data": { 

254 "schema": { 

255 "$ref": "#/components/schemas/Body_create_file_files__post" 

256 } 

257 } 

258 }, 

259 "required": True, 

260 }, 

261 } 

262 } 

263 }, 

264 "components": { 

265 "schemas": { 

266 "Body_create_file_files__post": { 

267 "title": "Body_create_file_files__post", 

268 "required": ["file", "fileb", "token"], 

269 "type": "object", 

270 "properties": { 

271 "file": {"title": "File", "type": "string", "format": "binary"}, 

272 "fileb": { 

273 "title": "Fileb", 

274 "type": "string", 

275 "format": "binary", 

276 }, 

277 "token": {"title": "Token", "type": "string"}, 

278 }, 

279 }, 

280 "ValidationError": { 

281 "title": "ValidationError", 

282 "required": ["loc", "msg", "type"], 

283 "type": "object", 

284 "properties": { 

285 "loc": { 

286 "title": "Location", 

287 "type": "array", 

288 "items": { 

289 "anyOf": [{"type": "string"}, {"type": "integer"}] 

290 }, 

291 }, 

292 "msg": {"title": "Message", "type": "string"}, 

293 "type": {"title": "Error Type", "type": "string"}, 

294 }, 

295 }, 

296 "HTTPValidationError": { 

297 "title": "HTTPValidationError", 

298 "type": "object", 

299 "properties": { 

300 "detail": { 

301 "title": "Detail", 

302 "type": "array", 

303 "items": {"$ref": "#/components/schemas/ValidationError"}, 

304 } 

305 }, 

306 }, 

307 } 

308 }, 

309 }