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

35 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

6from inline_snapshot import snapshot 1abcdef

7 

8from tests.utils import needs_py39, needs_py310 1abcdef

9 

10 

11@pytest.fixture( 1abcdef

12 name="client", 

13 params=[ 

14 "tutorial003", 

15 pytest.param("tutorial003_py39", marks=needs_py39), 

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

17 "tutorial003_an", 

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

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

20 ], 

21) 

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

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

24 

25 client = TestClient(mod.app) 1abcdef

26 return client 1abcdef

27 

28 

29def test_header_param_model(client: TestClient): 1abcdef

30 response = client.get( 1ghijkl

31 "/items/", 

32 headers=[ 

33 ("save_data", "true"), 

34 ("if_modified_since", "yesterday"), 

35 ("traceparent", "123"), 

36 ("x_tag", "one"), 

37 ("x_tag", "two"), 

38 ], 

39 ) 

40 assert response.status_code == 200 1ghijkl

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

42 "host": "testserver", 

43 "save_data": True, 

44 "if_modified_since": "yesterday", 

45 "traceparent": "123", 

46 "x_tag": ["one", "two"], 

47 } 

48 

49 

50def test_header_param_model_no_underscore(client: TestClient): 1abcdef

51 response = client.get( 1mnopqr

52 "/items/", 

53 headers=[ 

54 ("save-data", "true"), 

55 ("if-modified-since", "yesterday"), 

56 ("traceparent", "123"), 

57 ("x-tag", "one"), 

58 ("x-tag", "two"), 

59 ], 

60 ) 

61 assert response.status_code == 422 1mnopqr

62 assert response.json() == snapshot( 1mnopqr

63 { 

64 "detail": [ 

65 IsDict( 

66 { 

67 "type": "missing", 

68 "loc": ["header", "save_data"], 

69 "msg": "Field required", 

70 "input": { 

71 "host": "testserver", 

72 "traceparent": "123", 

73 "x_tag": [], 

74 "accept": "*/*", 

75 "accept-encoding": "gzip, deflate", 

76 "connection": "keep-alive", 

77 "user-agent": "testclient", 

78 "save-data": "true", 

79 "if-modified-since": "yesterday", 

80 "x-tag": "two", 

81 }, 

82 } 

83 ) 

84 | IsDict( 

85 # TODO: remove when deprecating Pydantic v1 

86 { 

87 "type": "value_error.missing", 

88 "loc": ["header", "save_data"], 

89 "msg": "field required", 

90 } 

91 ) 

92 ] 

93 } 

94 ) 

95 

96 

97def test_header_param_model_defaults(client: TestClient): 1abcdef

98 response = client.get("/items/", headers=[("save_data", "true")]) 1stuvwx

99 assert response.status_code == 200 1stuvwx

100 assert response.json() == { 1stuvwx

101 "host": "testserver", 

102 "save_data": True, 

103 "if_modified_since": None, 

104 "traceparent": None, 

105 "x_tag": [], 

106 } 

107 

108 

109def test_header_param_model_invalid(client: TestClient): 1abcdef

110 response = client.get("/items/") 1yzABCD

111 assert response.status_code == 422 1yzABCD

112 assert response.json() == snapshot( 1yzABCD

113 { 

114 "detail": [ 

115 IsDict( 

116 { 

117 "type": "missing", 

118 "loc": ["header", "save_data"], 

119 "msg": "Field required", 

120 "input": { 

121 "x_tag": [], 

122 "host": "testserver", 

123 "accept": "*/*", 

124 "accept-encoding": "gzip, deflate", 

125 "connection": "keep-alive", 

126 "user-agent": "testclient", 

127 }, 

128 } 

129 ) 

130 | IsDict( 

131 # TODO: remove when deprecating Pydantic v1 

132 { 

133 "type": "value_error.missing", 

134 "loc": ["header", "save_data"], 

135 "msg": "field required", 

136 } 

137 ) 

138 ] 

139 } 

140 ) 

141 

142 

143def test_header_param_model_extra(client: TestClient): 1abcdef

144 response = client.get( 1EFGHIJ

145 "/items/", headers=[("save_data", "true"), ("tool", "plumbus")] 

146 ) 

147 assert response.status_code == 200, response.text 1EFGHIJ

148 assert response.json() == snapshot( 1EFGHIJ

149 { 

150 "host": "testserver", 

151 "save_data": True, 

152 "if_modified_since": None, 

153 "traceparent": None, 

154 "x_tag": [], 

155 } 

156 ) 

157 

158 

159def test_openapi_schema(client: TestClient): 1abcdef

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

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

162 assert response.json() == snapshot( 1KLMNOP

163 { 

164 "openapi": "3.1.0", 

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

166 "paths": { 

167 "/items/": { 

168 "get": { 

169 "summary": "Read Items", 

170 "operationId": "read_items_items__get", 

171 "parameters": [ 

172 { 

173 "name": "host", 

174 "in": "header", 

175 "required": True, 

176 "schema": {"type": "string", "title": "Host"}, 

177 }, 

178 { 

179 "name": "save_data", 

180 "in": "header", 

181 "required": True, 

182 "schema": {"type": "boolean", "title": "Save Data"}, 

183 }, 

184 { 

185 "name": "if_modified_since", 

186 "in": "header", 

187 "required": False, 

188 "schema": IsDict( 

189 { 

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

191 "title": "If Modified Since", 

192 } 

193 ) 

194 | IsDict( 

195 # TODO: remove when deprecating Pydantic v1 

196 { 

197 "type": "string", 

198 "title": "If Modified Since", 

199 } 

200 ), 

201 }, 

202 { 

203 "name": "traceparent", 

204 "in": "header", 

205 "required": False, 

206 "schema": IsDict( 

207 { 

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

209 "title": "Traceparent", 

210 } 

211 ) 

212 | IsDict( 

213 # TODO: remove when deprecating Pydantic v1 

214 { 

215 "type": "string", 

216 "title": "Traceparent", 

217 } 

218 ), 

219 }, 

220 { 

221 "name": "x_tag", 

222 "in": "header", 

223 "required": False, 

224 "schema": { 

225 "type": "array", 

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

227 "default": [], 

228 "title": "X Tag", 

229 }, 

230 }, 

231 ], 

232 "responses": { 

233 "200": { 

234 "description": "Successful Response", 

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

236 }, 

237 "422": { 

238 "description": "Validation Error", 

239 "content": { 

240 "application/json": { 

241 "schema": { 

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

243 } 

244 } 

245 }, 

246 }, 

247 }, 

248 } 

249 } 

250 }, 

251 "components": { 

252 "schemas": { 

253 "HTTPValidationError": { 

254 "properties": { 

255 "detail": { 

256 "items": { 

257 "$ref": "#/components/schemas/ValidationError" 

258 }, 

259 "type": "array", 

260 "title": "Detail", 

261 } 

262 }, 

263 "type": "object", 

264 "title": "HTTPValidationError", 

265 }, 

266 "ValidationError": { 

267 "properties": { 

268 "loc": { 

269 "items": { 

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

271 }, 

272 "type": "array", 

273 "title": "Location", 

274 }, 

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

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

277 }, 

278 "type": "object", 

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

280 "title": "ValidationError", 

281 }, 

282 } 

283 }, 

284 } 

285 )