Coverage for tests / test_request_params / test_form / test_required_str.py: 100%

132 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-04-06 01:24 +0000

1from typing import Annotated 1adbc

2 

3import pytest 1adbc

4from dirty_equals import IsOneOf 1adbc

5from fastapi import FastAPI, Form 1adbc

6from fastapi.testclient import TestClient 1adbc

7from pydantic import BaseModel, Field 1adbc

8 

9from .utils import get_body_model_name 1adbc

10 

11app = FastAPI() 1adbc

12 

13# ===================================================================================== 

14# Without aliases 

15 

16 

17@app.post("/required-str", operation_id="required_str") 1adbc

18async def read_required_str(p: Annotated[str, Form()]): 1adbc

19 return {"p": p} 1efgh

20 

21 

22class FormModelRequiredStr(BaseModel): 1adbc

23 p: str 1abc

24 

25 

26@app.post("/model-required-str", operation_id="model_required_str") 1adbc

27async def read_model_required_str(p: Annotated[FormModelRequiredStr, Form()]): 1adbc

28 return {"p": p.p} 1ijkl

29 

30 

31@pytest.mark.parametrize( 1adbc

32 "path", 

33 ["/required-str", "/model-required-str"], 

34) 

35def test_required_str_schema(path: str): 1adbc

36 openapi = app.openapi() 2kblbmbnbobpbqbrb

37 body_model_name = get_body_model_name(openapi, path) 2kblbmbnbobpbqbrb

38 

39 assert app.openapi()["components"]["schemas"][body_model_name] == { 2kblbmbnbobpbqbrb

40 "properties": { 

41 "p": {"title": "P", "type": "string"}, 

42 }, 

43 "required": ["p"], 

44 "title": body_model_name, 

45 "type": "object", 

46 } 

47 

48 

49@pytest.mark.parametrize( 1adbc

50 "path", 

51 ["/required-str", "/model-required-str"], 

52) 

53def test_required_str_missing(path: str): 1adbc

54 client = TestClient(app) 1KLMNOPQR

55 response = client.post(path) 1KLMNOPQR

56 assert response.status_code == 422 1KLMNOPQR

57 assert response.json() == { 1KLMNOPQR

58 "detail": [ 

59 { 

60 "type": "missing", 

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

62 "msg": "Field required", 

63 "input": IsOneOf(None, {}), 

64 } 

65 ] 

66 } 

67 

68 

69@pytest.mark.parametrize( 1adbc

70 "path", 

71 ["/required-str", "/model-required-str"], 

72) 

73def test_required_str(path: str): 1adbc

74 client = TestClient(app) 1iejfkglh

75 response = client.post(path, data={"p": "hello"}) 1iejfkglh

76 assert response.status_code == 200 1iejfkglh

77 assert response.json() == {"p": "hello"} 1iejfkglh

78 

79 

80# ===================================================================================== 

81# Alias 

82 

83 

84@app.post("/required-alias", operation_id="required_alias") 1adbc

85async def read_required_alias(p: Annotated[str, Form(alias="p_alias")]): 1adbc

86 return {"p": p} 1mnop

87 

88 

89class FormModelRequiredAlias(BaseModel): 1adbc

90 p: str = Field(alias="p_alias") 1adbc

91 

92 

93@app.post("/model-required-alias", operation_id="model_required_alias") 1adbc

94async def read_model_required_alias(p: Annotated[FormModelRequiredAlias, Form()]): 1adbc

95 return {"p": p.p} 1qrst

96 

97 

98@pytest.mark.parametrize( 1adbc

99 "path", 

100 [ 

101 "/required-alias", 

102 "/model-required-alias", 

103 ], 

104) 

105def test_required_str_alias_schema(path: str): 1adbc

106 openapi = app.openapi() 2sbtbubvbwbxbybzb

107 body_model_name = get_body_model_name(openapi, path) 2sbtbubvbwbxbybzb

108 

109 assert app.openapi()["components"]["schemas"][body_model_name] == { 2sbtbubvbwbxbybzb

110 "properties": { 

111 "p_alias": {"title": "P Alias", "type": "string"}, 

112 }, 

113 "required": ["p_alias"], 

114 "title": body_model_name, 

115 "type": "object", 

116 } 

117 

118 

119@pytest.mark.parametrize( 1adbc

120 "path", 

121 ["/required-alias", "/model-required-alias"], 

122) 

123def test_required_alias_missing(path: str): 1adbc

124 client = TestClient(app) 1STUVWXYZ

125 response = client.post(path) 1STUVWXYZ

126 assert response.status_code == 422 1STUVWXYZ

127 assert response.json() == { 1STUVWXYZ

128 "detail": [ 

129 { 

130 "type": "missing", 

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

132 "msg": "Field required", 

133 "input": IsOneOf(None, {}), 

134 } 

135 ] 

136 } 

137 

138 

