use std::collections::BTreeMap;
use azul_core::{
dom::{DomId, DomNodeId},
events::*,
geom::{LogicalPosition, LogicalRect, LogicalSize},
id::{Node, NodeHierarchy, NodeId},
styled_dom::NodeHierarchyItemId,
task::{Instant, SystemTick},
};
fn test_instant() -> Instant {
Instant::Tick(SystemTick::new(0))
}
fn create_test_hierarchy() -> NodeHierarchy {
let nodes = vec![
Node {
parent: None,
previous_sibling: None,
next_sibling: None,
last_child: Some(NodeId::new(1)),
},
Node {
parent: Some(NodeId::new(0)),
previous_sibling: None,
next_sibling: None,
last_child: Some(NodeId::new(2)),
},
Node {
parent: Some(NodeId::new(1)),
previous_sibling: None,
next_sibling: None,
last_child: None,
},
];
NodeHierarchy::new(nodes)
}
#[test]
fn test_event_source_enum() {
let _user = EventSource::User;
let _programmatic = EventSource::Programmatic;
let _synthetic = EventSource::Synthetic;
let _lifecycle = EventSource::Lifecycle;
}
#[test]
fn test_event_phase_enum() {
let _capture = EventPhase::Capture;
let _target = EventPhase::Target;
let _bubble = EventPhase::Bubble;
assert_eq!(EventPhase::default(), EventPhase::Bubble);
}
#[test]
fn test_synthetic_event_creation() {
let dom_id = DomId { inner: 1 };
let node_id = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(0)));
let target = DomNodeId {
dom: dom_id,
node: node_id,
};
let event = SyntheticEvent::new(
EventType::Click,
EventSource::User,
target,
test_instant(),
EventData::None,
);
assert_eq!(event.event_type, EventType::Click);
assert_eq!(event.source, EventSource::User);
assert_eq!(event.phase, EventPhase::Target);
assert_eq!(event.target, target);
assert_eq!(event.current_target, target);
assert!(!event.stopped);
assert!(!event.stopped_immediate);
assert!(!event.prevented_default);
}
#[test]
fn test_stop_propagation() {
let dom_id = DomId { inner: 1 };
let node_id = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(0)));
let target = DomNodeId {
dom: dom_id,
node: node_id,
};
let mut event = SyntheticEvent::new(
EventType::Click,
EventSource::User,
target,
test_instant(),
EventData::None,
);
assert!(!event.is_propagation_stopped());
event.stop_propagation();
assert!(event.is_propagation_stopped());
assert!(!event.is_immediate_propagation_stopped());
}
#[test]
fn test_stop_immediate_propagation() {
let dom_id = DomId { inner: 1 };
let node_id = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(0)));
let target = DomNodeId {
dom: dom_id,
node: node_id,
};
let mut event = SyntheticEvent::new(
EventType::Click,
EventSource::User,
target,
test_instant(),
EventData::None,
);
event.stop_immediate_propagation();
assert!(event.is_propagation_stopped());
assert!(event.is_immediate_propagation_stopped());
}
#[test]
fn test_prevent_default() {
let dom_id = DomId { inner: 1 };
let node_id = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(0)));
let target = DomNodeId {
dom: dom_id,
node: node_id,
};
let mut event = SyntheticEvent::new(
EventType::Click,
EventSource::User,
target,
test_instant(),
EventData::None,
);
assert!(!event.is_default_prevented());
event.prevent_default();
assert!(event.is_default_prevented());
}
#[test]
fn test_get_dom_path_single_node() {
let hierarchy = NodeHierarchy::new(vec![Node {
parent: None,
previous_sibling: None,
next_sibling: None,
last_child: None,
}]);
let target = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(0)));
let path = get_dom_path(&hierarchy, target);
assert_eq!(path.len(), 1);
assert_eq!(path[0], NodeId::new(0));
}
#[test]
fn test_get_dom_path_three_nodes() {
let hierarchy = create_test_hierarchy();
let target = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(2)));
let path = get_dom_path(&hierarchy, target);
assert_eq!(path.len(), 3);
assert_eq!(path[0], NodeId::new(0)); assert_eq!(path[1], NodeId::new(1)); assert_eq!(path[2], NodeId::new(2)); }
#[test]
fn test_get_dom_path_middle_node() {
let hierarchy = create_test_hierarchy();
let target = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(1)));
let path = get_dom_path(&hierarchy, target);
assert_eq!(path.len(), 2);
assert_eq!(path[0], NodeId::new(0)); assert_eq!(path[1], NodeId::new(1)); }
#[test]
fn test_propagate_event_empty_callbacks() {
let hierarchy = create_test_hierarchy();
let dom_id = DomId { inner: 1 };
let target_node = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(2)));
let target = DomNodeId {
dom: dom_id,
node: target_node,
};
let mut event = SyntheticEvent::new(
EventType::Click,
EventSource::User,
target,
test_instant(),
EventData::None,
);
let callbacks: BTreeMap<NodeId, Vec<EventFilter>> = BTreeMap::new();
let result = propagate_event(&mut event, &hierarchy, &callbacks);
assert_eq!(result.callbacks_to_invoke.len(), 0);
assert!(!result.default_prevented);
}
#[test]
fn test_mouse_event_data_creation() {
let mouse_data = MouseEventData {
position: LogicalPosition { x: 100.0, y: 200.0 },
button: MouseButton::Left,
buttons: 1,
modifiers: KeyModifiers::new(),
};
assert_eq!(mouse_data.position.x, 100.0);
assert_eq!(mouse_data.position.y, 200.0);
assert_eq!(mouse_data.button, MouseButton::Left);
}
#[test]
fn test_key_modifiers() {
let modifiers = KeyModifiers::new().with_shift().with_ctrl();
assert!(modifiers.shift);
assert!(modifiers.ctrl);
assert!(!modifiers.alt);
assert!(!modifiers.meta);
assert!(!modifiers.is_empty());
let empty = KeyModifiers::new();
assert!(empty.is_empty());
}
#[test]
fn test_lifecycle_event_mount() {
let dom_id = DomId { inner: 1 };
let old_hierarchy = None;
let new_hierarchy = create_test_hierarchy();
let old_layout = None;
let new_layout = {
let mut map = BTreeMap::new();
map.insert(
NodeId::new(0),
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize {
width: 100.0,
height: 100.0,
},
},
);
map.insert(
NodeId::new(1),
LogicalRect {
origin: LogicalPosition { x: 10.0, y: 10.0 },
size: LogicalSize {
width: 80.0,
height: 80.0,
},
},
);
map.insert(
NodeId::new(2),
LogicalRect {
origin: LogicalPosition { x: 20.0, y: 20.0 },
size: LogicalSize {
width: 60.0,
height: 60.0,
},
},
);
Some(map)
};
let events = detect_lifecycle_events(
dom_id,
dom_id,
old_hierarchy,
Some(&new_hierarchy),
old_layout.as_ref(),
new_layout.as_ref(),
test_instant(),
);
assert_eq!(events.len(), 3);
for event in &events {
assert_eq!(event.event_type, EventType::Mount);
assert_eq!(event.source, EventSource::Lifecycle);
if let EventData::Lifecycle(data) = &event.data {
assert_eq!(data.reason, LifecycleReason::InitialMount);
assert!(data.previous_bounds.is_none());
} else {
panic!("Expected Lifecycle event data");
}
}
}
#[test]
fn test_lifecycle_event_unmount() {
let dom_id = DomId { inner: 1 };
let old_hierarchy = create_test_hierarchy();
let new_hierarchy = None;
let old_layout = {
let mut map = BTreeMap::new();
map.insert(
NodeId::new(0),
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize {
width: 100.0,
height: 100.0,
},
},
);
Some(map)
};
let new_layout = None;
let events = detect_lifecycle_events(
dom_id,
dom_id,
Some(&old_hierarchy),
new_hierarchy,
old_layout.as_ref(),
new_layout,
test_instant(),
);
assert_eq!(events.len(), 3);
for event in &events {
assert_eq!(event.event_type, EventType::Unmount);
assert_eq!(event.source, EventSource::Lifecycle);
}
}
#[test]
fn test_lifecycle_event_resize() {
let dom_id = DomId { inner: 1 };
let hierarchy = create_test_hierarchy();
let old_layout = {
let mut map = BTreeMap::new();
map.insert(
NodeId::new(0),
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize {
width: 100.0,
height: 100.0,
},
},
);
Some(map)
};
let new_layout = {
let mut map = BTreeMap::new();
map.insert(
NodeId::new(0),
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize {
width: 200.0,
height: 100.0,
}, },
);
Some(map)
};
let events = detect_lifecycle_events(
dom_id,
dom_id,
Some(&hierarchy),
Some(&hierarchy),
old_layout.as_ref(),
new_layout.as_ref(),
test_instant(),
);
assert_eq!(events.len(), 1);
assert_eq!(events[0].event_type, EventType::Resize);
assert_eq!(events[0].source, EventSource::Lifecycle);
if let EventData::Lifecycle(data) = &events[0].data {
assert_eq!(data.reason, LifecycleReason::Resize);
assert!(data.previous_bounds.is_some());
assert_eq!(data.current_bounds.size.width, 200.0);
} else {
panic!("Expected Lifecycle event data");
}
}
#[test]
fn test_event_filter_hover_match() {
let dom_id = DomId { inner: 1 };
let node_id = NodeHierarchyItemId::from_crate_internal(Some(NodeId::new(0)));
let target = DomNodeId {
dom: dom_id,
node: node_id,
};
let _event = SyntheticEvent::new(
EventType::MouseDown,
EventSource::User,
target,
test_instant(),
EventData::Mouse(MouseEventData {
position: LogicalPosition { x: 0.0, y: 0.0 },
button: MouseButton::Left,
buttons: 1,
modifiers: KeyModifiers::new(),
}),
);
}