Coverage for tests / test_request_params / test_query / test_list.py: 100%

124 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, Query 1adbc

6from fastapi.testclient import TestClient 1adbc

7from inline_snapshot import snapshot 1adbc

8from pydantic import BaseModel, Field 1adbc

9 

10app = FastAPI() 1adbc

11 

12# ===================================================================================== 

13# Without aliases 

14 

15 

16@app.get("/required-list-str") 1adbc

17async def read_required_list_str(p: Annotated[list[str], Query()]): 1adbc

18 return {"p": p} 1efgh

19 

20 

21class QueryModelRequiredListStr(BaseModel): 1adbc

22 p: list[str] 1abc

23 

24 

25@app.get("/model-required-list-str") 1adbc

26def read_model_required_list_str(p: Annotated[QueryModelRequiredListStr, Query()]): 1adbc

27 return {"p": p.p} 2i bbj k

28 

29 

30@pytest.mark.parametrize( 1adbc

31 "path", 

32 ["/required-list-str", "/model-required-list-str"], 

33) 

34def test_required_list_str_schema(path: str): 1adbc

35 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2cbdbebfbgbhbib

36 [ 

37 { 

38 "required": True, 

39 "schema": { 

40 "title": "P", 

41 "type": "array", 

42 "items": {"type": "string"}, 

43 }, 

44 "name": "p", 

45 "in": "query", 

46 } 

47 ] 

48 ) 

49 

50 

51@pytest.mark.parametrize( 1adbc

52 "path", 

53 ["/required-list-str", "/model-required-list-str"], 

54) 

55def test_required_list_str_missing(path: str): 1adbc

56 client = TestClient(app) 1HIJKLMN

57 response = client.get(path) 1HIJKLMN

58 assert response.status_code == 422 1HIJKLMN

59 assert response.json() == { 1HIJKLMN

60 "detail": [ 

61 { 

62 "type": "missing", 

63 "loc": ["query", "p"], 

64 "msg": "Field required", 

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

66 } 

67 ] 

68 } 

69 

70 

71@pytest.mark.parametrize( 1adbc

72 "path", 

73 ["/required-list-str", "/model-required-list-str"], 

74) 

75def test_required_list_str(path: str): 1adbc

76 client = TestClient(app) 1iefjgkh

77 response = client.get(f"{path}?p=hello&p=world") 1iefjgkh

78 assert response.status_code == 200 1iefjgkh

79 assert response.json() == {"p": ["hello", "world"]} 1iefjgkh

80 

81 

82# ===================================================================================== 

83# Alias 

84 

85 

86@app.get("/required-list-alias") 1adbc

87async def read_required_list_alias(p: Annotated[list[str], Query(alias="p_alias")]): 1adbc

88 return {"p": p} 1lmno

89 

90 

91class QueryModelRequiredListAlias(BaseModel): 1adbc

92 p: list[str] = Field(alias="p_alias") 1adbc

93 

94 

95@app.get("/model-required-list-alias") 1adbc

96async def read_model_required_list_alias( 1adbc

97 p: Annotated[QueryModelRequiredListAlias, Query()], 

98): 

99 return {"p": p.p} 2p jbq r

100 

101 

102@pytest.mark.parametrize( 1adbc

103 "path", 

104 ["/required-list-alias", "/model-required-list-alias"], 

105) 

106def test_required_list_str_alias_schema(path: str): 1adbc

107 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2kblbmbnbobpbqb

108 [ 

109 { 

110 "required": True, 

111 "schema": { 

112 "title": "P Alias", 

113 "type": "array", 

114 "items": {"type": "string"}, 

115 }, 

116 "name": "p_alias", 

117 "in": "query", 

118 } 

119 ] 

120 ) 

121 

122 

123@pytest.mark.parametrize( 1adbc

124 "path", 

125 ["/required-list-alias", "/model-required-list-alias"], 

126) 

127def test_required_list_alias_missing(path: str): 1adbc

128 client = TestClient(app) 1OPQRSTU

129 response = client.get(path) 1OPQRSTU

130 assert response.status_code == 422 1OPQRSTU

131 assert response.json() == { 1OPQRSTU

132 "detail": [ 

133 { 

134 "type": "missing", 

135 "loc": ["query", "p_alias"], 

136 "msg": "Field required", 

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

138 } 

139 ] 

140 } 

141 

142 

143@pytest.mark.parametrize( 1adbc

144 "path", 

145 [ 

146 "/required-list-alias", 

147 "/model-required-list-alias", 

148 ], 

149) 

