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

nordisk/holger-ui

tests/the_board_is_mounted.rs

//! ★ **The artifact flow stays mounted, on the Flow page and only there** (HBOARD-1; HOL-SEC,
//! owner 2026-10-27; HOL-SVG-RON, owner 2026-10-30; HOL-UI-FIX, owner 2026-10-31: "3 menus doing
//! the same flow"). The board went missing from where the owner looks once already, and then
//! it drew front | main | twin and nothing of the RON; later the Overview, the console's home
//! and the Flow page showed it two and three times. This guard holds: the Flow page (`/flow`)
//! mounts the ONE component `<EstateBoard/>`; the Overview shows the estate's state in cards and
//! links to the Flow, drawing nothing; the Admin page links to it; the Security page shows
//! security and NOT the board; the component shows holger's own drawing
//! (`AdminService.FlowSvg`) as an image, and the console carries no renderer of its own.

const ROOT: &str = env!("CARGO_MANIFEST_DIR");

/// A source file with its `//` comment lines dropped: a mount in a comment is no mount.
fn code(path: &str) -> String {
    let text = std::fs::read_to_string(format!("{ROOT}/{path}")).unwrap_or_else(|e| panic!("{path}: {e}"));
    text.lines().filter(|l| !l.trim_start().starts_with("//")).collect::<Vec<_>>().join("\n")
}

/// The component's own body in `page`: up to the next top-level component.
fn body(page: &str, component: &str) -> String {
    let src = code(page);
    let at = src.find(component).unwrap_or_else(|| panic!("{page}: no {component}"));
    let body = &src[at..];
    body[..body[1..].find("\n#[component]").map(|i| i + 1).unwrap_or(body.len())].to_string()
}

/// ★ **One picture, one page** (HOL-UI-FIX): the Flow page shows what its address opens (main
/// by default; level 2 or 3); the Overview (and the console's home, the same page) draws no
/// board and links to the Flow.
#[test]
fn the_flow_page_alone_mounts_the_board_and_the_others_link_to_it() {
    let flow = body("src/pages/estate_board.rs", "pub fn Flow");
    assert!(flow.contains("<EstateBoard") && flow.contains("sec::flow_open("), "the Flow page opens what its address names");
    let mounts: Vec<String> = std::fs::read_dir(format!("{ROOT}/src/pages"))
        .unwrap()
        .map(|e| e.unwrap().path())
        .filter(|p| p.file_name().is_some_and(|n| n != "estate_board.rs"))
        .filter(|p| code(&format!("src/pages/{}", p.file_name().unwrap().to_string_lossy())).contains("EstateBoard"))
        .map(|p| p.display().to_string())
        .collect();
    assert!(mounts.is_empty(), "the board is mounted again outside the Flow page: {mounts:?}");
    let overview = code("src/pages/dashboard.rs");
    assert!(!overview.contains("Machines") && !overview.contains("board-img"), "the Overview draws the flow again");
    assert!(overview.contains("ov::FLOW"), "the Overview links to the Flow page");
    assert!(code("src/overview.rs").contains(r#"pub const FLOW: &str = "/flow";"#));
    let admin = body("src/pages/admin.rs", "pub fn Admin");
    assert!(admin.contains(r#"data-board-link="estate""#) && admin.contains(r#"href="/flow""#), "the Admin page links to the board on the Flow page");
}

#[test]
fn the_security_page_shows_security_and_not_the_board() {
    let sec = body("src/pages/security.rs", "pub fn SecurityDashboard");
    assert!(!code("src/pages/security.rs").contains("EstateBoard"), "the Security page shows the machinery board again");
    assert!(sec.contains("<SecuritySummary/>"), "the Security page no longer shows the gateway's summary");
    let summary = body("src/pages/security.rs", "fn SecuritySummary");
    assert!(summary.contains("sec::load_security(&GrpcDoor)") && summary.contains("data-section"), "the summary is holger's SecuritySummary answer, a card per section");
}

#[test]
fn the_routes_lead_to_the_pages_that_mount_it() {
    let app = code("src/app.rs");
    for route in [r#"path!("/overview") view=Dashboard"#, r#"path!("/") view=Dashboard"#, r#"path!("/flow") view=Flow"#, r#"path!("/admin") view=Admin"#, r#"path!("/security") view=SecurityDashboard"#] {
        assert!(app.contains(route), "src/app.rs: the route {route} is gone");
    }
}

#[test]
fn the_board_component_shows_holgers_flow_drawing_and_draws_nothing_itself() {
    let c = code("src/pages/estate_board.rs");
    assert!(c.contains("sec::load_board(&GrpcDoor, &open)"), "the board is holger's answer, at the zoom the page asks");
    assert!(c.contains(r#"class="board-img""#) && c.contains("board-summary"), "the drawing and the server's line under it");
    assert!(c.contains(r#"class="board-hit""#) && c.contains("b.links"), "holger's clickable places, laid over the image as plain links");
    let sec = code("src/security.rs");
    assert!(sec.contains("crate::grpc::admin().flow_svg(pb::FlowSvgRequest { open"), "the drawing is holger's AdminService.FlowSvg, at the zoom the page asks");
    assert!(sec.contains("enc(&flow.svg)"), "shown as holger sent it");
    assert!(!std::path::Path::new(&format!("{ROOT}/src/board.rs")).exists() && !code("src/main.rs").contains("mod board;"), "the console carries no renderer of its own");
    assert!(!code("Cargo.toml").contains("nordisk-estate-svg"), "and no renderer crate");
    assert!(code("src/pages/mod.rs").contains("pub mod estate_board;"));
}