Coverage for tests/test_tutorial/test_query_param_models/test_tutorial001.py: 100%
31 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-01-13 13:38 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-01-13 13:38 +0000
1import importlib 1abcde
3import pytest 1abcde
4from dirty_equals import IsDict 1abcde
5from fastapi.testclient import TestClient 1abcde
6from inline_snapshot import snapshot 1abcde
8from tests.utils import needs_py39, needs_py310 1abcde
11@pytest.fixture( 1abcde
12 name="client",
13 params=[
14 "tutorial001",
15 pytest.param("tutorial001_py39", marks=needs_py39),
16 pytest.param("tutorial001_py310", marks=needs_py310),
17 "tutorial001_an",
18 pytest.param("tutorial001_an_py39", marks=needs_py39),
19 pytest.param("tutorial001_an_py310", marks=needs_py310),
20 ],
21)
22def get_client(request: pytest.FixtureRequest): 1abcde
23 mod = importlib.import_module(f"docs_src.query_param_models.{request.param}") 1abcde
25 client = TestClient(mod.app) 1abcde
26 return client 1abcde
29def test_query_param_model(client: TestClient): 1abcde
30 response = client.get( 1fghij
31 "/items/",
32 params={
33 "limit": 10,
34 "offset": 5,
35 "order_by": "updated_at",
36 "tags": ["tag1", "tag2"],
37 },
38 )
39 assert response.status_code == 200 1fghij
40 assert response.json() == { 1fghij
41 "limit": 10,
42 "offset": 5,
43 "order_by": "updated_at",
44 "tags": ["tag1", "tag2"],
45 }
48def test_query_param_model_defaults(client: TestClient): 1abcde
49 response = client.get("/items/") 1klmno
50 assert response.status_code == 200 1klmno
51 assert response.json() == { 1klmno
52 "limit": 100,
53 "offset": 0,
54 "order_by": "created_at",
55 "tags": [],
56 }
59def test_query_param_model_invalid(client: TestClient): 1abcde
60 response = client.get( 1pqrst
61 "/items/",
62 params={
63 "limit": 150,
64 "offset": -1,
65 "order_by": "invalid",
66 },
67 )
68 assert response.status_code == 422 1pqrst
69 assert response.json() == snapshot( 1pqrst
70 IsDict(
71 {
72 "detail": [
73 {
74 "type": "less_than_equal",
75 "loc": ["query", "limit"],
76 "msg": "Input should be less than or equal to 100",
77 "input": "150",
78 "ctx": {"le": 100},
79 },
80 {
81 "type": "greater_than_equal",
82 "loc": ["query", "offset"],
83 "msg": "Input should be greater than or equal to 0",
84 "input": "-1",
85 "ctx": {"ge": 0},
86 },
87 {
88 "type": "literal_error",
89 "loc": ["query", "order_by"],
90 "msg": "Input should be 'created_at' or 'updated_at'",
91 "input": "invalid",
92 "ctx": {"expected": "'created_at' or 'updated_at'"},
93 },
94 ]
95 }
96 )
97 | IsDict(
98 # TODO: remove when deprecating Pydantic v1
99 {
100 "detail": [
101 {
102 "type": "value_error.number.not_le",
103 "loc": ["query", "limit"],
104 "msg": "ensure this value is less than or equal to 100",
105 "ctx": {"limit_value": 100},
106 },
107 {
108 "type": "value_error.number.not_ge",
109 "loc": ["query", "offset"],
110 "msg": "ensure this value is greater than or equal to 0",
111 "ctx": {"limit_value": 0},
112 },
113 {
114 "type": "value_error.const",
115 "loc": ["query", "order_by"],
116 "msg": "unexpected value; permitted: 'created_at', 'updated_at'",
117 "ctx": {
118 "given": "invalid",
119 "permitted": ["created_at", "updated_at"],
120 },
121 },
122 ]
123 }
124 )
125 )
128def test_query_param_model_extra(client: TestClient): 1abcde
129 response = client.get( 1uvwxy
130 "/items/",
131 params={
132 "limit": 10,
133 "offset": 5,
134 "order_by": "updated_at",
135 "tags": ["tag1", "tag2"],
136 "tool": "plumbus",
137 },
138 )
139 assert response.status_code == 200 1uvwxy
140 assert response.json() == { 1uvwxy
141 "limit": 10,
142 "offset": 5,
143 "order_by": "updated_at",
144 "tags": ["tag1", "tag2"],
145 }
148def test_openapi_schema(client: TestClient): 1abcde
149 response = client.get("/openapi.json") 1zABCD
150 assert response.status_code == 200, response.text 1zABCD
151 assert response.json() == snapshot( 1zABCD
152 {
153 "openapi": "3.1.0",
154 "info": {"title": "FastAPI", "version": "0.1.0"},
155 "paths": {
156 "/items/": {
157 "get": {
158 "summary": "Read Items",
159 "operationId": "read_items_items__get",
160 "parameters": [
161 {
162 "name": "limit",
163 "in": "query",
164 "required": False,
165 "schema": {
166 "type": "integer",
167 "maximum": 100,
168 "exclusiveMinimum": 0,
169 "default": 100,
170 "title": "Limit",
171 },
172 },
173 {
174 "name": "offset",
175 "in": "query",
176 "required": False,
177 "schema": {
178 "type": "integer",
179 "minimum": 0,
180 "default": 0,
181 "title": "Offset",
182 },
183 },
184 {
185 "name": "order_by",
186 "in": "query",
187 "required": False,
188 "schema": {
189 "enum": ["created_at", "updated_at"],
190 "type": "string",
191 "default": "created_at",
192 "title": "Order By",
193 },
194 },
195 {
196 "name": "tags",
197 "in": "query",
198 "required": False,
199 "schema": {
200 "type": "array",
201 "items": {"type": "string"},
202 "default": [],
203 "title": "Tags",
204 },
205 },
206 ],
207 "responses": {
208 "200": {
209 "description": "Successful Response",
210 "content": {"application/json": {"schema": {}}},
211 },
212 "422": {
213 "description": "Validation Error",
214 "content": {
215 "application/json": {
216 "schema": {
217 "$ref": "#/components/schemas/HTTPValidationError"
218 }
219 }
220 },
221 },
222 },
223 }
224 }
225 },
226 "components": {
227 "schemas": {
228 "HTTPValidationError": {
229 "properties": {
230 "detail": {
231 "items": {
232 "$ref": "#/components/schemas/ValidationError"
233 },
234 "type": "array",
235 "title": "Detail",
236 }
237 },
238 "type": "object",
239 "title": "HTTPValidationError",
240 },
241 "ValidationError": {
242 "properties": {
243 "loc": {
244 "items": {
245 "anyOf": [{"type": "string"}, {"type": "integer"}]
246 },
247 "type": "array",
248 "title": "Location",
249 },
250 "msg": {"type": "string", "title": "Message"},
251 "type": {"type": "string", "title": "Error Type"},
252 },
253 "type": "object",
254 "required": ["loc", "msg", "type"],
255 "title": "ValidationError",
256 },
257 }
258 },
259 }
260 )