150def test_required_list_alias_by_name(path: str): 1adbc

151 client = TestClient(app) 1VWXYZ01

152 response = client.get(f"{path}?p=hello&p=world") 1VWXYZ01

153 assert response.status_code == 422 1VWXYZ01

154 assert response.json() == { 1VWXYZ01

155 "detail": [ 

156 { 

157 "type": "missing", 

158 "loc": ["query", "p_alias"], 

159 "msg": "Field required", 

160 "input": IsOneOf(None, {"p": ["hello", "world"]}), 

161 } 

162 ] 

163 } 

164 

165 

166@pytest.mark.parametrize( 1adbc

167 "path", 

168 [ 

169 "/required-list-alias", 

170 "/model-required-list-alias", 

171 ], 

172) 

173def test_required_list_alias_by_alias(path: str): 1adbc

174 client = TestClient(app) 1plmqnro

175 response = client.get(f"{path}?p_alias=hello&p_alias=world") 1plmqnro

176 assert response.status_code == 200, response.text 1plmqnro

177 assert response.json() == {"p": ["hello", "world"]} 1plmqnro

178 

179 

180# ===================================================================================== 

181# Validation alias 

182 

183 

184@app.get("/required-list-validation-alias") 1adbc

185def read_required_list_validation_alias( 1adbc

186 p: Annotated[list[str], Query(validation_alias="p_val_alias")], 

187): 

188 return {"p": p} 1stuv

189 

190 

191class QueryModelRequiredListValidationAlias(BaseModel): 1adbc

192 p: list[str] = Field(validation_alias="p_val_alias") 1adbc

193 

194 

195@app.get("/model-required-list-validation-alias") 1adbc

196async def read_model_required_list_validation_alias( 1adbc

197 p: Annotated[QueryModelRequiredListValidationAlias, Query()], 

198): 

199 return {"p": p.p} 2w rbx y

200 

201 

202@pytest.mark.parametrize( 1adbc

203 "path", 

204 ["/required-list-validation-alias", "/model-required-list-validation-alias"], 

205) 

206def test_required_list_validation_alias_schema(path: str): 1adbc

207 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2sbtbubvbwbxbyb

208 [ 

209 { 

210 "required": True, 

211 "schema": { 

212 "title": "P Val Alias", 

213 "type": "array", 

214 "items": {"type": "string"}, 

215 }, 

216 "name": "p_val_alias", 

217 "in": "query", 

218 } 

219 ] 

220 ) 

221 

222 

223@pytest.mark.parametrize( 1adbc

224 "path", 

225 [ 

226 "/required-list-validation-alias", 

227 "/model-required-list-validation-alias", 

228 ], 

229) 

230def test_required_list_validation_alias_missing(path: str): 1adbc

231 client = TestClient(app) 12345678

232 response = client.get(path) 12345678

233 assert response.status_code == 422 12345678

234 assert response.json() == { 12345678

235 "detail": [ 

236 { 

237 "type": "missing", 

238 "loc": [ 

239 "query", 

240 "p_val_alias", 

241 ], 

242 "msg": "Field required", 

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

244 } 

245 ] 

246 } 

247 

248 

249@pytest.mark.parametrize( 1adbc

250 "path", 

251 [ 

252 "/required-list-validation-alias", 

253 "/model-required-list-validation-alias", 

254 ], 

255) 

256def test_required_list_validation_alias_by_name(path: str): 1adbc

257 client = TestClient(app) 19!#$%'(

258 response = client.get(f"{path}?p=hello&p=world") 19!#$%'(

259 assert response.status_code == 422 19!#$%'(

260 

261 assert response.json() == { 19!#$%'(

262 "detail": [ 

263 { 

264 "type": "missing", 

265 "loc": ["query", "p_val_alias"], 

266 "msg": "Field required", 

267 "input": IsOneOf(None, {"p": ["hello", "world"]}), 

268 } 

269 ] 

270 } 

271 

272 

273@pytest.mark.parametrize( 1adbc

274 "path", 

275 ["/required-list-validation-alias", "/model-required-list-validation-alias"], 

276) 

277def test_required_list_validation_alias_by_validation_alias(path: str): 1adbc

278 client = TestClient(app) 1wstxuyv

279 response = client.get(f"{path}?p_val_alias=hello&p_val_alias=world") 1wstxuyv

280 assert response.status_code == 200, response.text 1wstxuyv

281 

282 assert response.json() == {"p": ["hello", "world"]} 1wstxuyv

283 

284 

285# ===================================================================================== 

