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

nordisk/dwarves

dwarves-gui/tests/robot_dataview.rs

//! **ROBOT SCENARIO — the 🏢 Data view tab: the warehouse deck wall + the DataFusion
//! SQL prompt.**
//!
//! Proves the tab that brought the facett warehouse dashboard back under Mímir:
//! 1. Scanning binds the Mímir/warehouse tables into a `facett_warehousedeck` WALL of
//!    ≥N panes (a 3D graph, a chart, grids), and the wall RENDERS for real in an
//!    `egui_kittest` frame (the deck toolbar + the SQL prompt are in the AccessKit tree,
//!    not merely `state_json`).
//! 2. The SQL prompt runs a known query (`SELECT repo, count(*) FROM git_heat_facts GROUP
//!    BY repo`) and shows a result grid (behind `--features dataview-sql`, the DataFusion
//!    engine skade re-exports).
//! 3. A bad SQL shows an HONEST error — never a crash, never an empty-as-ok.
//!
//! It drives the pane's REAL `Facet` seam over a deterministic fixture (no server), and
//! emits a `nornir-testmatrix` `functional_status` cell under `--features testmatrix`.

use std::cell::RefCell;

use dwarves_gui::dataview::{DataViewPane, DataViewSource};
use facett_core::Facet;
use nornir_warehouse_embed::WarehouseScan;

/// A never-blank fixture warehouse of tables that are still written: git heat across two
/// repos (a chart; the sample GROUP BY yields two rows), the dependency graph (a 3D
/// graph), coverage and test outcomes (grids). The rest of the key tables are "not
/// served" so a missing table reads as a named absence. (`symbol_facts` / `call_edges`
/// have no writer since Mímir v2: the wall does not ask for them.)
struct FixtureSource;

impl FixtureSource {
    fn s(cols: &[&str], rows: &[&[&str]]) -> WarehouseScan {
        WarehouseScan {
            columns: cols.iter().map(|s| s.to_string()).collect(),
            rows: rows
                .iter()
                .map(|r| r.iter().map(|s| s.to_string()).collect())
                .collect(),
        }
    }
}

impl DataViewSource for FixtureSource {
    fn scan(&self, table: &str) -> Result<WarehouseScan, String> {
        match table {
            "test_outcomes" => Ok(Self::s(
                &["repo", "test_name", "outcome"],
                &[
                    &["znippy", "parse_stream_round_trips", "ok"],
                    &["korp", "spark_ingest_smoke", "failed"],
                ],
            )),
            "dep_graph_edges" => Ok(Self::s(
                &["from_repo", "to_repo"],
                &[
                    &["korp", "znippy"],
                    &["korp", "skade"],
                    &["skade", "znippy"],
                ],
            )),
            "git_heat_facts" => Ok(Self::s(
                &["repo", "file", "commits_90d"],
                &[
                    &["znippy", "src/hot.rs", "37"],
                    &["znippy", "src/lib.rs", "12"],
                    &["korp", "src/spark.rs", "5"],
                ],
            )),
            "coverage" => Ok(Self::s(
                &["repo", "pct"],
                &[&["znippy", "84"], &["korp", "61"]],
            )),
            other => Err(format!("nornir warehouse not_served: no table `{other}`")),
        }
    }
    fn describe(&self) -> String {
        "fixture (demo)".to_string()
    }
}

