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

nordisk/nornir

tests/viz_bloodstream.rs

//! Headless robot-UI drive of the 🩸 **Bloodstream** tab (feature `viz`).
//!
//! Proves the DONE contract without a window or GPU: switch to the tab, assert the
//! organic body renders REAL workspace crates (organs) + arteries (vessels), then
//! **drill into an organ** through the control channel (`bloodstream.expand:<crate>`)
//! and assert the **recursive external-dependency layer appears** — a non-empty
//! crates.io deps-of-deps closure reaching ≥2 rings deep — read back from
//! `state_json` (LAW #6). Same pattern as `tests/viz_demo.rs`: one `ctx.run` per
//! frame drives `draw_ui`, which polls the control channel.
#![cfg(feature = "viz")]

use std::path::PathBuf;

use nornir::viz::UrdrThreadsApp;
use nornir::viz::control::VizCommand;

fn build_app() -> UrdrThreadsApp {
    let warehouse_root =
        std::env::temp_dir().join(format!("nornir-viz-bloodstream-{}", std::process::id()));
    let _ = std::fs::create_dir_all(&warehouse_root);
    // No live warehouse ⇒ the tab falls back to nornir's OWN body (embedded lock),
    // so the render + the recursive drill-down are real, deterministic data.
    UrdrThreadsApp::with_repos(
        warehouse_root,
        "nornir".to_string(),
        PathBuf::new(),
        vec!["nornir".to_string()],
    )
}

/// One headless frame so `draw_ui` (and the pane's `draw`) runs.
fn tick(app: &mut UrdrThreadsApp) {
    let ctx = egui::Context::default();
    // egui 0.36 debug-asserts on a FullOutput dropped with unapplied texture
    // deltas; nothing is uploaded headless, so they are cleared (2026-10-03).
    ctx.run_ui(egui::RawInput::default(), |ui| app.draw_ui(ui)).textures_delta.clear();
}

#[test]
fn bloodstream_renders_body_then_drills_into_recursive_external_deps() {
    let mut app = build_app();

    // 1) Switch to the Bloodstream tab and pump a few frames so the body builds.
    app.apply_command(&VizCommand {
        tab: Some("Bloodstream".into()),
        ..Default::default()
    });
    for _ in 0..4 {
        tick(&mut app);
    }

    let state = app.state_json();
    assert_eq!(state["tab"], "Bloodstream", "the tab switched");
    let blood = &state["bloodstream"];
    let organs = blood["organs"].as_array().expect("organs is an array");
    assert!(
        !organs.is_empty(),
        "the circulatory body rendered REAL workspace crates as organs (got 0)"
    );
    assert_eq!(
        blood["from_data"], true,
        "built from real data, not a demo/blank"
    );
    // Every organ carries an anatomical slot + a body position (the render coords).
    assert!(
        organs
            .iter()
            .all(|o| o["organ"].is_string() && o["x"].is_number() && o["y"].is_number())
    );
    // Vessels (arteries) wire the organs together.
    assert!(
        blood["vessel_count"].as_u64().unwrap_or(0) >= 1,
        "at least one artery between organs"
    );
    // Nothing drilled yet (lazy).
    assert_eq!(
        blood["external_count"].as_u64().unwrap(),
        0,
        "no capillaries before drill-down"
    );

    // 2) Pick an organ to drill into — prefer `nornir` (a big closure), else the
    //    first organ the body seated.
    let target = organs
        .iter()
        .find_map(|o| o["crate"].as_str().filter(|c| *c == "nornir"))
        .or_else(|| organs[0]["crate"].as_str())
        .expect("an organ crate name")
        .to_string();

    // 3) Drill in through the control channel (the robot-UI `viz.click` path).
    app.apply_command(&VizCommand {
        click_id: Some(format!("bloodstream.expand:{target}")),
        ..Default::default()
    });
    for _ in 0..4 {
        tick(&mut app);
    }

    // 4) Assert the RECURSIVE external-dependency layer appeared (non-empty), and
    //    that it is genuinely deps-of-deps (reaches ≥2 rings deep).
    let state2 = app.state_json();
    let blood2 = &state2["bloodstream"];
    let total_ext = blood2["external_count"].as_u64().unwrap();
    assert!(
        total_ext > 0,
        "drilling `{target}` surfaced its non-workspace transitive deps (got 0)"
    );

    let drilled = blood2["organs"]
        .as_array()
        .unwrap()
        .iter()
        .find(|o| o["crate"] == serde_json::json!(target))
        .expect("the drilled organ is present");
    assert_eq!(drilled["expanded"], true, "`{target}` is now expanded");
    let ext_here = drilled["external_count"].as_u64().unwrap();
    assert!(ext_here > 0, "`{target}` has a non-empty external closure");
    assert!(
        drilled["external_max_depth"].as_u64().unwrap() >= 2,
        "the closure is genuinely RECURSIVE (deps-of-deps, depth ≥2): {:?}",
        drilled["external_max_depth"]
    );
    // The external entries carry real name/version/depth (crates.io resolver data).
    let ext = drilled["external"].as_array().unwrap();
    assert!(
        ext.iter()
            .all(|e| e["name"].is_string() && e["version"].is_string() && e["depth"].is_number())
    );
    assert!(
        ext.iter().any(|e| e["depth"].as_u64() == Some(1)),
        "a direct external dep (depth 1) is present"
    );
    assert!(
        ext.iter().any(|e| e["depth"].as_u64().unwrap_or(0) >= 2),
        "a transitive deps-of-deps entry (depth ≥2) is present"
    );

    // 5) Collapse clears the capillaries (drill-down is toggleable).
    app.apply_command(&VizCommand {
        click_id: Some(format!("bloodstream.expand:{target}")),
        ..Default::default()
    });
    for _ in 0..2 {
        tick(&mut app);
    }
    let state3 = app.state_json();
    assert_eq!(
        state3["bloodstream"]["external_count"].as_u64().unwrap(),
        0,
        "collapsing the organ dropped its capillaries"
    );
}