//! Pass conditions for RUST.md's I4, exercised the same way //! `layout_tests.rs` exercises LAYOUT.md's: `AccessTree` only touches //! `Widgets`/`UiRenderState`, neither of which needs a GPU or a window, so //! it can be driven directly against `layout_tests::TestRsc`. use crate::layout_tests::TestRsc; use crate::prelude::*; #[test] fn a_named_widget_reaches_the_tree_with_its_role_and_bounds() { let mut rsc = TestRsc { ui: UiData::default(), }; let leaf: WeakWidget = rect(UiColor::WHITE).label("Add task").add(&mut rsc); let root = leaf.upgrade(&mut rsc).any(); let mut render = UiRenderState::new(); render.resize((800.0, 600.0)); render.update(&root, &mut rsc); let mut access = AccessTree::new(); let update = access .update(rsc.widgets(), &render, &rsc) .expect("a first draw with a named widget must produce a tree"); // One node for the widget, one for the synthetic window root. assert_eq!(update.nodes.len(), 2); let (_, node) = update .nodes .iter() .find(|(_, n)| n.role() != accesskit::Role::Window) .expect("the named widget's own node"); assert_eq!(node.label(), Some("Add task")); assert_eq!(node.role(), accesskit::Role::Unknown); let bounds = node.bounds().expect("a drawn widget reports its bounds"); let region = render .window_region(&leaf, &rsc) .expect("the widget is active after render.update"); assert_eq!(bounds.x0, region.top_left.x as f64); assert_eq!(bounds.y0, region.top_left.y as f64); assert_eq!(bounds.x1, region.bot_right.x as f64); assert_eq!(bounds.y1, region.bot_right.y as f64); } #[test] fn a_widget_with_no_label_never_reaches_the_tree() { let mut rsc = TestRsc { ui: UiData::default(), }; let root = rsc.ui.widgets.add_strong(rect(UiColor::WHITE)); let mut render = UiRenderState::new(); render.resize((800.0, 600.0)); render.update(&root.any(), &mut rsc); let mut access = AccessTree::new(); assert!( access.update(rsc.widgets(), &render, &rsc).is_none(), "no widget was ever `.label()`ed, so there is nothing to report -- \ not even an empty tree change" ); } /// LAYOUT.md's "a moved subtree" lesson applies here too: `resolved_region` /// (which `window_region` sits on) walks the move-offset chain, so a /// widget moved via `Offset` -- not redrawn from scratch -- must still /// report where it actually ended up. #[test] fn bounds_follow_a_moved_widget_and_updates_stay_incremental() { let mut rsc = TestRsc { ui: UiData::default(), }; let leaf: WeakWidget = rect(UiColor::WHITE).label("thing").add(&mut rsc); let leaf_strong = leaf.upgrade(&mut rsc).any(); let offset = rsc.ui.widgets.add_strong(Offset { inner: leaf_strong, amt: UiVec2::ZERO, }); let offset_id = offset.weak(); let root = offset.any(); let mut render = UiRenderState::new(); render.resize((800.0, 600.0)); render.update(&root, &mut rsc); let mut access = AccessTree::new(); access .update(rsc.widgets(), &render, &rsc) .expect("the first draw is always a change"); assert_eq!(access.take_rebuilds(), 1); // Unchanged frame: nothing moved, nothing renamed -- `update` must // report no change, and the rebuild counter (I4's twin of // `take_counters`) must stay at 0. render.update(&root, &mut rsc); assert!(access.update(rsc.widgets(), &render, &rsc).is_none()); assert_eq!(access.take_rebuilds(), 0); // Move the child via `Offset` (a move-offset write, not necessarily a // full redraw of the leaf -- see `resolve_move_chain`) and confirm the // reported bounds shifted by exactly that amount, in exactly one more // rebuild. let before = render .window_region(&leaf, &rsc) .expect("active before the move"); rsc.ui.widgets.get_mut(&offset_id).unwrap().amt = UiVec2::abs(Vec2::new(50.0, 0.0)); render.update(&root, &mut rsc); let update = access .update(rsc.widgets(), &render, &rsc) .expect("a moved named widget is a change"); assert_eq!(access.take_rebuilds(), 1); let after = render .window_region(&leaf, &rsc) .expect("still active after the move"); // Not asserting the exact delta: `Offset`'s own `amt` -> pixel mapping // is that widget's business, not this tree's. What I4 owns is that // `AccessTree` reports whatever `window_region` says *now* -- so the // node must have moved, and in the direction the offset moved it. assert!( after.top_left.x > before.top_left.x, "the leaf's reported bounds must move right along with its offset" ); let (_, node) = update .nodes .iter() .find(|(_, n)| n.role() != accesskit::Role::Window) .unwrap(); let bounds = node.bounds().unwrap(); assert_eq!(bounds.x0, after.top_left.x as f64); }