Skip to content

Commit 65c6334

Browse files
authored
test: add unit tests for routing models
test: add unit tests for routing models
2 parents 7f24861 + ada52f9 commit 65c6334

1 file changed

Lines changed: 192 additions & 0 deletions

File tree

tests/test_routing_models.py

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
"""
2+
Unit tests for FletX Routing Models
3+
"""
4+
5+
import pytest
6+
import flet as ft
7+
from unittest.mock import Mock
8+
9+
from fletx.core.routing.models import (
10+
RouteInfo,
11+
NavigationIntent,
12+
RouteType,
13+
NavigationMode,
14+
RouterState,
15+
NavigationResult,
16+
IRouteResolver
17+
)
18+
19+
20+
class TestRouteInfo:
21+
"""Test RouteInfo class."""
22+
23+
def test_creation_with_defaults(self):
24+
"""Test basic creation with defaults."""
25+
route = RouteInfo(path="/home")
26+
27+
assert route.path == "/home"
28+
assert route.params == {}
29+
assert route.query == {}
30+
assert route.fragment is None
31+
32+
def test_creation_with_all_params(self):
33+
"""Test creation with all parameters."""
34+
route = RouteInfo(
35+
path="/user",
36+
params={"id": "123"},
37+
query={"tab": "settings"},
38+
data={"user": "john"},
39+
fragment="section"
40+
)
41+
42+
assert route.params == {"id": "123"}
43+
assert route.query == {"tab": "settings"}
44+
assert route.fragment == "section"
45+
46+
def test_extra_data(self):
47+
"""Test adding and getting extra data."""
48+
route = RouteInfo(path="/test")
49+
route.add_extra("key", "value")
50+
51+
assert route.get_extra("key") == "value"
52+
assert route.get_extra("missing", "default") == "default"
53+
54+
def test_full_url_generation(self):
55+
"""Test full URL generation with query and fragment."""
56+
route = RouteInfo(
57+
path="/page",
58+
query={"id": "1", "tab": "main"},
59+
fragment="top"
60+
)
61+
62+
url = route.full_url
63+
assert url.startswith("/page?")
64+
assert "id=1" in url
65+
assert "tab=main" in url
66+
assert url.endswith("#top")
67+
68+
69+
class TestNavigationIntent:
70+
"""Test NavigationIntent class."""
71+
72+
def test_creation_with_defaults(self):
73+
"""Test basic creation with defaults."""
74+
intent = NavigationIntent(route="/home")
75+
76+
assert intent.route == "/home"
77+
assert intent.data == {}
78+
assert intent.replace is False
79+
assert intent.clear_history is False
80+
assert intent.transition is None
81+
82+
def test_creation_with_all_params(self):
83+
"""Test creation with all parameters."""
84+
intent = NavigationIntent(
85+
route="/profile",
86+
data={"user_id": 123},
87+
replace=True,
88+
clear_history=True
89+
)
90+
91+
assert intent.data == {"user_id": 123}
92+
assert intent.replace is True
93+
assert intent.clear_history is True
94+
95+
96+
class TestEnums:
97+
"""Test enum classes."""
98+
99+
def test_route_type_values(self):
100+
"""Test RouteType enum values."""
101+
assert RouteType.PAGE.value == "page"
102+
assert RouteType.VIEW.value == "view"
103+
assert RouteType.MODULE.value == "module"
104+
105+
def test_navigation_mode_values(self):
106+
"""Test NavigationMode enum values."""
107+
assert NavigationMode.NATIVE.value == "native"
108+
assert NavigationMode.VIEWS.value == "views"
109+
assert NavigationMode.HYBRID.value == "hybrid"
110+
111+
def test_navigation_result_values(self):
112+
"""Test NavigationResult enum values."""
113+
assert NavigationResult.SUCCESS.value == "success"
114+
assert NavigationResult.BLOCKED_BY_GUARD.value == "blocked_by_guard"
115+
assert NavigationResult.ERROR.value == "error"
116+
117+
118+
class TestRouterState:
119+
"""Test RouterState class."""
120+
121+
def test_creation_with_defaults(self):
122+
"""Test basic creation with defaults."""
123+
route = RouteInfo(path="/home")
124+
state = RouterState(current_route=route)
125+
126+
assert state.current_route == route
127+
assert state.history == []
128+
assert state.forward_stack == []
129+
assert state.navigation_mode == NavigationMode.HYBRID
130+
assert state.active_views == []
131+
132+
def test_mutable_collections(self):
133+
"""Test that collections can be modified."""
134+
route = RouteInfo(path="/test")
135+
state = RouterState(current_route=route)
136+
137+
state.history.append(RouteInfo(path="/home"))
138+
state.forward_stack.append(RouteInfo(path="/forward"))
139+
state.active_views.append(Mock(spec=ft.View))
140+
141+
assert len(state.history) == 1
142+
assert len(state.forward_stack) == 1
143+
assert len(state.active_views) == 1
144+
145+
146+
class TestIRouteResolver:
147+
"""Test IRouteResolver interface."""
148+
149+
def test_is_abstract(self):
150+
"""Test that IRouteResolver cannot be instantiated."""
151+
with pytest.raises(TypeError):
152+
IRouteResolver()
153+
154+
def test_concrete_implementation(self):
155+
"""Test concrete implementation works."""
156+
class ConcreteResolver(IRouteResolver):
157+
def resolve(self, route_info: RouteInfo):
158+
return {"data": route_info.path}
159+
160+
resolver = ConcreteResolver()
161+
route = RouteInfo(path="/test")
162+
result = resolver.resolve(route)
163+
164+
assert result == {"data": "/test"}
165+
assert isinstance(resolver, IRouteResolver)
166+
167+
168+
class TestIntegration:
169+
"""Integration tests."""
170+
171+
def test_navigation_flow(self):
172+
"""Test complete navigation flow with all models."""
173+
# Setup initial state
174+
home = RouteInfo(path="/home")
175+
state = RouterState(current_route=home)
176+
177+
# Create navigation intent
178+
intent = NavigationIntent(
179+
route="/profile",
180+
data={"user_id": 123}
181+
)
182+
183+
# Simulate navigation
184+
profile = RouteInfo(path=intent.route, data=intent.data)
185+
state.history.append(state.current_route)
186+
state.current_route = profile
187+
188+
# Verify
189+
assert state.current_route.path == "/profile"
190+
assert state.current_route.data["user_id"] == 123
191+
assert len(state.history) == 1
192+
assert state.history[0].path == "/home"

0 commit comments

Comments
 (0)