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

nordisk/facett

facett-syschart/tests/a11y.rs

//! **FC-4 interaction-layer proof for facett-syschart.** Render a real
//! [`SystemChart`] (a couple of nodes with real labels + badge counts) headless
//! through `egui_kittest`, then assert each painted peer node rode into the
//! AccessKit tree as a queryable Button carrying its badge as `numeric_value`.
//!
//! Before FC-4 the nodes were `painter.circle_filled`/`painter.text` only — zero
//! accesskit nodes, invisible to `get_by_label` / a robot driver. This proves the
//! per-node `facett_core::a11y::node` call (keyed on the stable `SysNode.id`)
//! makes them findable, labelled, and value-carrying.

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

use egui::accesskit::Role;
use egui_kittest::Harness;
use egui_kittest::kittest::{NodeT, Queryable};

use facett_core::Facet;
use facett_syschart::{SysEdge, SysNode, SystemChart};

fn chart() -> SystemChart {
    let nodes = vec![
        SysNode::new("pki", "PKI", egui::Color32::from_rgb(120, 200, 255), (0.2, 0.2)).badge(3),
        SysNode::new("oidc", "OIDC", egui::Color32::from_rgb(200, 160, 255), (0.8, 0.2)).badge(7),
    ];
    let edges = vec![SysEdge::new("pki", "oidc")];
    SystemChart::new("System Map", nodes, edges)
}

#[test]
fn painted_nodes_are_queryable_buttons_with_badge_value() {
    let mut c = chart();
    let mut harness = Harness::new_ui(move |ui| {
        c.ui(ui);
    });
    harness.run();

    // "PKI · 3 events" — role Button, numeric_value = the badge count 3.
    let pki = harness.get_by_label("PKI · 3 events").accesskit_node();
    assert_eq!(pki.role(), Role::Button, "a painted peer node must expose a Button role (FC-4)");
    assert_eq!(
        pki.numeric_value(),
        Some(3.0),
        "the node's badge count must ride into the AccessKit tree as numeric_value"
    );

    // "OIDC · 7 events" — a second node, different stable id → distinct addressable node.
    let oidc = harness.get_by_label("OIDC · 7 events").accesskit_node();
    assert_eq!(oidc.role(), Role::Button);
    assert_eq!(oidc.numeric_value(), Some(7.0));
    #[cfg(feature = "testmatrix")]
    facett_core::testmatrix::emit(
        "SystemChart",
        "fc4_node_badge_value",
        pki.numeric_value() == Some(3.0) && oidc.numeric_value() == Some(7.0),
        "PKI badge=3, OIDC badge=7 as a11y values",
    );
}

#[test]
fn clicking_a_node_selects_it_by_stable_id() {
    // Share the chart with the closure so we can read its real selection back out
    // after driving a real click through the AccessKit node (inject input → assert
    // output). FC-5: selection must land on the stable SysNode.id, not a loop index.
    let chart_ref = Rc::new(RefCell::new(chart()));
    let in_ui = chart_ref.clone();
    let mut harness = Harness::new_ui(move |ui| {
        in_ui.borrow_mut().ui(ui);
    });
    harness.run();
    assert!(chart_ref.borrow().selected().is_none(), "starts unselected");

    // Click the OIDC node's accesskit button, then let the click flow into ui().
    harness.get_by_label("OIDC · 7 events").click();
    harness.run();

    assert_eq!(
        chart_ref.borrow().selected(),
        Some("oidc"),
        "clicking the painted node selects it by its stable id (FC-4 click → FC-5 id)"
    );
    assert_eq!(chart_ref.borrow().state_json()["selected"], "oidc");

    // Clicking the same node again toggles it back off.
    harness.get_by_label("OIDC · 7 events").click();
    harness.run();
    assert!(chart_ref.borrow().selected().is_none(), "re-click toggles selection off");
    #[cfg(feature = "testmatrix")]
    facett_core::testmatrix::emit(
        "SystemChart",
        "fc5_click_selects_by_stable_id",
        chart_ref.borrow().selected().is_none(),
        "click oidc selected then re-click toggled off (stable id)",
    );
}