286# Alias and validation alias 

287 

288 

289@app.get("/required-list-alias-and-validation-alias") 1adbc

290def read_required_list_alias_and_validation_alias( 1adbc

291 p: Annotated[list[str], Query(alias="p_alias", validation_alias="p_val_alias")], 

292): 

293 return {"p": p} 1zABC

294 

295 

296class QueryModelRequiredListAliasAndValidationAlias(BaseModel): 1adbc

297 p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias") 1adbc

298 

299 

300@app.get("/model-required-list-alias-and-validation-alias") 1adbc

301def read_model_required_list_alias_and_validation_alias( 1adbc

302 p: Annotated[QueryModelRequiredListAliasAndValidationAlias, Query()], 

303): 

304 return {"p": p.p} 1DEFG

305 

306 

307@pytest.mark.parametrize( 1adbc

308 "path", 

309 [ 

310 "/required-list-alias-and-validation-alias", 

311 "/model-required-list-alias-and-validation-alias", 

312 ], 

313) 

314def test_required_list_alias_and_validation_alias_schema(path: str): 1adbc

315 assert app.openapi()["paths"][path]["get"]["parameters"] == snapshot( 2zbAbBbCbDbEbFbGb

316 [ 

317 { 

318 "required": True, 

319 "schema": { 

320 "title": "P Val Alias", 

321 "type": "array", 

322 "items": {"type": "string"}, 

323 }, 

324 "name": "p_val_alias", 

325 "in": "query", 

326 } 

327 ] 

328 ) 

329 

330 

331@pytest.mark.parametrize( 1adbc

332 "path", 

333 [ 

334 "/required-list-alias-and-validation-alias", 

335 "/model-required-list-alias-and-validation-alias", 

336 ], 

337) 

338def test_required_list_alias_and_validation_alias_missing(path: str): 1adbc

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

340 response = client.get(path) 1)*+,-./:

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

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

343 "detail": [ 

344 { 

345 "type": "missing", 

346 "loc": [ 

347 "query", 

348 "p_val_alias", 

349 ], 

350 "msg": "Field required", 

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

352 } 

353 ] 

354 } 

355 

356 

357@pytest.mark.parametrize( 1adbc

358 "path", 

359 [ 

360 "/required-list-alias-and-validation-alias", 

361 "/model-required-list-alias-and-validation-alias", 

362 ], 

363) 

364def test_required_list_alias_and_validation_alias_by_name(path: str): 1adbc

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

366 response = client.get(f"{path}?p=hello&p=world") 1;=?@[]^

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

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

369 "detail": [ 

370 { 

371 "type": "missing", 

372 "loc": [ 

373 "query", 

374 "p_val_alias", 

375 ], 

376 "msg": "Field required", 

377 "input": IsOneOf( 

378 None, 

379 { 

380 "p": [ 

381 "hello", 

382 "world", 

383 ] 

384 }, 

385 ), 

386 } 

387 ] 

388 } 

389 

390 

391@pytest.mark.parametrize( 1adbc

392 "path", 

393 [ 

394 "/required-list-alias-and-validation-alias", 

395 "/model-required-list-alias-and-validation-alias", 

396 ], 

397) 

398def test_required_list_alias_and_validation_alias_by_alias(path: str): 1adbc

399 client = TestClient(app) 2_ ` { | } ~ ab

400 response = client.get(f"{path}?p_alias=hello&p_alias=world") 2_ ` { | } ~ ab

401 assert response.status_code == 422 2_ ` { | } ~ ab

402 assert response.json() == { 2_ ` { | } ~ ab

403 "detail": [ 

404 { 

405 "type": "missing", 

406 "loc": ["query", "p_val_alias"], 

407 "msg": "Field required", 

408 "input": IsOneOf( 

409 None, 

410 {"p_alias": ["hello", "world"]}, 

411 ), 

412 } 

413 ] 

414 } 

415 

416 

417@pytest.mark.parametrize( 1adbc

418 "path", 

419 [ 

420 "/required-list-alias-and-validation-alias", 

421 "/model-required-list-alias-and-validation-alias", 

422 ], 

423) 

424def test_required_list_alias_and_validation_alias_by_validation_alias(path: str): 1adbc

425 client = TestClient(app) 1DzEAFBGC

426 response = client.get(f"{path}?p_val_alias=hello&p_val_alias=world") 1DzEAFBGC

427 assert response.status_code == 200, response.text 1DzEAFBGC

428 assert response.json() == {"p": ["hello", "world"]} 1DzEAFBGC