tests/facett_harness_drive.rs
//! **The Elm-harness DRIVE proof** — the first nornir test that exercises an
//! INDIVIDUAL embedded facett component's `update()` headless (no window, no GPU,
//! no whole-app kittest render), reads back its `Model`/`state_json`, and proves the
//! drive verdict flows DOWN into the test-matrix surface as real coverage.
//!
//! This is the payoff of the Elm migration: each facett component is a pure
//! `Model`/`Msg`/`update`/`view` value the `facett_core::harness` drives directly.
//! nornir-testmatrix stays facett-free; the facett-touching drive lives in the
//! `nornir` binary crate behind the `viz` feature (same gate as the embeds).
#![cfg(feature = "viz")]
use facett_core::harness;
use facett_jobview::{JobEntry, JobList, JobStatus, Msg as JobMsg};
use nornir::autonom::facett_probe::probe_facett_components;
use nornir::autonom::{SurfaceInputs, build_surface_and_covered};
use nornir_testmatrix::discover::covered_facetts;
/// Drive ONE component (`facett-jobview`) through a `Msg` script via the harness and
/// assert its serialized `Model` — the individual-component `update()` proof.
#[test]
fn jobview_update_drives_headless_and_snapshot_reflects_msgs() {
let mut view = JobList::new("jobs-probe");
let parent = JobEntry::new("p1", "build", JobStatus::Done);
let child = JobEntry {
parent_id: Some("p1".to_string()),
..JobEntry::new("c1", "compile", JobStatus::Running)
};
// FC-2: apply msgs through `update()` only; FC-3: read the resulting Model as JSON.
let state = harness::snapshot_json(
&mut view,
vec![
JobMsg::SetJobs(vec![parent, child]),
JobMsg::ToggleFold("p1".to_string()),
JobMsg::Select("c1".to_string()),
],
);
// The drive really mutated the Model: the selection the last Msg set is observable.
let s = state.to_string();
assert!(
s.contains("c1"),
"the selected child id must appear in the driven Model state_json: {s}"
);
assert!(
s.contains("p1"),
"the folded parent id must appear in the driven Model state_json: {s}"
);
// `snapshot` (the typed Model clone) is the same FC-3 value the JSON came from.
let model = harness::snapshot::<JobList>(&mut JobList::new("empty"), Vec::new());
// A fresh, un-driven list has no rows — proves the drive above is what populated it.
let empty = serde_json::to_value(&model).unwrap();
assert_ne!(
empty, state,
"an un-driven list differs from the driven one"
);
}
/// All six embedded components drive clean through the harness, and the driven
/// verdict becomes REAL coverage in `build_surface_and_covered` — the full seam.
#[test]
fn six_embedded_components_drive_green_and_flow_into_surface_coverage() {
let rows = probe_facett_components();
assert_eq!(rows.len(), 6, "one driven FacetRow per embedded component");
let green: Vec<&str> = rows
.iter()
.filter(|r| r.driven)
.map(|r| r.component.as_str())
.collect();
assert_eq!(
green.len(),
6,
"every embedded component must drive green: driven={green:?}"
);
// The driven rows produce exactly six covered facett-component keys...
let covered_keys = covered_facetts(&rows);
assert_eq!(covered_keys.len(), 6);
// ...and those keys land in the covered set of the assembled surface (data flows
// DOWN from the harness drive into the pure test-matrix crate).
let inputs = SurfaceInputs {
facett: rows.clone(),
..Default::default()
};
let (surface, covered) = build_surface_and_covered(&inputs, &[], &[]);
let facett_nodes = surface
.nodes
.iter()
.filter(|n| n.kind == nornir_testmatrix::discover::SurfaceKind::FacettComponent)
.count();
assert_eq!(facett_nodes, 6, "six facett-component surface nodes");
for r in &rows {
let key = format!("facett_component:{}@na", r.component);
assert!(
covered.contains(&key),
"driven component `{}` must be COVERED via the harness drive (key {key})",
r.component
);
}
}