Coverage for tests/test_tutorial/test_request_files/test_tutorial002.py: 100%

51 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 "tutorial002", 

15 "tutorial002_an", 

16 pytest.param("tutorial002_py39", marks=needs_py39), 

17 pytest.param("tutorial002_an_py39", marks=needs_py39), 

18 ], 

19) 

20def get_app(request: pytest.FixtureRequest): 1abcdef

21 mod = importlib.import_module(f"docs_src.request_files.{request.param}") 1abcdef

22 

23 return mod.app 1abcdef

24 

25 

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

27def get_client(app: FastAPI): 1abcdef

28 client = TestClient(app) 1abcdef

29 return client 1abcdef

30 

31 

32def test_post_form_no_body(client: TestClient): 1abcdef

33 response = client.post("/files/") 1yzABCD

34 assert response.status_code == 422, response.text 1yzABCD

35 assert response.json() == IsDict( 1yzABCD

36 { 

37 "detail": [ 

38 { 

39 "type": "missing", 

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

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", "files"], 

52 "msg": "field required", 

53 "type": "value_error.missing", 

54 } 

55 ] 

56 } 

57 ) 

58 

59 

60def test_post_body_json(client: TestClient): 1abcdef

61 response = client.post("/files/", json={"file": "Foo"}) 1EFGHIJ

62 assert response.status_code == 422, response.text 1EFGHIJ

63 assert response.json() == IsDict( 1EFGHIJ

64 { 

65 "detail": [ 

66 { 

67 "type": "missing", 

68 "loc": ["body", "files"], 

69 "msg": "Field required", 

70 "input": None, 

71 } 

72 ] 

73 } 

74 ) | IsDict( 

75 # TODO: remove when deprecating Pydantic v1 

76 { 

77 "detail": [ 

78 { 

79 "loc": ["body", "files"], 

80 "msg": "field required", 

81 "type": "value_error.missing", 

82 } 

83 ] 

84 } 

85 ) 

86 

87 

88def test_post_files(tmp_path, app: FastAPI): 1abcdef

89 path = tmp_path / "test.txt" 1ghijkl

90 path.write_bytes(b"<file content>") 1ghijkl

91 path2 = tmp_path / "test2.txt" 1ghijkl

92 path2.write_bytes(b"<file content2>") 1ghijkl

93 

94 client = TestClient(app) 1ghijkl

95 with path.open("rb") as file, path2.open("rb") as file2: 1ghijkl

96 response = client.post( 1ghijkl

97 "/files/", 

98 files=( 

99 ("files", ("test.txt", file)), 

100 ("files", ("test2.txt", file2)), 

101 ), 

102 ) 

103 assert response.status_code == 200, response.text 1ghijkl

104 assert response.json() == {"file_sizes": [14, 15]} 1ghijkl

105 

106 

107def test_post_upload_file(tmp_path, app: FastAPI): 1abcdef

108 path = tmp_path / "test.txt" 1mnopqr

109 path.write_bytes(b"<file content>") 1mnopqr

110 path2 = tmp_path / "test2.txt" 1mnopqr

111 path2.write_bytes(b"<file content2>") 1mnopqr

112 

113 client = TestClient(app) 1mnopqr

114 with path.open("rb") as file, path2.open("rb") as file2: 1mnopqr

115 response = client.post( 1mnopqr

116 "/uploadfiles/", 

117 files=( 

118 ("files", ("test.txt", file)), 

119 ("files", ("test2.txt", file2)), 

120 ), 

121 ) 

122 assert response.status_code == 200, response.text 1mnopqr

123 assert response.json() == {"filenames": ["test.txt", "test2.txt"]} 1mnopqr

124 

125 

126def test_get_root(app: FastAPI): 1abcdef

127 client = TestClient(app) 1stuvwx

128 response = client.get("/") 1stuvwx

129 assert response.status_code == 200, response.text 1stuvwx

130 assert b"<form" in response.content 1stuvwx

131 

132 

133def test_openapi_schema(client: TestClient): 1abcdef

134 response = client.get("/openapi.json") 1KLMNOP

135 assert response.status_code == 200, response.text 1KLMNOP

136 assert response.json() == { 1KLMNOP

137 "openapi": "3.1.0", 

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

139 "paths": { 

140 "/files/": { 

141 "post": { 

142 "responses": { 

143 "200": { 

144 "description": "Successful Response", 

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

146 }, 

147 "422": { 

148 "description": "Validation Error", 

149 "content": { 

150 "application/json": { 

151 "schema": { 

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

153 } 

154 } 

155 }, 

156 }, 

157 }, 

158 "summary": "Create Files", 

159 "operationId": "create_files_files__post", 

160 "requestBody": { 

161 "content": { 

162 "multipart/form-data": { 

163 "schema": { 

164 "$ref": "#/components/schemas/Body_create_files_files__post" 

165 } 

166 } 

167 }, 

168 "required": True, 

169 }, 

170 } 

171 }, 

172 "/uploadfiles/": { 

173 "post": { 

174 "responses": { 

175 "200": { 

176 "description": "Successful Response", 

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

178 }, 

179 "422": { 

180 "description": "Validation Error", 

181 "content": { 

182 "application/json": { 

183 "schema": { 

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

185 } 

186 } 

187 }, 

188 }, 

189 }, 

190 "summary": "Create Upload Files", 

191 "operationId": "create_upload_files_uploadfiles__post", 

192 "requestBody": { 

193 "content": { 

194 "multipart/form-data": { 

195 "schema": { 

196 "$ref": "#/components/schemas/Body_create_upload_files_uploadfiles__post" 

197 } 

198 } 

199 }, 

200 "required": True, 

201 }, 

202 } 

203 }, 

204 "/": { 

205 "get": { 

206 "responses": { 

207 "200": { 

208 "description": "Successful Response", 

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

210 } 

211 }, 

212 "summary": "Main", 

213 "operationId": "main__get", 

214 } 

215 }, 

216 }, 

217 "components": { 

218 "schemas": { 

219 "Body_create_upload_files_uploadfiles__post": { 

220 "title": "Body_create_upload_files_uploadfiles__post", 

221 "required": ["files"], 

222 "type": "object", 

223 "properties": { 

224 "files": { 

225 "title": "Files", 

226 "type": "array", 

227 "items": {"type": "string", "format": "binary"}, 

228 } 

229 }, 

230 }, 

231 "Body_create_files_files__post": { 

232 "title": "Body_create_files_files__post", 

233 "required": ["files"], 

234 "type": "object", 

235 "properties": { 

236 "files": { 

237 "title": "Files", 

238 "type": "array", 

239 "items": {"type": "string", "format": "binary"}, 

240 } 

241 }, 

242 }, 

243 "ValidationError": { 

244 "title": "ValidationError", 

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

246 "type": "object", 

247 "properties": { 

248 "loc": { 

249 "title": "Location", 

250 "type": "array", 

251 "items": { 

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

253 }, 

254 }, 

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

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

257 }, 

258 }, 

259 "HTTPValidationError": { 

260 "title": "HTTPValidationError", 

261 "type": "object", 

262 "properties": { 

263 "detail": { 

264 "title": "Detail", 

265 "type": "array", 

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

267 } 

268 }, 

269 }, 

270 } 

271 }, 

272 }