139@pytest.mark.parametrize( 1adbc

140 "path", 

141 ["/required-alias", "/model-required-alias"], 

142) 

143def test_required_alias_by_name(path: str): 1adbc

144 client = TestClient(app) 101234567

145 response = client.post(path, data={"p": "hello"}) 101234567

146 assert response.status_code == 422 101234567

147 assert response.json() == { 101234567

148 "detail": [ 

149 { 

150 "type": "missing", 

151 "loc": ["body", "p_alias"], 

152 "msg": "Field required", 

153 "input": IsOneOf(None, {"p": "hello"}), 

154 } 

155 ] 

156 } 

157 

158 

159@pytest.mark.parametrize( 1adbc

160 "path", 

161 ["/required-alias", "/model-required-alias"], 

162) 

163def test_required_alias_by_alias(path: str): 1adbc

164 client = TestClient(app) 1qmrnsotp

165 response = client.post(path, data={"p_alias": "hello"}) 1qmrnsotp

166 assert response.status_code == 200, response.text 1qmrnsotp

167 assert response.json() == {"p": "hello"} 1qmrnsotp

168 

169 

170# ===================================================================================== 

171# Validation alias 

172 

173 

174@app.post("/required-validation-alias", operation_id="required_validation_alias") 1adbc

175def read_required_validation_alias( 1adbc

176 p: Annotated[str, Form(validation_alias="p_val_alias")], 

177): 

178 return {"p": p} 1uvwx

179 

180 

181class FormModelRequiredValidationAlias(BaseModel): 1adbc

182 p: str = Field(validation_alias="p_val_alias") 1adbc

183 

184 

185@app.post( 1adbc

186 "/model-required-validation-alias", operation_id="model_required_validation_alias" 

187) 

188def read_model_required_validation_alias( 1adbc

189 p: Annotated[FormModelRequiredValidationAlias, Form()], 

190): 

191 return {"p": p.p} 1yzAB

192 

193 

194@pytest.mark.parametrize( 1adbc

195 "path", 

196 ["/required-validation-alias", "/model-required-validation-alias"], 

197) 

198def test_required_validation_alias_schema(path: str): 1adbc

199 openapi = app.openapi() 2AbBbCbDbEbFbGb

200 body_model_name = get_body_model_name(openapi, path) 2AbBbCbDbEbFbGb

201 

202 assert app.openapi()["components"]["schemas"][body_model_name] == { 2AbBbCbDbEbFbGb

203 "properties": { 

204 "p_val_alias": {"title": "P Val Alias", "type": "string"}, 

205 }, 

206 "required": ["p_val_alias"], 

207 "title": body_model_name, 

208 "type": "object", 

209 } 

210 

211 

212@pytest.mark.parametrize( 1adbc

213 "path", 

214 [ 

215 "/required-validation-alias", 

216 "/model-required-validation-alias", 

217 ], 

218) 

219def test_required_validation_alias_missing(path: str): 1adbc

220 client = TestClient(app) 189!#$%'(

221 response = client.post(path) 189!#$%'(

222 assert response.status_code == 422 189!#$%'(

223 assert response.json() == { 189!#$%'(

224 "detail": [ 

225 { 

226 "type": "missing", 

227 "loc": [ 

228 "body", 

229 "p_val_alias", 

230 ], 

231 "msg": "Field required", 

232 "input": IsOneOf(None, {}), 

233 } 

234 ] 

235 } 

236 

237 

238@pytest.mark.parametrize( 1adbc

239 "path", 

240 [ 

241 "/required-validation-alias", 

242 "/model-required-validation-alias", 

243 ], 

244) 

245def test_required_validation_alias_by_name(path: str): 1adbc

246 client = TestClient(app) 1)*+,-./:

247 response = client.post(path, data={"p": "hello"}) 1)*+,-./:

248 assert response.status_code == 422, response.text 1)*+,-./:

249 

250 assert response.json() == { 1)*+,-./:

251 "detail": [ 

252 { 

253 "type": "missing", 

254 "loc": ["body", "p_val_alias"], 

255 "msg": "Field required", 

256 "input": IsOneOf(None, {"p": "hello"}), 

257 } 

258 ] 

259 } 

260 

261 

262@pytest.mark.parametrize( 1adbc

263 "path", 

264 [ 

265 "/required-validation-alias", 

266 "/model-required-validation-alias", 

267 ], 

268) 

269def test_required_validation_alias_by_validation_alias(path: str): 1adbc

270 client = TestClient(app) 1yuzvAwBx

271 response = client.post(path, data={"p_val_alias": "hello"}) 1yuzvAwBx

272 assert response.status_code == 200, response.text 1yuzvAwBx

273 

274 assert response.json() == {"p": "hello"} 1yuzvAwBx

275 

276 

277# ===================================================================================== 

278# Alias and validation alias 

279 

280 

