Coverage for tests/test_tutorial/test_body_multiple_params/test_tutorial003.py: 100%

26 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.testclient import TestClient 1abcdef

6 

7from ...utils import needs_py39, needs_py310 1abcdef

8 

9 

10@pytest.fixture( 1abcdef

11 name="client", 

12 params=[ 

13 "tutorial003", 

14 pytest.param("tutorial003_py310", marks=needs_py310), 

15 "tutorial003_an", 

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

17 pytest.param("tutorial003_an_py310", marks=needs_py310), 

18 ], 

19) 

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

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

22 

23 client = TestClient(mod.app) 1abcdef

24 return client 1abcdef

25 

26 

27def test_post_body_valid(client: TestClient): 1abcdef

28 response = client.put( 1ghijkl

29 "/items/5", 

30 json={ 

31 "importance": 2, 

32 "item": {"name": "Foo", "price": 50.5}, 

33 "user": {"username": "Dave"}, 

34 }, 

35 ) 

36 assert response.status_code == 200 1ghijkl

37 assert response.json() == { 1ghijkl

38 "item_id": 5, 

39 "importance": 2, 

40 "item": { 

41 "name": "Foo", 

42 "price": 50.5, 

43 "description": None, 

44 "tax": None, 

45 }, 

46 "user": {"username": "Dave", "full_name": None}, 

47 } 

48 

49 

50def test_post_body_no_data(client: TestClient): 1abcdef

51 response = client.put("/items/5", json=None) 1mnopqr

52 assert response.status_code == 422 1mnopqr

53 assert response.json() == IsDict( 1mnopqr

54 { 

55 "detail": [ 

56 { 

57 "type": "missing", 

58 "loc": ["body", "item"], 

59 "msg": "Field required", 

60 "input": None, 

61 }, 

62 { 

63 "type": "missing", 

64 "loc": ["body", "user"], 

65 "msg": "Field required", 

66 "input": None, 

67 }, 

68 { 

69 "type": "missing", 

70 "loc": ["body", "importance"], 

71 "msg": "Field required", 

72 "input": None, 

73 }, 

74 ] 

75 } 

76 ) | IsDict( 

77 # TODO: remove when deprecating Pydantic v1 

78 { 

79 "detail": [ 

80 { 

81 "loc": ["body", "item"], 

82 "msg": "field required", 

83 "type": "value_error.missing", 

84 }, 

85 { 

86 "loc": ["body", "user"], 

87 "msg": "field required", 

88 "type": "value_error.missing", 

89 }, 

90 { 

91 "loc": ["body", "importance"], 

92 "msg": "field required", 

93 "type": "value_error.missing", 

94 }, 

95 ] 

96 } 

97 ) 

98 

99 

100def test_post_body_empty_list(client: TestClient): 1abcdef

101 response = client.put("/items/5", json=[]) 1stuvwx

102 assert response.status_code == 422 1stuvwx

103 assert response.json() == IsDict( 1stuvwx

104 { 

105 "detail": [ 

106 { 

107 "type": "missing", 

108 "loc": ["body", "item"], 

109 "msg": "Field required", 

110 "input": None, 

111 }, 

112 { 

113 "type": "missing", 

114 "loc": ["body", "user"], 

115 "msg": "Field required", 

116 "input": None, 

117 }, 

118 { 

119 "type": "missing", 

120 "loc": ["body", "importance"], 

121 "msg": "Field required", 

122 "input": None, 

123 }, 

124 ] 

125 } 

126 ) | IsDict( 

127 # TODO: remove when deprecating Pydantic v1 

128 { 

129 "detail": [ 

130 { 

131 "loc": ["body", "item"], 

132 "msg": "field required", 

133 "type": "value_error.missing", 

134 }, 

135 { 

136 "loc": ["body", "user"], 

137 "msg": "field required", 

138 "type": "value_error.missing", 

139 }, 

140 { 

141 "loc": ["body", "importance"], 

142 "msg": "field required", 

143 "type": "value_error.missing", 

144 }, 

145 ] 

146 } 

147 ) 

