Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/dwarves

crates/nornir-warehouse-nav/tests/robot_camera_rules.rs

//! **Warehouse →: the graph opens centred in what the viewer sees, and a click never
//! moves it** — rendered (kittest, real clicks), with the pane in an OVER-WIDE layout
//! (a 6 000 px wide region on a 1 400 px window, as a scroll area hands its content):
//!
//! * first show (repo grid, and the world graph): fitted, centred (±2 px) and wholly
//!   inside the visible canvas;
//! * 📌 Stay: a click that drills (repo → its crates; a world repo → its functions)
//!   leaves the camera exactly where it was;
//! * 🎯 Focus: the drill flies to frame what it opened, centred;
//! * ⊙ fit: back to the whole graph, centred.
//!
//! The owner (loki, UI 8d0bb3c): "the fix for when I click the graph and it moves to the
//! right outside the window is not fixed — it's in Warehouse →". RED before: the canvas
//! took the whole 6 000 px (the camera centres on it), every drill reset the camera to
//! zoom 1 with world (0, 0) at that far-right centre, and a world drill re-framed.

#![cfg(not(target_arch = "wasm32"))]

use std::cell::RefCell;
use std::rc::Rc;

use egui::{vec2, Pos2, Rect};
use egui_kittest::kittest::Queryable;
use egui_kittest::Harness;
use facett_core::fly::NavMode;
use facett_core::Facet;
use nornir_warehouse_nav::WarehouseNav;

type Nav = Rc<RefCell<WarehouseNav>>;

fn harness(nav: WarehouseNav, mode: NavMode) -> (Harness<'static>, Nav) {
    let nav = Rc::new(RefCell::new(nav));
    let n = nav.clone();
    let h = Harness::builder().with_size(vec2(1400.0, 900.0)).with_step_dt(1.0 / 60.0).build_ui(move |ui| {
        let wide = Rect::from_min_size(ui.max_rect().min, vec2(6000.0, ui.max_rect().height()));
        ui.scope_builder(egui::UiBuilder::new().max_rect(wide), |ui| n.borrow_mut().ui(ui));
    });
    mode.remember(&h.ctx);
    (h, nav)
}

fn steps(h: &mut Harness<'static>, n: usize) {
    for _ in 0..n {
        h.step();
    }
}

fn camera(nav: &Nav) -> (egui::Vec2, f32) {
    let v = nav.borrow().world_view_snapshot();
    (v.pan, v.zoom)
}

fn assert_centred(nav: &Nav, what: &str) {
    let (b, seen) = nav.borrow().screen_box().expect("drawn");
    assert!(seen.width() <= 1400.0 + 0.5, "{what}: the canvas is the visible width, not the layout's 6 000 px: {seen:?}");
    assert!((b.center() - seen.center()).length() <= 2.0, "{what}: centred: box {b:?} in {seen:?}");
    assert!(seen.expand(0.5).contains_rect(b), "{what}: wholly visible: box {b:?} in {seen:?}");
}

fn click(h: &mut Harness<'static>, p: Pos2) {
    h.input_mut().events.push(egui::Event::PointerMoved(p));
    h.step();
    for pressed in [true, false] {
        h.input_mut().events.push(egui::Event::PointerButton { pos: p, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() });
        h.step();
    }
}

fn first_repo(nav: &Nav) -> (String, Pos2) {
    let n = nav.borrow();
    let (_, seen) = n.screen_box().unwrap();
    let st = Facet::state_json(&*n);
    let ids: Vec<String> = st["nodes"].as_array().unwrap().iter().filter_map(|v| v["id"].as_str().or_else(|| v.as_str()).map(str::to_string)).collect();
    ids.into_iter()
        .filter(|i| i.starts_with("repo:"))
        .filter_map(|i| n.node_on_screen(&i).map(|p| (i, p)))
        .find(|(_, p)| seen.shrink(20.0).contains(*p))
        .expect("a repo on screen")
}

/// First show of the repo grid: centred and wholly visible in the visible canvas.
#[test]
fn the_warehouse_graph_opens_centred() {
    let (mut h, nav) = harness(WarehouseNav::from_fixture(), NavMode::Stay);
    steps(&mut h, 4);
    assert_centred(&nav, "first show");
    let (_, seen) = nav.borrow().screen_box().unwrap();
    assert!(seen.height() >= 0.6 * 900.0, "the graph covers most of the tab's height: {seen:?}");
}

/// 📌 Stay: a click that drills into a repo leaves the camera exactly where it was.
#[test]
fn stay_a_drill_click_never_moves_the_camera() {
    let (mut h, nav) = harness(WarehouseNav::from_fixture(), NavMode::Stay);
    steps(&mut h, 4);
    let (id, p) = first_repo(&nav);
    let cam = camera(&nav);
    click(&mut h, p);
    steps(&mut h, 40);
    assert_eq!(Facet::state_json(&*nav.borrow())["level"], "repo", "the click on {id} drilled");
    assert_eq!(camera(&nav), cam, "the camera did not move");
}

/// 🎯 Focus: the drill flies to frame the repo's crates, centred.
#[test]
fn focus_a_drill_click_frames_what_it_opened() {
    let (mut h, nav) = harness(WarehouseNav::from_fixture(), NavMode::Focus);
    steps(&mut h, 4);
    let (_, p) = first_repo(&nav);
    click(&mut h, p);
    steps(&mut h, 60);
    assert_eq!(Facet::state_json(&*nav.borrow())["level"], "repo");
    assert_centred(&nav, "after a Focus drill");
}

/// ⊙ fit: after a drag, the whole graph comes back centred.
#[test]
fn fit_brings_the_graph_back_centred() {
    let (mut h, nav) = harness(WarehouseNav::from_fixture(), NavMode::Stay);
    steps(&mut h, 4);
    let (a, b) = (Pos2::new(700.0, 500.0), Pos2::new(1100.0, 700.0));
    h.hover_at(a);
    h.step();
    h.drag_at(a);
    h.step();
    h.hover_at(b);
    h.step();
    h.drop_at(b);
    h.step();
    h.get_by_label("⊙ fit").click();
    steps(&mut h, 60);
    assert_centred(&nav, "after ⊙ fit");
}

/// The world graph: first show centred in the visible canvas; a 📌 Stay click on a
/// repo star (which focuses that repo) leaves the camera where it was.
#[test]
fn the_world_graph_opens_centred_and_a_click_never_moves_it() {
    let (mut h, nav) = harness(WarehouseNav::from_fixture_with_functions(200), NavMode::Stay);
    nav.borrow_mut().update_json(r#"{"world":true}"#);
    steps(&mut h, 6);
    assert_centred(&nav, "world first show");
    let p = {
        let n = nav.borrow();
        let (_, seen) = n.screen_box().unwrap();
        let shot = Facet::state_json(&*n);
        let _ = shot;
        // the first world node (a repo star) on screen
        (0..50).filter_map(|i| n.node_on_screen(&format!("w{i}"))).find(|p| seen.shrink(20.0).contains(*p)).expect("a star on screen")
    };
    let cam = camera(&nav);
    click(&mut h, p);
    steps(&mut h, 40);
    assert_eq!(camera(&nav), cam, "a world click did not move the camera");
}