Skip to content

Commit b033381

Browse files
committed
added tests test_Fast_API__Route__Helper, test_Fast_API__Routes__path_parsing__integration , test_Fast_API__Routes__path_parsing__unit , test_Schema__Route__Parameter and
test_Schema__Route__Signature also updated tests for test_Fast_API__Routes and test_Fast_API__Routes__client
1 parent c39c44a commit b033381

8 files changed

+1250
-138
lines changed

osbot_fast_api/api/routes/Fast_API__Route__Helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ def add_route_delete(self, app : FastAPI , # FastAPI ap
4242
@type_safe
4343
def add_route_any(self, app : FastAPI , # FastAPI app instance
4444
function : Callable , # Function to register
45-
path : str = None # Optional explicit path
45+
path : str = None # Optional explicit path # todo: replace str with a Safe_Str__* class
4646
): # Register route accepting ANY HTTP method
4747
self.route_registration.register_route_any(app.router, function, path)
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
from unittest import TestCase
2+
from fastapi import FastAPI, APIRouter
3+
from osbot_utils.utils.Dev import pprint
4+
5+
from osbot_utils.utils.Objects import obj
6+
7+
from osbot_utils.type_safe.Type_Safe import Type_Safe
8+
from osbot_utils.type_safe.primitives.core.Safe_Str import Safe_Str
9+
from osbot_utils.type_safe.primitives.domains.identifiers.Safe_Id import Safe_Id
10+
from osbot_fast_api.api.routes.Fast_API__Route__Helper import Fast_API__Route__Helper
11+
from osbot_fast_api.api.routes.Type_Safe__Route__Registration import Type_Safe__Route__Registration
12+
13+
14+
class test_Fast_API__Route__Helper(TestCase):
15+
16+
def setUp(self): # Per-test setup for app
17+
self.fastapi_kwargs = dict(docs_url = None, # disables Swagger UI (/docs)
18+
redoc_url = None, # disables ReDoc (/redoc)
19+
openapi_url = None) # disables OpenAPI schema (/openapi.json)
20+
21+
self.app = FastAPI(**self.fastapi_kwargs)
22+
self.helper = Fast_API__Route__Helper()
23+
24+
def test__init__(self): # Test helper initialization
25+
with Fast_API__Route__Helper() as _:
26+
assert type(_) is Fast_API__Route__Helper
27+
assert type(_.route_registration) is Type_Safe__Route__Registration
28+
29+
def test_add_route__with_get_method(self): # Test adding route with GET method
30+
def test_endpoint():
31+
return {"status": "ok"}
32+
33+
self.helper.add_route(self.app, test_endpoint, methods=['GET'])
34+
35+
routes = self.app.routes
36+
assert type(routes) is list
37+
38+
assert len(routes) == 1
39+
assert routes[0].path == '/test-endpoint'
40+
assert routes[0].methods == {'GET'}
41+
42+
def test_add_route__with_post_method(self): # Test adding route with POST method
43+
def create_item():
44+
return {"created": True}
45+
46+
self.helper.add_route(self.app, create_item, methods=['POST'])
47+
48+
routes = self.app.routes
49+
assert len(routes) == 1
50+
assert routes[0].path == '/create-item'
51+
assert routes[0].methods == {'POST'}
52+
53+
def test_add_route__with_multiple_methods(self): # Test adding route with multiple HTTP methods
54+
def handle_resource():
55+
return {"handled": True}
56+
57+
self.helper.add_route(self.app, handle_resource, methods=['GET', 'POST', 'PUT'])
58+
59+
routes = self.app.routes
60+
assert len(routes) == 1
61+
assert routes[0].methods == {'GET', 'POST', 'PUT'}
62+
63+
def test_add_route_get(self): # Test convenience method for GET routes
64+
def get_data():
65+
return {"data": [1, 2, 3]}
66+
67+
self.helper.add_route_get(self.app, get_data)
68+
69+
routes = self.app.routes
70+
assert len(routes) == 1
71+
assert routes[0].path == '/get-data'
72+
assert routes[0].methods == {'GET'}
73+
74+
def test_add_route_post(self): # Test convenience method for POST routes
75+
def create_user():
76+
return {"created": True}
77+
78+
self.helper.add_route_post(self.app, create_user)
79+
80+
routes = self.app.routes
81+
assert len(routes) == 1
82+
assert routes[0].path == '/create-user'
83+
assert routes[0].methods == {'POST'}
84+
85+
def test_add_route_put(self): # Test convenience method for PUT routes
86+
def update_item():
87+
return {"updated": True}
88+
89+
self.helper.add_route_put(self.app, update_item)
90+
91+
routes = self.app.routes
92+
assert len(routes) == 1
93+
assert routes[0].path == '/update-item'
94+
assert routes[0].methods == {'PUT'}
95+
96+
def test_add_route_delete(self): # Test convenience method for DELETE routes
97+
def delete_item():
98+
return {"deleted": True}
99+
100+
self.helper.add_route_delete(self.app, delete_item)
101+
102+
routes = self.app.routes
103+
assert len(routes) == 1
104+
assert routes[0].path == '/delete-item'
105+
assert routes[0].methods == {'DELETE'}
106+
107+
def test_add_route_any__default_path(self): # Test ANY method with default path parsing
108+
def catch_all():
109+
return {"method": "any"}
110+
111+
self.helper.add_route_any(self.app, catch_all)
112+
113+
routes = self.app.routes
114+
assert len(routes) == 1
115+
assert routes[0].path == '/catch-all'
116+
assert routes[0].methods == {'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'}
117+
118+
def test_add_route_any__explicit_path(self): # Test ANY method with explicit path
119+
def proxy(path: str):
120+
return {"proxied": path}
121+
122+
self.helper.add_route_any(self.app, proxy, path="/{path:path}")
123+
124+
routes = self.app.routes
125+
assert len(routes) == 1
126+
assert routes[0].path == '/{path:path}'
127+
assert routes[0].methods == {'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT'}
128+
129+
def test_add_route__with_type_safe_params(self): # Test route with Type_Safe parameters
130+
class User_Data(Type_Safe):
131+
name : Safe_Str
132+
email : Safe_Str
133+
134+
def create_user(user_data: User_Data):
135+
return {"created": True}
136+
137+
self.helper.add_route(self.app, create_user, methods=['POST'])
138+
139+
routes = self.app.routes
140+
assert len(routes) == 1
141+
assert routes[0].path == '/create-user'
142+
assert routes[0].methods == {'POST'}
143+
144+
def test_add_route__with_path_params(self): # Test route with path parameters
145+
def get__user_id(user_id: Safe_Id):
146+
return {"user_id": str(user_id)}
147+
148+
self.helper.add_route_get(self.app, get__user_id)
149+
150+
routes = self.app.routes
151+
assert len(routes) == 1
152+
assert routes[0].path == '/get/{user_id}'
153+
154+
def test_add_multiple_routes(self): # Test adding multiple routes to same app
155+
def endpoint_1():
156+
pass
157+
158+
def endpoint_2():
159+
pass
160+
161+
def endpoint_3():
162+
pass
163+
164+
self.helper.add_route_get(self.app, endpoint_1)
165+
self.helper.add_route_post(self.app, endpoint_2)
166+
self.helper.add_route_put(self.app, endpoint_3)
167+
168+
routes = self.app.routes
169+
assert len(routes) == 3
170+
assert routes[0].path == '/endpoint-1'
171+
assert routes[1].path == '/endpoint-2'
172+
assert routes[2].path == '/endpoint-3'
173+
assert routes[0].methods == {'GET'}
174+
assert routes[1].methods == {'POST'}
175+
assert routes[2].methods == {'PUT'}
176+
177+
def test_add_route__integration_with_analyzer_and_converter(self): # Test full integration with Type_Safe system
178+
class Order_Data(Type_Safe):
179+
items : list
180+
quantity : Safe_Id
181+
182+
def create__order_id(order_id: Safe_Id, data: Order_Data):
183+
return {"order_id": str(order_id), "created": True}
184+
185+
self.helper.add_route_post(self.app, create__order_id)
186+
187+
routes = self.app.routes
188+
assert len(routes) == 1
189+
assert routes[0].path == '/create/{order_id}'
190+
191+
def test_add_route_any__no_explicit_path(self): # Test ANY without explicit path uses parser
192+
def handle_request():
193+
return {"handled": True}
194+
195+
self.helper.add_route_any(self.app, handle_request, path=None)
196+
197+
routes = self.app.routes
198+
assert len(routes) == 1
199+
assert routes[0].path == '/handle-request'

0 commit comments

Comments
 (0)