facett-cfd/tests/matrix.rs
//! **The functional matrix cell for facett-cfd** — the pane emitted NO testmatrix
//! row of either aspect before this file (see
//! `.nornir/docs/test-matrix-inventory-history.md`, "~10 panes emit no cell").
//!
//! ONE call through the shared generic-`Facet` probe (L5) — no bespoke harness.
use facett_cfd::Cfd;
#[test]
fn cfd_probe_emits_render_and_input_cells() {
let mut view = Cfd::local();
let script = [
r#"{"snapshot":{"date":"2026-06-07","counts":{"todo":1,"doing":2,"done":9}}}"#,
r#""clear""#,
];
let probe = facett_core::testmatrix::probe_and_emit("facett-cfd", &mut view, &script);
assert!(probe.drew(), "the stacked area must tessellate to vertices");
assert!(probe.cardinality() > 0, "state_json reports the bands/series");
assert!(probe.responded(), "update_json must drive state — a dead seam is a regression");
// EXACT contract: 3 snapshots, the y-scale is the LARGEST daily total (11 on
// 2026-06-05: 3+3+4 = 10, vs 8+1+0 = 9 and 5+2+2 = 9 → 10), and the range
// spans first→last date.
assert_eq!(probe.initial_state["snapshots"], 3);
assert_eq!(probe.initial_state["max_total"], 10);
assert_eq!(probe.initial_state["range"], serde_json::json!(["2026-06-01", "2026-06-05"]));
assert_eq!(probe.initial_state["latest"]["total"], 10);
// The new day is heavier (1+2+9 = 12) → it becomes both the latest AND the
// new y-scale. A loose "count grew" oracle would miss the rescale.
assert_eq!(probe.steps[0].state["snapshots"], 4);
assert_eq!(probe.steps[0].state["max_total"], 12);
assert_eq!(probe.steps[0].state["latest"]["date"], "2026-06-07");
assert_eq!(probe.steps[1].state["snapshots"], 0, "clear empties the series");
}
/// RED-when-broken: an out-of-order snapshot must be re-SORTED into the series,
/// not appended — a CFD that plots dates backwards draws a self-intersecting
/// area and its `range` would report a reversed interval.
#[test]
fn out_of_order_snapshots_are_sorted_into_place() {
use std::collections::BTreeMap;
let mut c = Cfd::local();
let mut counts = BTreeMap::new();
counts.insert("todo".to_string(), 9usize);
c.push_snapshot(facett_cfd::Snapshot {
date: chrono::NaiveDate::from_ymd_opt(2026, 6, 2).unwrap(),
counts,
});
let st = c.state_json();
assert_eq!(st["snapshots"], 4);
assert_eq!(st["range"], serde_json::json!(["2026-06-01", "2026-06-05"]), "the tail is still the latest date");
assert_eq!(st["latest"]["date"], "2026-06-05", "the inserted day did not become the tail");
}