281@app.post( 1adbc

282 "/required-alias-and-validation-alias", 

283 operation_id="required_alias_and_validation_alias", 

284) 

285def read_required_alias_and_validation_alias( 1adbc

286 p: Annotated[str, Form(alias="p_alias", validation_alias="p_val_alias")], 

287): 

288 return {"p": p} 1CDEF

289 

290 

291class FormModelRequiredAliasAndValidationAlias(BaseModel): 1adbc

292 p: str = Field(alias="p_alias", validation_alias="p_val_alias") 1adbc

293 

294 

295@app.post( 1adbc

296 "/model-required-alias-and-validation-alias", 

297 operation_id="model_required_alias_and_validation_alias", 

298) 

299def read_model_required_alias_and_validation_alias( 1adbc

300 p: Annotated[FormModelRequiredAliasAndValidationAlias, Form()], 

301): 

302 return {"p": p.p} 1GHIJ

303 

304 

305@pytest.mark.parametrize( 1adbc

306 "path", 

307 [ 

308 "/required-alias-and-validation-alias", 

309 "/model-required-alias-and-validation-alias", 

310 ], 

311) 

312def test_required_alias_and_validation_alias_schema(path: str): 1adbc

313 openapi = app.openapi() 2HbIbJbKbLbMbNbOb

314 body_model_name = get_body_model_name(openapi, path) 2HbIbJbKbLbMbNbOb

315 

316 assert app.openapi()["components"]["schemas"][body_model_name] == { 2HbIbJbKbLbMbNbOb

317 "properties": { 

318 "p_val_alias": {"title": "P Val Alias", "type": "string"}, 

319 }, 

320 "required": ["p_val_alias"], 

321 "title": body_model_name, 

322 "type": "object", 

323 } 

324 

325 

326@pytest.mark.parametrize( 1adbc

327 "path", 

328 [ 

329 "/required-alias-and-validation-alias", 

330 "/model-required-alias-and-validation-alias", 

331 ], 

332) 

333def test_required_alias_and_validation_alias_missing(path: str): 1adbc

334 client = TestClient(app) 1;=?@[]^_

335 response = client.post(path) 1;=?@[]^_

336 assert response.status_code == 422 1;=?@[]^_

337 assert response.json() == { 1;=?@[]^_

338 "detail": [ 

339 { 

340 "type": "missing", 

341 "loc": [ 

342 "body", 

343 "p_val_alias", 

344 ], 

345 "msg": "Field required", 

346 "input": IsOneOf(None, {}), 

347 } 

348 ] 

349 } 

350 

351 

352@pytest.mark.parametrize( 1adbc

353 "path", 

354 [ 

355 "/required-alias-and-validation-alias", 

356 "/model-required-alias-and-validation-alias", 

357 ], 

358) 

359def test_required_alias_and_validation_alias_by_name(path: str): 1adbc

360 client = TestClient(app) 2` { | } ~ abbbcb

361 response = client.post(path, data={"p": "hello"}) 2` { | } ~ abbbcb

362 assert response.status_code == 422 2` { | } ~ abbbcb

363 

364 assert response.json() == { 2` { | } ~ abbbcb

365 "detail": [ 

366 { 

367 "type": "missing", 

368 "loc": [ 

369 "body", 

370 "p_val_alias", 

371 ], 

372 "msg": "Field required", 

373 "input": IsOneOf(None, {"p": "hello"}), 

374 } 

375 ] 

376 } 

377 

378 

379@pytest.mark.parametrize( 1adbc

380 "path", 

381 [ 

382 "/required-alias-and-validation-alias", 

383 "/model-required-alias-and-validation-alias", 

384 ], 

385) 

386def test_required_alias_and_validation_alias_by_alias(path: str): 1adbc

387 client = TestClient(app) 2dbebfbgbhbibjb

388 response = client.post(path, data={"p_alias": "hello"}) 2dbebfbgbhbibjb

389 assert response.status_code == 422, response.text 2dbebfbgbhbibjb

390 

391 assert response.json() == { 2dbebfbgbhbibjb

392 "detail": [ 

393 { 

394 "type": "missing", 

395 "loc": ["body", "p_val_alias"], 

396 "msg": "Field required", 

397 "input": IsOneOf(None, {"p_alias": "hello"}), 

398 } 

399 ] 

400 } 

401 

402 

403@pytest.mark.parametrize( 1adbc

404 "path", 

405 [ 

406 "/required-alias-and-validation-alias", 

407 "/model-required-alias-and-validation-alias", 

408 ], 

409) 

410def test_required_alias_and_validation_alias_by_validation_alias(path: str): 1adbc

411 client = TestClient(app) 1GCHDIEJF

412 response = client.post(path, data={"p_val_alias": "hello"}) 1GCHDIEJF

413 assert response.status_code == 200, response.text 1GCHDIEJF

414 

415 assert response.json() == {"p": "hello"} 1GCHDIEJF