facett-demo/tests/pink_proof.rs
//! **The error CODES paint on screen** — headless render of the Errors tab → PNG, then a
//! pixel census for the code chips.
//!
//! # Why the expected colour is ASKED FOR, not written down
//!
//! `facett_core::errcode::code_color()` is the shipped decision and it is **profile
//! dependent by design**: the clear `PINK` in a debug build, the same hue at alpha 90 in a
//! release one, so "a release build does not shout the developer-facing code but a
//! reviewer can still spot it" (error-codes design, decision (2)). This file used to
//! hard-code `rgb(255, 64, 180)` with a ±40/±60/±50 tolerance — i.e. it restated one half
//! of that rule inside the test — so it was asserting a DEBUG-only fact and could only
//! ever pass in debug. MEASURED 2026-08-31: `cargo test --release --workspace` failed here
//! with `PINK_PIXELS=0` while the chips were painted exactly as the design says.
//!
//! That is the same shape as the devid failures in the same run, and it is the trap
//! `devid_scene_slots.rs` records in its own header: *a test that re-implements the rule
//! and then compares its copy against its own expectation is not testing the shipped
//! decision.* So the expectation now comes from `code_color()` — one copy of the rule —
//! composited the way egui composites it, and the census is a real positive proof in
//! **both** profiles.
//!
//! ```bash
//! cargo test -p facett-demo --test pink_proof
//! cargo test --release -p facett-demo --test pink_proof # ← must be green too
//! ```
use egui_kittest::Harness;
use facett_demo::DemoState;
/// How far a pixel may sit from the expected chip colour and still count, **at full
/// opacity**. Unchanged from the debug-only version this replaces, so the debug census is
/// the same measurement it always was.
const TOL_OPAQUE: [i32; 3] = [40, 60, 50];
/// The tolerance for a chip drawn at alpha `a`, scaled with it.
///
/// This is the line between a widened census and a hollow one, and it was MEASURED, not
/// reasoned: with the flat `TOL_OPAQUE` box kept around the release composite, pointing
/// this test at a tab with **no error codes on it at all** still counted 7 477 "chip"
/// pixels and PASSED, while debug correctly reported 0 and failed. A subdued chip sits
/// closer to the ground, so the box that was tight around clear pink swallows ordinary
/// chrome around a dim mauve. The tolerance therefore shrinks with the chip's own alpha —
/// the same fraction of a smaller distance.
fn tol(alpha: u8) -> [i32; 3] {
TOL_OPAQUE.map(|t| (t * alpha as i32 / 255).max(4))
}
/// The colour the chip's glyphs land as, once egui has composited them.
///
/// `Color32` stores **premultiplied** channels, so `from_rgba_unmultiplied(r, g, b, a)`
/// already holds `r·a/255`; what reaches the framebuffer is those channels plus the ground
/// showing through the remaining `255 − a`. In debug `code_color()` is opaque and this is
/// the identity — the expectation is literally `PINK`, exactly as before.
fn composited(want: egui::Color32, ground: [u8; 3]) -> [i32; 3] {
let through = 255 - want.a() as u32;
[
(want.r() as u32 + ground[0] as u32 * through / 255) as i32,
(want.g() as u32 + ground[1] as u32 * through / 255) as i32,
(want.b() as u32 + ground[2] as u32 * through / 255) as i32,
]
}
fn near(px: &image::Rgba<u8>, want: [i32; 3], tol: [i32; 3]) -> bool {
let (r, g, b) = (px.0[0] as i32, px.0[1] as i32, px.0[2] as i32);
(r - want[0]).abs() < tol[0] && (g - want[1]).abs() < tol[1] && (b - want[2]).abs() < tol[2]
}
/// The image's most common colour — the pane's own ground, which is what the chip is
/// composited over. Taken from the render rather than assumed, so a palette change moves
/// the expectation with it instead of quietly emptying the census.
fn dominant_ground(img: &image::RgbaImage) -> [u8; 3] {
let mut counts: std::collections::HashMap<[u8; 3], u32> = std::collections::HashMap::new();
for p in img.pixels() {
*counts.entry([p.0[0], p.0[1], p.0[2]]).or_insert(0) += 1;
}
counts.into_iter().max_by_key(|(_, n)| *n).map(|(c, _)| c).unwrap_or([0, 0, 0])
}
#[test]
fn shoot_errors_tab() {
let mut demo = DemoState::new();
assert!(demo.deck.set_active_by_title("Errors"));
let mut h = Harness::builder()
.with_size(egui::vec2(1400.0, 900.0))
.build_ui(move |ui| {
demo.deck.ui(ui);
});
h.run_steps(4);
let img = h.render().expect("rendered");
// The proof artifact goes to the workspace target dir (like robot_demo's matrix
// rows) — a stable, always-existing location. A hardcoded per-session scratchpad
// path sat here and broke the whole test with NotFound once that session's dir
// was gone, which had nothing to do with the pink codes this test proves.
let target_dir = std::env::var_os("CARGO_TARGET_DIR")
.map(std::path::PathBuf::from)
.unwrap_or_else(|| {
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..").join("target")
});
std::fs::create_dir_all(&target_dir).ok();
img.save(target_dir.join("errors_headless.png")).unwrap();
// ── The expectation, from the SHIPPED decision ───────────────────────────────
let want = facett_core::errcode::code_color();
let ground = dominant_ground(&img);
let expect = composited(want, ground);
let tol = tol(want.a());
let pink = img.pixels().filter(|p| near(p, expect, tol)).count();
eprintln!(
"PINK_PIXELS={pink} (expect {expect:?} = code_color {want:?} over ground {ground:?}, \
tol {tol:?}, debug_assertions={})",
cfg!(debug_assertions)
);
assert!(
pink > 100,
"the error codes did not paint: only {pink} px near {expect:?}, the composite of \
the SHIPPED `errcode::code_color()` ({want:?}, alpha {}) over this render's own \
ground {ground:?}",
want.a()
);
// ── Anti-hollow: the census must not be satisfied by the background ──────────
// In release the chip is subdued, so its composite sits much closer to the ground than
// the clear pink does — and a tolerance that swallowed the ground would report tens of
// thousands of "chip" pixels and pass over an empty tab. This is the check that keeps
// the widened expectation honest.
let ground_px = image::Rgba([ground[0], ground[1], ground[2], 255]);
assert!(
!near(&ground_px, expect, tol),
"the expected chip colour {expect:?} is within tolerance of the pane's own ground \
{ground:?} — this census would count the background as error codes and could \
never go red (code_color {want:?}, alpha {})",
want.a()
);
}