#[test]
fn dataview_renders_the_deck_wall_and_runs_the_sql_prompt() {
    use egui_kittest::kittest::Queryable;
    use egui_kittest::Harness;

    let mut pane = DataViewPane::with_source(Box::new(FixtureSource));

    // 1) Scan binds the served key tables into a deck wall of ≥3 panes.
    pane.update_json("\"scan\"");
    let s = pane.state_json();
    assert_eq!(s["scanned"], true, "scan built the deck");
    let panes = s["pane_count"].as_u64().unwrap();
    assert!(
        panes >= 3,
        "the wall binds ≥3 Mímir tables to panes (got {panes})"
    );
    assert!(
        s["deck"]["graph3d_count"].as_u64().unwrap() >= 1,
        "dep_graph_edges → a 3D graph pane"
    );
    assert!(
        s["deck"]["chart_count"].as_u64().unwrap() >= 1,
        "git_heat_facts → a chart pane"
    );
    assert!(
        s["deck"]["grid_count"].as_u64().unwrap() >= 1,
        "coverage/test_outcomes → grid panes"
    );
    // This pane was given no code room (`with_source` only): the wall has no code-room
    // pane and claims none. The room's two panes are driven in `robot_dataview_room.rs`.
    assert!(
        s["room"]["symbols"].is_null() && s["room"]["calls"].is_null(),
        "no room was asked: {}",
        s["room"]
    );
    assert!(
        s["room"]["symbols_shown"].is_null() && s["room"]["call_nodes"].is_null(),
        "…so nothing is counted: {}",
        s["room"]
    );

    // 2) The wall RENDERS for real in an egui frame (not merely in state_json).
    let cell = RefCell::new(pane);
    {
        let mut h = Harness::builder()
            .with_size(egui::vec2(1200.0, 900.0))
            .build_ui(|ui| Facet::ui(&mut *cell.borrow_mut(), ui));
        // The 3D-graph panes animate (force layout keeps requesting repaint), so a fixed
        // number of steps rather than `run()`-to-stable — the wall never goes idle.
        for _ in 0..3 {
            h.step();
        }
        assert!(
            h.get_all_by_label_contains("Data view").next().is_some(),
            "the tab heading drew"
        );
        assert!(
            h.get_all_by_label_contains("Run SQL").next().is_some(),
            "the SQL prompt drew"
        );
    }

    // 3) The SQL prompt: a known query → a result; a bad query → an honest error.
    let mut pane = cell.into_inner();
    let sql_ok;
    let bad_ok;
    #[cfg(feature = "dataview-sql")]
    {
        let before = pane.state_json()["pane_count"].as_u64().unwrap();
        pane.update_json(
            r#"{"sql":"SELECT repo, count(*) AS n FROM git_heat_facts GROUP BY repo"}"#,
        );
        let q = pane.state_json();
        sql_ok = q["sql_ok"] == true && q["sql_rows"] == 2;
        assert!(
            sql_ok,
            "the known query ran and grouped into two repos: {}",
            q["sql_status"]
        );
        assert_eq!(
            q["pane_count"].as_u64().unwrap(),
            before + 1,
            "the SQL result fed the deck as a new pane"
        );

        pane.update_json(r#"{"sql":"SELECT * FROM no_such_table"}"#);
        let b = pane.state_json();
        bad_ok = b["sql_ok"] == false && b["sql_error"].is_string();
        assert!(
            bad_ok,
            "a bad query shows an honest error, no crash: {}",
            b["sql_status"]
        );
    }
    #[cfg(not(feature = "dataview-sql"))]
    {
        // Engine off: the prompt says so honestly (names the feature). Still no crash.
        pane.update_json(r#"{"run_sql":true}"#);
        let q = pane.state_json();
        sql_ok = q["sql_enabled"] == false;
        bad_ok = q["sql_error"]
            .as_str()
            .map(|e| e.contains("dataview-sql"))
            .unwrap_or(false);
        assert!(
            sql_ok && bad_ok,
            "off-build names the feature to rebuild with: {}",
            q["sql_error"]
        );
    }

    #[cfg(feature = "testmatrix")]
    nornir_testmatrix::functional_status(
        "dwarves-gui",
        "dataview_deck_wall_and_sql_prompt",
        panes >= 3 && sql_ok && bad_ok,
        "the 🏢 Data view tab binds ≥3 Mímir/warehouse tables into a facett-warehousedeck \
         wall (3D graph + chart + grids) that renders in a real egui frame, and its \
         DataFusion SQL prompt runs a known query into a result (fed to a deck pane) while \
         a bad query shows an honest error — the facett warehouse dashboard is back under Mímir",
    );
    let _ = (sql_ok, bad_ok);
}