use slate_framework::types::ElementId;
use slate_framework::{FocusRegistry, FocusableEntry};
fn id(n: u64) -> ElementId {
ElementId::from_raw(n)
}
fn entry(n: u64, tab_index: i32) -> FocusableEntry {
FocusableEntry {
id: id(n),
tab_index,
focus_ring: true,
}
}
#[test]
fn tab_forward_tree_order_when_all_zero() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.register(entry(2, 0));
r.register(entry(3, 0));
assert_eq!(r.shift_forward(), Some(id(1)));
r.set_focus(id(1));
assert_eq!(r.shift_forward(), Some(id(2)));
r.set_focus(id(2));
assert_eq!(r.shift_forward(), Some(id(3)));
r.set_focus(id(3));
assert_eq!(r.shift_forward(), Some(id(1)));
}
#[test]
fn tab_backward_tree_order_when_all_zero() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.register(entry(2, 0));
r.register(entry(3, 0));
assert_eq!(r.shift_backward(), Some(id(3)));
r.set_focus(id(3));
assert_eq!(r.shift_backward(), Some(id(2)));
r.set_focus(id(2));
assert_eq!(r.shift_backward(), Some(id(1)));
r.set_focus(id(1));
assert_eq!(r.shift_backward(), Some(id(3)));
}
#[test]
fn positive_tab_index_hoisted_before_zero() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0)); r.register(entry(2, 2)); r.register(entry(3, 1)); r.register(entry(4, 0));
assert_eq!(r.shift_forward(), Some(id(1)));
r.set_focus(id(1));
assert_eq!(r.shift_forward(), Some(id(4))); r.set_focus(id(4));
assert_eq!(r.shift_forward(), Some(id(3))); r.set_focus(id(3));
assert_eq!(r.shift_forward(), Some(id(2))); }
#[test]
fn negative_tab_index_skipped_by_tab_but_focusable_programmatically() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.register(entry(2, -1));
r.register(entry(3, 0));
assert_eq!(r.shift_forward(), Some(id(1)));
r.set_focus(id(1));
assert_eq!(r.shift_forward(), Some(id(3)));
r.set_focus(id(3));
assert_eq!(r.shift_forward(), Some(id(1)));
assert!(r.set_focus(id(2)));
assert_eq!(r.focused(), Some(id(2)));
assert!(!r.is_tab_reachable(id(2)));
assert!(r.is_focusable(id(2)));
}
#[test]
fn prune_missing_clears_focused_when_id_absent() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.set_focus(id(1));
assert_eq!(r.focused(), Some(id(1)));
r.clear();
r.register(entry(2, 0));
r.prune_missing();
assert_eq!(r.focused(), None);
}
#[test]
fn prune_missing_keeps_focused_when_id_still_registered() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.set_focus(id(1));
r.clear();
r.register(entry(1, 0));
r.register(entry(2, 0));
r.prune_missing();
assert_eq!(r.focused(), Some(id(1)));
}
#[test]
fn set_focus_returns_false_for_unregistered_id() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
assert!(!r.set_focus(id(999)));
assert_eq!(r.focused(), None);
}
#[test]
fn forward_wrap_around_at_boundary() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.register(entry(2, 0));
r.set_focus(id(2));
assert_eq!(r.shift_forward(), Some(id(1)));
}
#[test]
fn backward_wrap_around_at_boundary() {
let mut r = FocusRegistry::new();
r.register(entry(1, 0));
r.register(entry(2, 0));
r.set_focus(id(1));
assert_eq!(r.shift_backward(), Some(id(2)));
}
#[test]
fn no_tab_reachable_returns_none() {
let mut r = FocusRegistry::new();
r.register(entry(1, -1));
r.register(entry(2, -2));
assert_eq!(r.shift_forward(), None);
assert_eq!(r.shift_backward(), None);
}
#[test]
fn entry_lookup_returns_metadata() {
let mut r = FocusRegistry::new();
r.register(FocusableEntry {
id: id(1),
tab_index: 5,
focus_ring: false,
});
let e = r.entry(id(1)).expect("entry present");
assert_eq!(e.tab_index, 5);
assert!(!e.focus_ring);
}