Coverage for tests / test_request_params / test_header / 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 AnyThing, IsOneOf, IsPartialDict 1adbc

5from fastapi import FastAPI, Header 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], Header()]): 1adbc

18 return {"p": p} 1efgh

19 

20 

21class HeaderModelRequiredListStr(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[HeaderModelRequiredListStr, Header()]): 1adbc

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

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( 2kblbmbnbobpbqbrb

36 [ 

37 { 

38 "required": True, 

39 "schema": { 

40 "title": "P", 

41 "type": "array", 

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

43 }, 

44 "name": "p", 

45 "in": "header", 

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) 1KLMNOPQR

57 response = client.get(path) 1KLMNOPQR

58 assert response.status_code == 422 1KLMNOPQR

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

60 "detail": [ 

61 { 

62 "type": "missing", 

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

64 "msg": "Field required", 

65 "input": AnyThing, 

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) 1iejfkglh

77 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1iejfkglh

78 assert response.status_code == 200 1iejfkglh

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

80 

81 

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

83# Alias 

84 

85 

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

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

88 return {"p": p} 1mnop

89 

90 

91class HeaderModelRequiredListAlias(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[HeaderModelRequiredListAlias, Header()], 

98): 

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

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( 2sbtbubvbwbxbybzb

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": "header", 

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) 1STUVWXYZ

129 response = client.get(path) 1STUVWXYZ

130 assert response.status_code == 422 1STUVWXYZ

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

132 "detail": [ 

133 { 

134 "type": "missing", 

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

136 "msg": "Field required", 

137 "input": AnyThing, 

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) 101234567

152 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 101234567

153 assert response.status_code == 422 101234567

154 assert response.json() == { 101234567

155 "detail": [ 

156 { 

157 "type": "missing", 

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

159 "msg": "Field required", 

160 "input": IsOneOf(None, IsPartialDict({"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) 1qmrnsotp

175 response = client.get(path, headers=[("p_alias", "hello"), ("p_alias", "world")]) 1qmrnsotp

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

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

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], Header(validation_alias="p_val_alias")], 

187): 

188 return {"p": p} 1uvwx

189 

190 

191class HeaderModelRequiredListValidationAlias(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[HeaderModelRequiredListValidationAlias, Header()], 

198): 

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

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( 2AbBbCbDbEbFbGbHb

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": "header", 

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) 189!#$%'(

232 response = client.get(path) 189!#$%'(

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

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

235 "detail": [ 

236 { 

237 "type": "missing", 

238 "loc": [ 

239 "header", 

240 "p_val_alias", 

241 ], 

242 "msg": "Field required", 

243 "input": AnyThing, 

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) 1)*+,-./

258 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 1)*+,-./

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

260 

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

262 "detail": [ 

263 { 

264 "type": "missing", 

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

266 "msg": "Field required", 

267 "input": IsOneOf(None, IsPartialDict({"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) 1yuzvAwBx

279 response = client.get( 1yuzvAwBx

280 path, headers=[("p_val_alias", "hello"), ("p_val_alias", "world")] 

281 ) 

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

283 

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

285 

286 

287# ===================================================================================== 

288# Alias and validation alias 

289 

290 

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

292def read_required_list_alias_and_validation_alias( 1adbc

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

294): 

295 return {"p": p} 1CDEF

296 

297 

298class HeaderModelRequiredListAliasAndValidationAlias(BaseModel): 1adbc

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

300 

301 

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

303def read_model_required_list_alias_and_validation_alias( 1adbc

304 p: Annotated[HeaderModelRequiredListAliasAndValidationAlias, Header()], 

305): 

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

307 

308 

309@pytest.mark.parametrize( 1adbc

310 "path", 

311 [ 

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

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

314 ], 

315) 

316def test_required_list_alias_and_validation_alias_schema(path: str): 1adbc

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

318 [ 

319 { 

320 "required": True, 

321 "schema": { 

322 "title": "P Val Alias", 

323 "type": "array", 

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

325 }, 

326 "name": "p_val_alias", 

327 "in": "header", 

328 } 

329 ] 

330 ) 

331 

332 

333@pytest.mark.parametrize( 1adbc

334 "path", 

335 [ 

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

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

338 ], 

339) 

340def test_required_list_alias_and_validation_alias_missing(path: str): 1adbc

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

342 response = client.get(path) 1:;=?@[]^

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

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

345 "detail": [ 

346 { 

347 "type": "missing", 

348 "loc": [ 

349 "header", 

350 "p_val_alias", 

351 ], 

352 "msg": "Field required", 

353 "input": AnyThing, 

354 } 

355 ] 

356 } 

357 

358 

359@pytest.mark.parametrize( 1adbc

360 "path", 

361 [ 

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

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

364 ], 

365) 

366def test_required_list_alias_and_validation_alias_by_name(path: str): 1adbc

367 client = TestClient(app) 2_ ` { | } ~ abbb

368 response = client.get(path, headers=[("p", "hello"), ("p", "world")]) 2_ ` { | } ~ abbb

369 assert response.status_code == 422 2_ ` { | } ~ abbb

370 assert response.json() == { 2_ ` { | } ~ abbb

371 "detail": [ 

372 { 

373 "type": "missing", 

374 "loc": [ 

375 "header", 

376 "p_val_alias", 

377 ], 

378 "msg": "Field required", 

379 "input": IsOneOf( 

380 None, 

381 IsPartialDict({"p": ["hello", "world"]}), 

382 ), 

383 } 

384 ] 

385 } 

386 

387 

388@pytest.mark.parametrize( 1adbc

389 "path", 

390 [ 

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

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

393 ], 

394) 

395def test_required_list_alias_and_validation_alias_by_alias(path: str): 1adbc

396 client = TestClient(app) 2cbdbebfbgbhbibjb

397 response = client.get(path, headers=[("p_alias", "hello"), ("p_alias", "world")]) 2cbdbebfbgbhbibjb

398 assert response.status_code == 422 2cbdbebfbgbhbibjb

399 assert response.json() == { 2cbdbebfbgbhbibjb

400 "detail": [ 

401 { 

402 "type": "missing", 

403 "loc": ["header", "p_val_alias"], 

404 "msg": "Field required", 

405 "input": IsOneOf( 

406 None, 

407 IsPartialDict({"p_alias": ["hello", "world"]}), 

408 ), 

409 } 

410 ] 

411 } 

412 

413 

414@pytest.mark.parametrize( 1adbc

415 "path", 

416 [ 

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

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

419 ], 

420) 

421def test_required_list_alias_and_validation_alias_by_validation_alias(path: str): 1adbc

422 client = TestClient(app) 1GCHDIEJF

423 response = client.get( 1GCHDIEJF

424 path, headers=[("p_val_alias", "hello"), ("p_val_alias", "world")] 

425 ) 

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

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