flow_rs_core/selection/
tests.rs

1//! Tests for selection system
2
3#[cfg(test)]
4mod tests {
5    use crate::graph::{Graph, Node};
6    use crate::types::{NodeId, Position};
7    
8    use crate::selection::SelectionManager;
9    use crate::selection::{KeyboardShortcut, NavigationDirection, SelectionMode};
10    // use crate::selection::VisualFeedback; // Not used in tests
11
12    fn create_test_graph() -> Graph<(), ()> {
13        let mut graph = Graph::new();
14        graph
15            .add_node(Node::simple("node1", Position::new(100.0, 100.0)))
16            .unwrap();
17        graph
18            .add_node(Node::simple("node2", Position::new(200.0, 150.0)))
19            .unwrap();
20        graph
21            .add_node(Node::simple("node3", Position::new(300.0, 200.0)))
22            .unwrap();
23        graph
24            .add_node(Node::simple("node4", Position::new(150.0, 250.0)))
25            .unwrap();
26
27        graph
28    }
29
30    #[test]
31    fn test_new_selection_manager() {
32        let manager = SelectionManager::new();
33        assert_eq!(manager.selection_count(), 0);
34        assert_eq!(manager.mode(), &SelectionMode::Single);
35        assert!(manager.selected_nodes().is_empty());
36    }
37
38    #[test]
39    fn test_single_node_selection() {
40        let mut manager = SelectionManager::new();
41        let node_id: NodeId = "node1".into();
42
43        manager.select_node(node_id.clone());
44
45        assert_eq!(manager.selection_count(), 1);
46        assert!(manager.is_selected(&node_id));
47    }
48
49    #[test]
50    fn test_single_mode_replaces_selection() {
51        let mut manager = SelectionManager::new();
52        let node1: NodeId = "node1".into();
53        let node2: NodeId = "node2".into();
54
55        manager.select_node(node1.clone());
56        manager.select_node(node2.clone());
57
58        assert_eq!(manager.selection_count(), 1);
59        assert!(!manager.is_selected(&node1));
60        assert!(manager.is_selected(&node2));
61    }
62
63    #[test]
64    fn test_multi_mode_accumulates_selection() {
65        let mut manager = SelectionManager::new();
66        manager.set_mode(SelectionMode::Multi);
67
68        let node1: NodeId = "node1".into();
69        let node2: NodeId = "node2".into();
70
71        manager.select_node(node1.clone());
72        manager.select_node(node2.clone());
73
74        assert_eq!(manager.selection_count(), 2);
75        assert!(manager.is_selected(&node1));
76        assert!(manager.is_selected(&node2));
77    }
78
79    #[test]
80    fn test_toggle_node_selection() {
81        let mut manager = SelectionManager::new();
82        let node_id: NodeId = "node1".into();
83
84        // Toggle on
85        manager.toggle_node(node_id.clone());
86        assert!(manager.is_selected(&node_id));
87        assert_eq!(manager.selection_count(), 1);
88
89        // Toggle off
90        manager.toggle_node(node_id.clone());
91        assert!(!manager.is_selected(&node_id));
92        assert_eq!(manager.selection_count(), 0);
93    }
94
95    #[test]
96    fn test_clear_selection() {
97        let mut manager = SelectionManager::new();
98        manager.set_mode(SelectionMode::Multi);
99
100        manager.select_node("node1".into());
101        manager.select_node("node2".into());
102
103        assert_eq!(manager.selection_count(), 2);
104
105        manager.clear_selection();
106
107        assert_eq!(manager.selection_count(), 0);
108        assert!(manager.selected_nodes().is_empty());
109    }
110
111    #[test]
112    fn test_rectangle_selection_basic() {
113        let mut manager = SelectionManager::new();
114        let graph = create_test_graph();
115
116        // Start rectangle selection
117        manager.start_rectangle_selection(Position::new(50.0, 50.0));
118        assert_eq!(manager.mode(), &SelectionMode::Rectangle);
119
120        // Update rectangle to cover nodes 1 and 2
121        manager.update_rectangle_selection(Position::new(250.0, 175.0));
122
123        // Complete selection
124        let selected = manager.complete_rectangle_selection(&graph);
125        assert_eq!(selected.len(), 2);
126        assert_eq!(manager.mode(), &SelectionMode::Single);
127    }
128
129    #[test]
130    fn test_rectangle_selection_bounds() {
131        let mut manager = SelectionManager::new();
132
133        // Start rectangle selection
134        manager.start_rectangle_selection(Position::new(100.0, 100.0));
135        assert_eq!(manager.mode(), &SelectionMode::Rectangle);
136
137        // Update rectangle
138        manager.update_rectangle_selection(Position::new(200.0, 200.0));
139
140        // Check bounds
141        let bounds = manager.rectangle_bounds();
142        assert!(bounds.is_some());
143        let (start, end) = bounds.unwrap();
144        assert_eq!(start, Position::new(100.0, 100.0));
145        assert_eq!(end, Position::new(200.0, 200.0));
146    }
147
148    #[test]
149    fn test_keyboard_navigation() {
150        let mut manager = SelectionManager::new();
151        let graph = create_test_graph();
152
153        // Navigate to first node
154        let first = manager.navigate_selection(&graph, NavigationDirection::Next);
155        assert!(first.is_some());
156        assert_eq!(manager.selection_count(), 1);
157
158        // Navigate to next node
159        let second = manager.navigate_selection(&graph, NavigationDirection::Next);
160        assert!(second.is_some());
161        assert_eq!(manager.selection_count(), 1);
162        assert_ne!(first, second);
163
164        // Navigate back
165        let back = manager.navigate_selection(&graph, NavigationDirection::Previous);
166        assert!(back.is_some());
167        assert_eq!(back, first);
168    }
169
170    #[test]
171    fn test_keyboard_shortcuts() {
172        let mut manager = SelectionManager::new();
173        let graph = create_test_graph();
174
175        // Test select all
176        manager.handle_keyboard_shortcut(&graph, KeyboardShortcut::SelectAll);
177        assert_eq!(manager.selection_count(), 4);
178
179        // Test escape
180        manager.handle_keyboard_shortcut(&graph, KeyboardShortcut::Escape);
181        assert_eq!(manager.selection_count(), 0);
182
183        // Test arrow navigation
184        manager.handle_keyboard_shortcut(&graph, KeyboardShortcut::ArrowRight);
185        assert_eq!(manager.selection_count(), 1);
186    }
187
188    #[test]
189    fn test_destructive_keyboard_shortcuts() {
190        let mut manager = SelectionManager::new();
191        let mut graph = create_test_graph();
192
193        // Select a node
194        manager.select_node("node1".into());
195        assert_eq!(manager.selection_count(), 1);
196
197        // Delete selected node
198        manager.handle_destructive_keyboard_shortcut(&mut graph, KeyboardShortcut::Delete);
199        assert_eq!(manager.selection_count(), 0);
200        assert_eq!(graph.node_count(), 3);
201    }
202
203    #[test]
204    fn test_visual_feedback_basic() {
205        let mut manager = SelectionManager::new();
206        let node_id: NodeId = "node1".into();
207
208        // Set hover state
209        manager.set_hover_state(&node_id, true);
210        assert!(manager.has_visual_feedback(&node_id));
211        assert!(manager.get_visual_feedback(&node_id).unwrap().is_hovered());
212
213        // Set highlight state
214        manager.set_highlight_state(&node_id, true);
215        assert!(manager.get_visual_feedback(&node_id).unwrap().is_highlighted());
216
217        // Clear hover state
218        manager.set_hover_state(&node_id, false);
219        assert!(manager.has_visual_feedback(&node_id)); // Still has highlight
220
221        // Clear highlight state
222        manager.set_highlight_state(&node_id, false);
223        assert!(!manager.has_visual_feedback(&node_id)); // No more feedback
224    }
225
226    #[test]
227    fn test_visual_feedback_animation() {
228        let mut manager = SelectionManager::new();
229        let node_id: NodeId = "node1".into();
230
231        // Set hover state first to create visual feedback
232        manager.set_hover_state(&node_id, true);
233        
234        // Set animation progress
235        manager.set_animation_progress(&node_id, 0.5);
236        assert!(manager.has_visual_feedback(&node_id));
237        assert_eq!(manager.get_visual_feedback(&node_id).unwrap().animation_progress(), 0.5);
238
239        // Clamp animation progress
240        manager.set_animation_progress(&node_id, 1.5);
241        assert_eq!(manager.get_visual_feedback(&node_id).unwrap().animation_progress(), 1.0);
242
243        manager.set_animation_progress(&node_id, -0.5);
244        assert_eq!(manager.get_visual_feedback(&node_id).unwrap().animation_progress(), 0.0);
245    }
246
247    #[test]
248    fn test_visual_feedback_selection_integration() {
249        let mut manager = SelectionManager::new();
250        let node1: NodeId = "node1".into();
251        let node2: NodeId = "node2".into();
252
253        // Select first node
254        manager.select_node(node1.clone());
255        assert!(manager.get_visual_feedback(&node1).unwrap().is_selected());
256
257        // Select second node - should clear first node's selection state
258        manager.select_node(node2.clone());
259
260        // First node should lose selection visual feedback
261        if let Some(feedback1) = manager.get_visual_feedback(&node1) {
262            assert!(!feedback1.is_selected());
263        } else {
264            // Or might be completely removed if no other states
265            assert!(!manager.has_visual_feedback(&node1));
266        }
267
268        // Second node should have selection visual feedback
269        assert!(manager.get_visual_feedback(&node2).unwrap().is_selected());
270    }
271
272    #[test]
273    fn test_visual_feedback_batch_operations() {
274        let mut manager = SelectionManager::new();
275        let nodes: Vec<NodeId> = (0..10)
276            .map(|i| NodeId::from(format!("node{}", i)))
277            .collect();
278
279        // Set all nodes to different states
280        for (i, node_id) in nodes.iter().enumerate() {
281            if i % 3 == 0 {
282                manager.select_node(node_id.clone());
283            }
284            if i % 2 == 0 {
285                manager.set_hover_state(node_id, true);
286            }
287            if i % 5 == 0 {
288                manager.set_highlight_state(node_id, true);
289            }
290        }
291
292        // Verify states
293        let feedback_nodes = manager.nodes_with_visual_feedback();
294        assert!(!feedback_nodes.is_empty());
295
296        // Clear all visual feedback
297        manager.clear_all_visual_feedbacks();
298
299        // Verify all feedback is cleared
300        for node_id in &nodes {
301            assert!(!manager.has_visual_feedback(node_id));
302        }
303
304        // But selection state should remain in the selection manager
305        assert!(!manager.selected_nodes().is_empty()); // Some nodes were selected
306    }
307}