Coverage for tests / test_extra_routes.py: 100%
63 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1from fastapi import FastAPI 1adbc
2from fastapi.responses import JSONResponse 1adbc
3from fastapi.testclient import TestClient 1adbc
4from inline_snapshot import snapshot 1adbc
5from pydantic import BaseModel 1adbc
7app = FastAPI() 1adbc
10class Item(BaseModel): 1adbc
11 name: str 1abc
12 price: float | None = None 1adbc
15@app.api_route("/items/{item_id}", methods=["GET"]) 1adbc
16def get_items(item_id: str): 1adbc
17 return {"item_id": item_id} 1efgh
20def get_not_decorated(item_id: str): 1adbc
21 return {"item_id": item_id} 1ijkl
24app.add_api_route("/items-not-decorated/{item_id}", get_not_decorated) 1adbc
27@app.delete("/items/{item_id}") 1adbc
28def delete_item(item_id: str, item: Item): 1adbc
29 return {"item_id": item_id, "item": item} 1mnop
32@app.head("/items/{item_id}") 1adbc
33def head_item(item_id: str): 1adbc
34 return JSONResponse(None, headers={"x-fastapi-item-id": item_id}) 1qrst
37@app.options("/items/{item_id}") 1adbc
38def options_item(item_id: str): 1adbc
39 return JSONResponse(None, headers={"x-fastapi-item-id": item_id}) 1uvwx
42@app.patch("/items/{item_id}") 1adbc
43def patch_item(item_id: str, item: Item): 1adbc
44 return {"item_id": item_id, "item": item} 1yzAB
47@app.trace("/items/{item_id}") 1adbc
48def trace_item(item_id: str): 1adbc
49 return JSONResponse(None, media_type="message/http") 1CDEF
52client = TestClient(app) 1adbc
55def test_get_api_route(): 1adbc
56 response = client.get("/items/foo") 1efgh
57 assert response.status_code == 200, response.text 1efgh
58 assert response.json() == {"item_id": "foo"} 1efgh
61def test_get_api_route_not_decorated(): 1adbc
62 response = client.get("/items-not-decorated/foo") 1ijkl
63 assert response.status_code == 200, response.text 1ijkl
64 assert response.json() == {"item_id": "foo"} 1ijkl
67def test_delete(): 1adbc
68 response = client.request("DELETE", "/items/foo", json={"name": "Foo"}) 1mnop
69 assert response.status_code == 200, response.text 1mnop
70 assert response.json() == {"item_id": "foo", "item": {"name": "Foo", "price": None}} 1mnop
73def test_head(): 1adbc
74 response = client.head("/items/foo") 1qrst
75 assert response.status_code == 200, response.text 1qrst
76 assert response.headers["x-fastapi-item-id"] == "foo" 1qrst
79def test_options(): 1adbc
80 response = client.options("/items/foo") 1uvwx
81 assert response.status_code == 200, response.text 1uvwx
82 assert response.headers["x-fastapi-item-id"] == "foo" 1uvwx
85def test_patch(): 1adbc
86 response = client.patch("/items/foo", json={"name": "Foo"}) 1yzAB
87 assert response.status_code == 200, response.text 1yzAB
88 assert response.json() == {"item_id": "foo", "item": {"name": "Foo", "price": None}} 1yzAB
91def test_trace(): 1adbc
92 response = client.request("trace", "/items/foo") 1CDEF
93 assert response.status_code == 200, response.text 1CDEF
94 assert response.headers["content-type"] == "message/http" 1CDEF
97def test_openapi_schema(): 1adbc
98 response = client.get("/openapi.json") 1GHIJ
99 assert response.status_code == 200, response.text 1GHIJ
100 assert response.json() == snapshot( 1GHIJ
101 {
102 "openapi": "3.1.0",
103 "info": {"title": "FastAPI", "version": "0.1.0"},
104 "paths": {
105 "/items/{item_id}": {
106 "get": {
107 "responses": {
108 "200": {
109 "description": "Successful Response",
110 "content": {"application/json": {"schema": {}}},
111 },
112 "422": {
113 "description": "Validation Error",
114 "content": {
115 "application/json": {
116 "schema": {
117 "$ref": "#/components/schemas/HTTPValidationError"
118 }
119 }
120 },
121 },
122 },
123 "summary": "Get Items",
124 "operationId": "get_items_items__item_id__get",
125 "parameters": [
126 {
127 "required": True,
128 "schema": {"title": "Item Id", "type": "string"},
129 "name": "item_id",
130 "in": "path",
131 }
132 ],
133 },
134 "delete": {
135 "responses": {
136 "200": {
137 "description": "Successful Response",
138 "content": {"application/json": {"schema": {}}},
139 },
140 "422": {
141 "description": "Validation Error",
142 "content": {
143 "application/json": {
144 "schema": {
145 "$ref": "#/components/schemas/HTTPValidationError"
146 }
147 }
148 },
149 },
150 },
151 "summary": "Delete Item",
152 "operationId": "delete_item_items__item_id__delete",
153 "parameters": [
154 {
155 "required": True,
156 "schema": {"title": "Item Id", "type": "string"},
157 "name": "item_id",
158 "in": "path",
159 }
160 ],
161 "requestBody": {
162 "content": {
163 "application/json": {
164 "schema": {"$ref": "#/components/schemas/Item"}
165 }
166 },
167 "required": True,
168 },
169 },
170 "options": {
171 "responses": {
172 "200": {
173 "description": "Successful Response",
174 "content": {"application/json": {"schema": {}}},
175 },
176 "422": {
177 "description": "Validation Error",
178 "content": {
179 "application/json": {
180 "schema": {
181 "$ref": "#/components/schemas/HTTPValidationError"
182 }
183 }
184 },
185 },
186 },
187 "summary": "Options Item",
188 "operationId": "options_item_items__item_id__options",
189 "parameters": [
190 {
191 "required": True,
192 "schema": {"title": "Item Id", "type": "string"},
193 "name": "item_id",
194 "in": "path",
195 }
196 ],
197 },
198 "head": {
199 "responses": {
200 "200": {
201 "description": "Successful Response",
202 "content": {"application/json": {"schema": {}}},
203 },
204 "422": {
205 "description": "Validation Error",
206 "content": {
207 "application/json": {
208 "schema": {
209 "$ref": "#/components/schemas/HTTPValidationError"
210 }
211 }
212 },
213 },
214 },
215 "summary": "Head Item",
216 "operationId": "head_item_items__item_id__head",
217 "parameters": [
218 {
219 "required": True,
220 "schema": {"title": "Item Id", "type": "string"},
221 "name": "item_id",
222 "in": "path",
223 }
224 ],
225 },
226 "patch": {
227 "responses": {
228 "200": {
229 "description": "Successful Response",
230 "content": {"application/json": {"schema": {}}},
231 },
232 "422": {
233 "description": "Validation Error",
234 "content": {
235 "application/json": {
236 "schema": {
237 "$ref": "#/components/schemas/HTTPValidationError"
238 }
239 }
240 },
241 },
242 },
243 "summary": "Patch Item",
244 "operationId": "patch_item_items__item_id__patch",
245 "parameters": [
246 {
247 "required": True,
248 "schema": {"title": "Item Id", "type": "string"},
249 "name": "item_id",
250 "in": "path",
251 }
252 ],
253 "requestBody": {
254 "content": {
255 "application/json": {
256 "schema": {"$ref": "#/components/schemas/Item"}
257 }
258 },
259 "required": True,
260 },
261 },
262 "trace": {
263 "responses": {
264 "200": {
265 "description": "Successful Response",
266 "content": {"application/json": {"schema": {}}},
267 },
268 "422": {
269 "description": "Validation Error",
270 "content": {
271 "application/json": {
272 "schema": {
273 "$ref": "#/components/schemas/HTTPValidationError"
274 }
275 }
276 },
277 },
278 },
279 "summary": "Trace Item",
280 "operationId": "trace_item_items__item_id__trace",
281 "parameters": [
282 {
283 "required": True,
284 "schema": {"title": "Item Id", "type": "string"},
285 "name": "item_id",
286 "in": "path",
287 }
288 ],
289 },
290 },
291 "/items-not-decorated/{item_id}": {
292 "get": {
293 "responses": {
294 "200": {
295 "description": "Successful Response",
296 "content": {"application/json": {"schema": {}}},
297 },
298 "422": {
299 "description": "Validation Error",
300 "content": {
301 "application/json": {
302 "schema": {
303 "$ref": "#/components/schemas/HTTPValidationError"
304 }
305 }
306 },
307 },
308 },
309 "summary": "Get Not Decorated",
310 "operationId": "get_not_decorated_items_not_decorated__item_id__get",
311 "parameters": [
312 {
313 "required": True,
314 "schema": {"title": "Item Id", "type": "string"},
315 "name": "item_id",
316 "in": "path",
317 }
318 ],
319 }
320 },
321 },
322 "components": {
323 "schemas": {
324 "Item": {
325 "title": "Item",
326 "required": ["name"],
327 "type": "object",
328 "properties": {
329 "name": {"title": "Name", "type": "string"},
330 "price": {
331 "title": "Price",
332 "anyOf": [{"type": "number"}, {"type": "null"}],
333 },
334 },
335 },
336 "ValidationError": {
337 "title": "ValidationError",
338 "required": ["loc", "msg", "type"],
339 "type": "object",
340 "properties": {
341 "loc": {
342 "title": "Location",
343 "type": "array",
344 "items": {
345 "anyOf": [{"type": "string"}, {"type": "integer"}]
346 },
347 },
348 "msg": {"title": "Message", "type": "string"},
349 "type": {"title": "Error Type", "type": "string"},
350 "input": {"title": "Input"},
351 "ctx": {"title": "Context", "type": "object"},
352 },
353 },
354 "HTTPValidationError": {
355 "title": "HTTPValidationError",
356 "type": "object",
357 "properties": {
358 "detail": {
359 "title": "Detail",
360 "type": "array",
361 "items": {
362 "$ref": "#/components/schemas/ValidationError"
363 },
364 }
365 },
366 },
367 }
368 },
369 }
370 )