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

32 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-01-13 13:38 +0000

1import importlib 1abcde

2 

3import pytest 1abcde

4from dirty_equals import IsDict 1abcde

5from fastapi.testclient import TestClient 1abcde

6from inline_snapshot import snapshot 1abcde

7 

8from tests.utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2 1abcde

9 

10 

11@pytest.fixture( 1abcde

12 name="client", 

13 params=[ 

14 pytest.param("tutorial002", marks=needs_pydanticv2), 

15 pytest.param("tutorial002_py310", marks=[needs_py310, needs_pydanticv2]), 

16 pytest.param("tutorial002_an", marks=needs_pydanticv2), 

17 pytest.param("tutorial002_an_py39", marks=[needs_py39, needs_pydanticv2]), 

18 pytest.param("tutorial002_an_py310", marks=[needs_py310, needs_pydanticv2]), 

19 pytest.param("tutorial002_pv1", marks=[needs_pydanticv1, needs_pydanticv1]), 

20 pytest.param("tutorial002_pv1_py310", marks=[needs_py310, needs_pydanticv1]), 

21 pytest.param("tutorial002_pv1_an", marks=[needs_pydanticv1]), 

22 pytest.param("tutorial002_pv1_an_py39", marks=[needs_py39, needs_pydanticv1]), 

23 pytest.param("tutorial002_pv1_an_py310", marks=[needs_py310, needs_pydanticv1]), 

24 ], 

25) 

26def get_client(request: pytest.FixtureRequest): 1abcde

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

28 

29 client = TestClient(mod.app) 1abcde

30 client.headers.clear() 1abcde

31 return client 1abcde

32 

33 

34def test_header_param_model(client: TestClient): 1abcde

35 response = client.get( 1fghij

36 "/items/", 

37 headers=[ 

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

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

40 ("traceparent", "123"), 

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

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

43 ], 

44 ) 

45 assert response.status_code == 200, response.text 1fghij

46 assert response.json() == { 1fghij

47 "host": "testserver", 

48 "save_data": True, 

49 "if_modified_since": "yesterday", 

50 "traceparent": "123", 

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

52 } 

53 

54 

55def test_header_param_model_defaults(client: TestClient): 1abcde

56 response = client.get("/items/", headers=[("save-data", "true")]) 1klmno

57 assert response.status_code == 200 1klmno

58 assert response.json() == { 1klmno

59 "host": "testserver", 

60 "save_data": True, 

61 "if_modified_since": None, 

62 "traceparent": None, 

63 "x_tag": [], 

64 } 

65 

66 

67def test_header_param_model_invalid(client: TestClient): 1abcde

68 response = client.get("/items/") 1pqrst

69 assert response.status_code == 422 1pqrst

70 assert response.json() == snapshot( 1pqrst

71 { 

72 "detail": [ 

73 IsDict( 

74 { 

75 "type": "missing", 

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

77 "msg": "Field required", 

78 "input": {"x_tag": [], "host": "testserver"}, 

79 } 

80 ) 

81 | IsDict( 

82 # TODO: remove when deprecating Pydantic v1 

83 { 

84 "type": "value_error.missing", 

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

86 "msg": "field required", 

87 } 

88 ) 

89 ] 

90 } 

91 ) 

92 

93 

94def test_header_param_model_extra(client: TestClient): 1abcde

95 response = client.get( 1uvwxy

96 "/items/", headers=[("save-data", "true"), ("tool", "plumbus")] 

97 ) 

98 assert response.status_code == 422, response.text 1uvwxy

99 assert response.json() == snapshot( 1uvwxy

100 { 

101 "detail": [ 

102 IsDict( 

103 { 

104 "type": "extra_forbidden", 

105 "loc": ["header", "tool"], 

106 "msg": "Extra inputs are not permitted", 

107 "input": "plumbus", 

108 } 

109 ) 

110 | IsDict( 

111 # TODO: remove when deprecating Pydantic v1 

112 { 

113 "type": "value_error.extra", 

114 "loc": ["header", "tool"], 

115 "msg": "extra fields not permitted", 

116 } 

117 ) 

118 ] 

119 } 

120 ) 

121 

122 

123def test_openapi_schema(client: TestClient): 1abcde

124 response = client.get("/openapi.json") 1zABCD

125 assert response.status_code == 200, response.text 1zABCD

126 assert response.json() == snapshot( 1zABCD

127 { 

128 "openapi": "3.1.0", 

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

130 "paths": { 

131 "/items/": { 

132 "get": { 

133 "summary": "Read Items", 

134 "operationId": "read_items_items__get", 

135 "parameters": [ 

136 { 

137 "name": "host", 

138 "in": "header", 

139 "required": True, 

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

141 }, 

142 { 

143 "name": "save_data", 

144 "in": "header", 

145 "required": True, 

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

147 }, 

148 { 

149 "name": "if_modified_since", 

150 "in": "header", 

151 "required": False, 

152 "schema": IsDict( 

153 { 

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

155 "title": "If Modified Since", 

156 } 

157 ) 

158 | IsDict( 

159 # TODO: remove when deprecating Pydantic v1 

160 { 

161 "type": "string", 

162 "title": "If Modified Since", 

163 } 

164 ), 

165 }, 

166 { 

167 "name": "traceparent", 

168 "in": "header", 

169 "required": False, 

170 "schema": IsDict( 

171 { 

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

173 "title": "Traceparent", 

174 } 

175 ) 

176 | IsDict( 

177 # TODO: remove when deprecating Pydantic v1 

178 { 

179 "type": "string", 

180 "title": "Traceparent", 

181 } 

182 ), 

183 }, 

184 { 

185 "name": "x_tag", 

186 "in": "header", 

187 "required": False, 

188 "schema": { 

189 "type": "array", 

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

191 "default": [], 

192 "title": "X Tag", 

193 }, 

194 }, 

195 ], 

196 "responses": { 

197 "200": { 

198 "description": "Successful Response", 

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

200 }, 

201 "422": { 

202 "description": "Validation Error", 

203 "content": { 

204 "application/json": { 

205 "schema": { 

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

207 } 

208 } 

209 }, 

210 }, 

211 }, 

212 } 

213 } 

214 }, 

215 "components": { 

216 "schemas": { 

217 "HTTPValidationError": { 

218 "properties": { 

219 "detail": { 

220 "items": { 

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

222 }, 

223 "type": "array", 

224 "title": "Detail", 

225 } 

226 }, 

227 "type": "object", 

228 "title": "HTTPValidationError", 

229 }, 

230 "ValidationError": { 

231 "properties": { 

232 "loc": { 

233 "items": { 

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

235 }, 

236 "type": "array", 

237 "title": "Location", 

238 }, 

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

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

241 }, 

242 "type": "object", 

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

244 "title": "ValidationError", 

245 }, 

246 } 

247 }, 

248 } 

249 )