Coverage for tests / test_tutorial / test_query_param_models / test_tutorial001.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("tutorial001_py310", marks=needs_py310), 

14 pytest.param("tutorial001_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 == 200 1nop

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

106 "limit": 10, 

107 "offset": 5, 

108 "order_by": "updated_at", 

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

110 } 

111 

112 

113def test_openapi_schema(client: TestClient): 1abdc

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

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

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

117 { 

118 "openapi": "3.1.0", 

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

120 "paths": { 

121 "/items/": { 

122 "get": { 

123 "summary": "Read Items", 

124 "operationId": "read_items_items__get", 

125 "parameters": [ 

126 { 

127 "name": "limit", 

128 "in": "query", 

129 "required": False, 

130 "schema": { 

131 "type": "integer", 

132 "maximum": 100, 

133 "exclusiveMinimum": 0, 

134 "default": 100, 

135 "title": "Limit", 

136 }, 

137 }, 

138 { 

139 "name": "offset", 

140 "in": "query", 

141 "required": False, 

142 "schema": { 

143 "type": "integer", 

144 "minimum": 0, 

145 "default": 0, 

146 "title": "Offset", 

147 }, 

148 }, 

149 { 

150 "name": "order_by", 

151 "in": "query", 

152 "required": False, 

153 "schema": { 

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

155 "type": "string", 

156 "default": "created_at", 

157 "title": "Order By", 

158 }, 

159 }, 

160 { 

161 "name": "tags", 

162 "in": "query", 

163 "required": False, 

164 "schema": { 

165 "type": "array", 

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

167 "default": [], 

168 "title": "Tags", 

169 }, 

170 }, 

171 ], 

172 "responses": { 

173 "200": { 

174 "description": "Successful Response", 

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

176 }, 

177 "422": { 

178 "description": "Validation Error", 

179 "content": { 

180 "application/json": { 

181 "schema": { 

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

183 } 

184 } 

185 }, 

186 }, 

187 }, 

188 } 

189 } 

190 }, 

191 "components": { 

192 "schemas": { 

193 "HTTPValidationError": { 

194 "properties": { 

195 "detail": { 

196 "items": { 

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

198 }, 

199 "type": "array", 

200 "title": "Detail", 

201 } 

202 }, 

203 "type": "object", 

204 "title": "HTTPValidationError", 

205 }, 

206 "ValidationError": { 

207 "properties": { 

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

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

210 "loc": { 

211 "items": { 

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

213 }, 

214 "type": "array", 

215 "title": "Location", 

216 }, 

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

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

219 }, 

220 "type": "object", 

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

222 "title": "ValidationError", 

223 }, 

224 } 

225 }, 

226 } 

227 )