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