148 

149 

150def test_openapi_schema(client: TestClient): 1abcdef

151 response = client.get("/openapi.json") 1yzABCD

152 assert response.status_code == 200, response.text 1yzABCD

153 assert response.json() == { 1yzABCD

154 "openapi": "3.1.0", 

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

156 "paths": { 

157 "/items/{item_id}": { 

158 "put": { 

159 "responses": { 

160 "200": { 

161 "description": "Successful Response", 

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

163 }, 

164 "422": { 

165 "description": "Validation Error", 

166 "content": { 

167 "application/json": { 

168 "schema": { 

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

170 } 

171 } 

172 }, 

173 }, 

174 }, 

175 "summary": "Update Item", 

176 "operationId": "update_item_items__item_id__put", 

177 "parameters": [ 

178 { 

179 "required": True, 

180 "schema": {"title": "Item Id", "type": "integer"}, 

181 "name": "item_id", 

182 "in": "path", 

183 } 

184 ], 

185 "requestBody": { 

186 "content": { 

187 "application/json": { 

188 "schema": { 

189 "$ref": "#/components/schemas/Body_update_item_items__item_id__put" 

190 } 

191 } 

192 }, 

193 "required": True, 

194 }, 

195 } 

196 } 

197 }, 

198 "components": { 

199 "schemas": { 

200 "Item": { 

201 "title": "Item", 

202 "required": ["name", "price"], 

203 "type": "object", 

204 "properties": { 

205 "name": {"title": "Name", "type": "string"}, 

206 "description": IsDict( 

207 { 

208 "title": "Description", 

209 "anyOf": [{"type": "string"}, {"type": "null"}], 

210 } 

211 ) 

212 | IsDict( 

213 # TODO: remove when deprecating Pydantic v1 

214 {"title": "Description", "type": "string"} 

215 ), 

216 "price": {"title": "Price", "type": "number"}, 

217 "tax": IsDict( 

218 { 

219 "title": "Tax", 

220 "anyOf": [{"type": "number"}, {"type": "null"}], 

221 } 

222 ) 

223 | IsDict( 

224 # TODO: remove when deprecating Pydantic v1 

225 {"title": "Tax", "type": "number"} 

226 ), 

227 }, 

228 }, 

229 "User": { 

230 "title": "User", 

231 "required": ["username"], 

232 "type": "object", 

233 "properties": { 

234 "username": {"title": "Username", "type": "string"}, 

235 "full_name": IsDict( 

236 { 

237 "title": "Full Name", 

238 "anyOf": [{"type": "string"}, {"type": "null"}], 

239 } 

240 ) 

241 | IsDict( 

242 # TODO: remove when deprecating Pydantic v1 

243 {"title": "Full Name", "type": "string"} 

244 ), 

245 }, 

246 }, 

247 "Body_update_item_items__item_id__put": { 

248 "title": "Body_update_item_items__item_id__put", 

249 "required": ["item", "user", "importance"], 

250 "type": "object", 

251 "properties": { 

252 "item": {"$ref": "#/components/schemas/Item"}, 

253 "user": {"$ref": "#/components/schemas/User"}, 

254 "importance": {"title": "Importance", "type": "integer"}, 

255 }, 

256 }, 

257 "ValidationError": { 

258 "title": "ValidationError", 

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

260 "type": "object", 

261 "properties": { 

262 "loc": { 

263 "title": "Location", 

264 "type": "array", 

265 "items": { 

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

267 }, 

268 }, 

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

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

271 }, 

272 }, 

273 "HTTPValidationError": { 

274 "title": "HTTPValidationError", 

275 "type": "object", 

276 "properties": { 

277 "detail": { 

278 "title": "Detail", 

279 "type": "array", 

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

281 } 

282 }, 

283 }, 

284 } 

285 }, 

286 }