dwarves-gui/tests/robot_claude_token.rs
//! **robot_claude_token** — the robot-UI coverage for *"what has actually run?"*
//!
//! **Funnel pane → event-sourced run history** — the funnel's own `RunRecorded` ledger
//! (folded by funnel-core), surfaced as `event_runs`, newest first.
//!
//! The scenario runs through the SHARED `nornir-robotui` framework (egui_kittest /
//! AccessKit — REUSE, never a twinned harness) and records a `nornir-testmatrix` cell.
//!
//! The Settings→Claude-token scenarios are the sibling leg; they live in
//! `src/settings.rs`'s own test module because `settings` is a module of the BINARY
//! target (declared in `main.rs`), not of the library, so an integration test cannot
//! reach it.
//!
//! **No crate-level `#![cfg(feature = ...)]`.** A feature gate at file scope would
//! silently compile this suite to ZERO tests under a bare `cargo test` and still
//! report green (the 2026-07-21 silenced-tests trap). This scenario runs
//! unconditionally.
#![cfg(not(target_arch = "wasm32"))]
use facett_core::Facet;
use nornir_robotui::egui_kittest::Harness;
use nornir_robotui::{status, Assert, Observable, RobotSession, Scenario, Step};
use serde_json::json;
/// The funnel pane wrapped as an `Observable` — the robot reads exactly what the pane
/// renders through `Facet::state_json`, no twinned oracle.
struct FunnelApp(nornir_funnel_embed::FunnelPanel);
impl Observable for FunnelApp {
fn state_json(&self) -> serde_json::Value {
Facet::state_json(&self.0)
}
}
/// **The funnel pane surfaces the EVENT-SOURCED run history.** A robot mounts the
/// embedded pane (offline — no server, no network) and asserts, through the rendered
/// state, that the funnel's `RunRecorded` ledger rides the seam newest-first with the
/// event payload intact, and that the run strip PAINTS into the AccessKit tree.
///
/// RED-when-broken: revert funnel-core's `RunRecorded` arm to validate-and-drop and
/// `event_runs` empties ⇒ every step fails.
#[test]
fn robot_drives_the_funnel_event_run_history() {
let panel = nornir_funnel_embed::FunnelPanel::new_embedded_seeded("nordisk");
let harness = Harness::builder()
.with_size(nornir_robotui::egui::Vec2::new(1400.0, 1000.0))
.build_ui_state(
|ui, app: &mut FunnelApp| Facet::ui(&mut app.0, ui),
FunnelApp(panel),
);
let mut robot = RobotSession::new(harness, "dwarves-gui");
robot.run(2); // settle the layout so every widget is in the AccessKit tree
let scenario = Scenario::new("funnel-event-run-history")
.step(
Step::new("the funnel's RunRecorded ledger rides the seam").assert(Assert::State {
pointer: "/event_run_count".into(),
expected: json!(3),
}),
)
.step(
Step::new("the history is newest-first (the projection's order)").assert(
Assert::State {
pointer: "/event_runs/0/run_id".into(),
expected: json!("r-003"),
},
),
)
.step(
Step::new("the EVENT payload survives the fold — the outcome is the recorded one")
.assert(Assert::State {
pointer: "/event_runs/2/outcome".into(),
expected: json!("ok"),
}),
)
.step(
Step::new("a run is anchored to the plan node it ran against").assert(Assert::State {
pointer: "/event_runs/2/node_id".into(),
expected: json!("n-001"),
}),
)
.step(
Step::new("the run-history strip PAINTS (rides the AccessKit tree)")
.assert(Assert::LabelVisible("runs · 3 recorded".into())),
);
let rows = robot.run_scenario(&scenario);
let all_green = rows.iter().all(|r| r.status == status::PASS);
assert!(
all_green,
"the robot observes the funnel's event-sourced run history: {:?}",
rows.iter()
.map(|r| (&r.test_name, &r.status, &r.message))
.collect::<Vec<_>>()
);
#[cfg(feature = "testmatrix")]
nornir_testmatrix::functional_status(
"dwarves-gui",
"funnel_event_run_history_robot",
all_green,
"the funnel pane's run history driven through the shared nornir-robotui framework: the RunRecorded ledger folded by funnel-core rides the seam newest-first with its payload intact and the run strip paints — history from the state engine's events, not a parallel store",
);
}