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

30 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-12 18:15 +0000

1import importlib 1abdc

2 

3import pytest 1abdc

4from fastapi.testclient import TestClient 1abdc

5from inline_snapshot import snapshot 1abdc

6 

7from tests.utils import needs_py310 1abdc

8 

9 

10@pytest.fixture( 1abdc

11 name="client", 

12 params=[ 

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

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

15 ], 

16) 

17def get_client(request: pytest.FixtureRequest): 1abdc

18 mod = importlib.import_module(f"docs_src.query_param_models.{request.param}") 1abc

19 

20 client = TestClient(mod.app) 1abc

21 return client 1abc

22 

23 

24def test_query_param_model(client: TestClient): 1abdc

25 response = client.get( 1efg

26 "/items/", 

27 params={ 

28 "limit": 10, 

29 "offset": 5, 

30 "order_by": "updated_at", 

31 "tags": ["tag1", "tag2"], 

32 }, 

33 ) 

34 assert response.status_code == 200 1efg

35 assert response.json() == { 1efg

36 "limit": 10, 

37 "offset": 5, 

38 "order_by": "updated_at", 

39 "tags": ["tag1", "tag2"], 

40 } 

41 

42 

43def test_query_param_model_defaults(client: TestClient): 1abdc

44 response = client.get("/items/") 1hij

45 assert response.status_code == 200 1hij

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

47 "limit": 100, 

48 "offset": 0, 

49 "order_by": "created_at", 

50 "tags": [], 

51 } 

52 

53 

54def test_query_param_model_invalid(client: TestClient): 1abdc

55 response = client.get( 1klm

56 "/items/", 

57 params={ 

58 "limit": 150, 

59 "offset": -1, 

60 "order_by": "invalid", 

61 }, 

62 ) 

63 assert response.status_code == 422 1klm

64 assert response.json() == snapshot( 1klm

65 { 

66 "detail": [ 

67 { 

68 "type": "less_than_equal", 

69 "loc": ["query", "limit"], 

70 "msg": "Input should be less than or equal to 100", 

71 "input": "150", 

72 "ctx": {"le": 100}, 

73 }, 

74 { 

75 "type": "greater_than_equal", 

76 "loc": ["query", "offset"], 

77 "msg": "Input should be greater than or equal to 0", 

78 "input": "-1", 

79 "ctx": {"ge": 0}, 

80 }, 

81 { 

82 "type": "literal_error", 

83 "loc": ["query", "order_by"], 

84 "msg": "Input should be 'created_at' or 'updated_at'", 

85 "input": "invalid", 

86 "ctx": {"expected": "'created_at' or 'updated_at'"}, 

87 }, 

88 ] 

89 } 

90 ) 

91 

92 

93def test_query_param_model_extra(client: TestClient): 1abdc

94 response = client.get( 1nop

95 "/items/", 

96 params={ 

97 "limit": 10, 

98 "offset": 5, 

99 "order_by": "updated_at", 

100 "tags": ["tag1", "tag2"], 

101 "tool": "plumbus", 

102 }, 

103 ) 

104 assert response.status_code == 422 1nop

105 assert response.json() == snapshot( 1nop

106 { 

107 "detail": [ 

108 { 

109 "type": "extra_forbidden", 

110 "loc": ["query", "tool"], 

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

112 "input": "plumbus", 

113 } 

114 ] 

115 } 

116 ) 

117 

118 

119def test_openapi_schema(client: TestClient): 1abdc

120 response = client.get("/openapi.json") 1qrs

121 assert response.status_code == 200, response.text 1qrs

122 assert response.json() == snapshot( 1qrs

123 { 

124 "openapi": "3.1.0", 

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

126 "paths": { 

127 "/items/": { 

128 "get": { 

129 "summary": "Read Items", 

130 "operationId": "read_items_items__get", 

131 "parameters": [ 

132 { 

133 "name": "limit", 

134 "in": "query", 

135 "required": False, 

136 "schema": { 

137 "type": "integer", 

138 "maximum": 100, 

139 "exclusiveMinimum": 0, 

140 "default": 100, 

141 "title": "Limit", 

142 }, 

143 }, 

144 { 

145 "name": "offset", 

146 "in": "query", 

147 "required": False, 

148 "schema": { 

149 "type": "integer", 

150 "minimum": 0, 

151 "default": 0, 

152 "title": "Offset", 

153 }, 

154 }, 

155 { 

156 "name": "order_by", 

157 "in": "query", 

158 "required": False, 

159 "schema": { 

160 "enum": ["created_at", "updated_at"], 

161 "type": "string", 

162 "default": "created_at", 

163 "title": "Order By", 

164 }, 

165 }, 

166 { 

167 "name": "tags", 

168 "in": "query", 

169 "required": False, 

170 "schema": { 

171 "type": "array", 

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

173 "default": [], 

174 "title": "Tags", 

175 }, 

176 }, 

177 ], 

178 "responses": { 

179 "200": { 

180 "description": "Successful Response", 

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

182 }, 

183 "422": { 

184 "description": "Validation Error", 

185 "content": { 

186 "application/json": { 

187 "schema": { 

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

189 } 

190 } 

191 }, 

192 }, 

193 }, 

194 } 

195 } 

196 }, 

197 "components": { 

198 "schemas": { 

199 "HTTPValidationError": { 

200 "properties": { 

201 "detail": { 

202 "items": { 

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

204 }, 

205 "type": "array", 

206 "title": "Detail", 

207 } 

208 }, 

209 "type": "object", 

210 "title": "HTTPValidationError", 

211 }, 

212 "ValidationError": { 

213 "properties": { 

214 "ctx": {"title": "Context", "type": "object"}, 

215 "input": {"title": "Input"}, 

216 "loc": { 

217 "items": { 

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

219 }, 

220 "type": "array", 

221 "title": "Location", 

222 }, 

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

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

225 }, 

226 "type": "object", 

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

228 "title": "ValidationError", 

229 }, 

230 } 

231 }, 

232 } 

233 )