use crate::env::{Env, RuntimeState};
use crate::lowering::{LoweringContext};
use crate::ui::traits::Lower;
use crate::ui::Node;
use crate::ui::widgets::button::Button;
use crate::ui::widgets::focus_scope::FocusScope;
use crate::hit_test::find_next_focus_node;
use fission_ir::{CoreIR, NodeId, Op};
#[test]
fn test_focus_scope_traversal() {
let env = Env::default();
let runtime_state = RuntimeState::default();
let action = crate::ActionEnvelope { id: crate::ActionId::from_u128(1), payload: vec![] };
let b1 = Button { on_press: Some(action.clone()), ..Default::default() };
let b2 = Button { on_press: Some(action.clone()), ..Default::default() };
let b3 = Button { on_press: Some(action.clone()), ..Default::default() };
let b4 = Button { on_press: Some(action.clone()), ..Default::default() };
let scope = FocusScope {
is_barrier: true,
children: vec![b2.into_node(), b3.into_node()],
..Default::default()
};
let root = crate::ui::widgets::column::Column {
children: vec![b1.into_node(), scope.into_node(), b4.into_node()],
..Default::default()
};
let mut cx = LoweringContext::new(&env, &runtime_state, None, None);
let root_id = root.lower(&mut cx);
cx.ir.root = Some(root_id);
let mut focusable = Vec::new();
for (id, node) in &cx.ir.nodes {
if let Op::Semantics(s) = &node.op {
if s.focusable {
focusable.push(*id);
}
}
}
let mut scope_id = None;
for (id, node) in &cx.ir.nodes {
if let Op::Semantics(s) = &node.op {
if s.is_focus_scope {
scope_id = Some(*id);
}
}
}
let scope_id = scope_id.expect("FocusScope node not found");
fn collect_focusable(node_id: NodeId, ir: &CoreIR, out: &mut Vec<NodeId>) {
if let Some(node) = ir.nodes.get(&node_id) {
if let Op::Semantics(s) = &node.op {
if s.focusable {
out.push(node_id);
}
}
for child in &node.children {
collect_focusable(*child, ir, out);
}
}
}
let mut scope_focusables = Vec::new();
collect_focusable(scope_id, &cx.ir, &mut scope_focusables);
assert_eq!(scope_focusables.len(), 2, "FocusScope should contain two focusable nodes");
let b2_id = scope_focusables[0];
let b3_id = scope_focusables[1];
let next = find_next_focus_node(&cx.ir, Some(b2_id), false);
assert_eq!(next, Some(b3_id), "Tab from B2 should go to B3");
let next = find_next_focus_node(&cx.ir, Some(b3_id), false);
assert_eq!(next, Some(b2_id), "Tab from B3 should cycle to B2 due to barrier");
}