facett-brokkrview/tests/render.rs
//! **CPU render-proof for facett-brokkrview.** The inline tests cover the Elm
//! `update` transitions + `state_json`; the `ui()` render path — the roster rows +
//! Run buttons, the tree stage/step chips, and the DAG painter — is never executed
//! there. This drives real `egui_kittest` frames in **all three** surfaces so the
//! painter runs and the controls ride into the AccessKit tree (LAW #4: prove the
//! surface renders non-blank), and that a REAL click on a surface toggle mutates
//! the model through the pure-view loop.
use egui_kittest::kittest::Queryable;
use egui_kittest::Harness;
use facett_core::Facet;
use facett_brokkrview::{BrokkrView, ViewMode};
#[test]
fn roster_surface_paints_run_buttons_and_toggles() {
let mut v = BrokkrView::demo("Brokkr");
let mut harness = Harness::builder()
.with_size(egui::vec2(820.0, 640.0))
.build_ui(move |ui| v.ui(ui));
harness.run();
assert!(harness.query_by_label("▤ Roster").is_some(), "the Roster toggle painted");
assert!(harness.query_by_label("▸ Tree").is_some(), "the Tree toggle painted");
assert!(harness.query_by_label("◈ DAG").is_some(), "the DAG toggle painted");
assert!(harness.query_by_label("▶ nornir-ci").is_some(), "the per-pipeline Run button painted");
}
#[test]
fn tree_surface_renders_stage_step_chips_without_panicking() {
let mut v = BrokkrView::demo("Brokkr");
v.update_json(r#"{"set_view":"tree"}"#);
let mut harness = Harness::builder()
.with_size(egui::vec2(720.0, 620.0))
.build_ui(move |ui| v.ui(ui));
harness.run();
// The project · pipeline header + a step name painted.
assert!(harness.query_by_label("nornir · nornir-ci").is_some(), "the tree header painted");
assert!(harness.query_by_label("compile").is_some(), "a step row painted");
}
#[test]
fn dag_surface_paints_the_graph_without_panicking() {
let mut v = BrokkrView::demo("Brokkr");
v.update_json(r#"{"set_view":"dag"}"#);
let mut harness = Harness::builder()
.with_size(egui::vec2(760.0, 560.0))
.build_ui(move |ui| v.ui(ui)); // paints nodes + edges via the painter
harness.run();
assert!(harness.query_by_label("DAG · all green").is_some(), "the all-green DAG header painted");
}
#[test]
fn clicking_a_surface_toggle_switches_the_view_through_the_pure_view_loop() {
// A real click on the "◈ DAG" toggle must flip the model's view via the
// FC-9 view→update loop the Facet `ui` bridge runs (not a programmatic call).
let v = BrokkrView::demo("Brokkr");
assert_eq!(v.model().view, ViewMode::Roster);
let mut app = v;
let mut harness = Harness::builder()
.with_size(egui::vec2(820.0, 640.0))
.build_ui(move |ui| app.ui(ui));
harness.run();
harness.get_by_label("◈ DAG").click();
harness.run();
// The DAG surface is now active — its header proves the view switched.
assert!(harness.query_by_label("DAG · all green").is_some(), "clicking the toggle switched to the DAG surface");
}
/// **F5 — the surface toggles + Run buttons drive the OBSERVABLE state through real
/// clicks.** The `SetView` toggles and per-pipeline Run buttons were only ever driven
/// via the JSON/Elm path; this clicks them for real and asserts `state_json` — the
/// view field flips to `"tree"`, and pressing a Run button GROWS the log.
#[test]
fn clicking_tree_toggle_and_run_button_drive_state_json() {
let mut harness = Harness::builder()
.with_size(egui::vec2(820.0, 720.0))
.build_ui_state(|ui, v: &mut BrokkrView| { v.ui(ui); }, BrokkrView::demo("Brokkr"));
harness.run();
assert_eq!(harness.state().state_json()["view"], "roster", "opens on the roster surface");
// Click ▸ Tree → the model's view flips through the pure view→update loop.
harness.get_by_label("▸ Tree").click();
harness.run();
assert_eq!(
harness.state().state_json()["view"], "tree",
"a real click on ▸ Tree flips state_json[\"view\"] to tree"
);
// Back to the roster (where the Run buttons live), then press a Run button and
// assert the log grew by the "running '<pipeline>'…" line the click pushes.
harness.get_by_label("▤ Roster").click();
harness.run();
let before = harness.state().state_json()["log"].as_array().map(|a| a.len()).unwrap_or(0);
harness.get_by_label("▶ nornir-ci").click();
harness.run();
let after = harness.state().state_json()["log"].as_array().map(|a| a.len()).unwrap_or(0);
assert!(after > before, "pressing ▶ Run grows the log: {before} -> {after}");
let log = harness.state().state_json()["log"].clone();
assert!(
log.as_array().unwrap().iter().any(|l| l.as_str().is_some_and(|s| s.contains("nornir-ci"))),
"the new log line names the pipeline that was run: {log}"
);
}