dwarves-gui/tests/robot_dupes_reads_lens.rs
//! **ROBOT-UI: the 🧬 Dupes tab READS `lens_similar_code` over the wire — it does not
//! fold.**
//!
//! Since the lens chain landed, the duplicate answer is computed by a jera job and read
//! off the `lens_similar_code` warehouse table over the SAME thin `Mimir.SimilarCode`
//! RPC seam the Lenses pane's `SimilarCode` view uses. This drove the SHIPPED Dupes pane
//! (`dupes::dupes_pane` / `DupesPane::live`) through the REAL widget tree against an
//! in-process mock `Mimir` server (`testkit::spawn_mock_mimir` — a real tonic server on
//! an ephemeral port, NOT a stub), and asserts APPLIED output: the pane reads itself on
//! open, off the egui thread, and carries the server's answer verbatim.
//!
//! RED-first, the fold path is GONE: the mock's `similar_code` body carries
//! `__over_wire__: true` — a marker NO local `detect()` fold could ever synthesise — so
//! the pane showing it proves the read path. Before this refactor the tab folded locally
//! over `Warehouse.Scan`; it could not produce the sentinel and `folded_locally` was the
//! whole findings path, not an apply-only escape hatch.
use std::time::{Duration, Instant};
use dwarves_gui::dupes::{dupes_pane, DupesPane};
use facett_core::Facet;
use nornir_robotui::egui_kittest::Harness;
use nornir_robotui::{Observable, RobotSession};
use nornir_warehouse_embed::testkit::{spawn_mock_mimir, MockMimir};
use serde_json::json;
struct DupesApp(DupesPane);
impl Observable for DupesApp {
fn state_json(&self) -> serde_json::Value {
Facet::state_json(&self.0)
}
}
/// The lens reply is held this long, so the open frame must come back BEFORE it — proving
/// the read ran on a worker, not the egui thread.
const REPLY_DELAY: Duration = Duration::from_millis(400);
/// A `Mimir.SimilarCode` answer in nornir's Mímir v2 envelope: ranked clusters, the
/// feeds it read, `lens_meta.state` + an over-wire sentinel a LOCAL fold could never make.
fn lens_body() -> String {
json!({
"__over_wire__": true,
"kind": "similar_code",
"cluster_count": 2,
"cluster_count_total": 2,
"clusters_shown": 2,
"top_clusters": [
{ "canonical": "nornir#progress", "size": 2, "avg_cosine": 0.99, "structural": 0.9, "score": 1.98 },
{ "canonical": "korp#config", "size": 3, "avg_cosine": 0.94, "structural": 0.7, "score": 2.82 }
],
"evidence_note": "similar_code: 2 cluster(s). MISSING: `embeddings` carried no row for 1 repo.",
"feeds": [ { "table": "embeddings", "rows": 0, "root": "", "missing": true } ],
"lens_meta": { "state": "partial", "lens": "similar_code", "repo_scope": "", "gaps": [], "lower_bounds": [], "ms": 4 }
})
.to_string()
}
#[allow(unused_variables)]
fn matrix(check: &str, ok: bool, detail: &str) {
#[cfg(feature = "testmatrix")]
nornir_testmatrix::functional_status("dwarves-gui", check, ok, detail);
}
#[test]
fn the_dupes_tab_reads_similarcode_over_the_wire_and_never_folds() {
let srv = spawn_mock_mimir(MockMimir {
reply_delay: REPLY_DELAY,
similar_code: lens_body(),
..Default::default()
});
// The SHIPPED constructor — the pane a user actually gets. Its findings reader is the
// thin `Mimir.SimilarCode` RPC pointed at the in-proc server.
let pane = dupes_pane(&srv.endpoint, "", "nordisk");
let harness = Harness::builder()
.with_size(nornir_robotui::egui::Vec2::new(1200.0, 900.0))
.build_ui_state(
|ui, app: &mut DupesApp| Facet::ui(&mut app.0, ui),
DupesApp(pane),
);
let mut robot = RobotSession::new(harness, "dwarves-gui");
// THE OPEN — one frame, timed. The pane must have STARTED its read (no button) and
// given the frame back before the server answers.
let t0 = Instant::now();
robot.run(1);
let held = t0.elapsed();
assert_eq!(
robot.state_at("/pending"),
Some(json!(true)),
"the pane reads ITSELF on open — the chain folded the answer, so a button is friction (state {})",
robot.state_at("").map(|v| v.to_string()).unwrap_or_default()
);
assert_eq!(
robot.state_at("/scanned"),
Some(json!(false)),
"not read yet — the server holds its reply"
);
assert!(
held < REPLY_DELAY,
"the open frame took {held:?} — longer than one server reply ({REPLY_DELAY:?}); the read ran on the egui thread"
);
// ── THE BUTTONS. `Scan` AND `⟳` are both gone (`768983f`, 2026-08-22, the owner's
// call — quoted at `dupes.rs:676`): this is the Similar Code sub-view under
// Lenses, the jera chain folds off populate in the background, and the pane reads
// itself on open (asserted above). The ONE action left is the apply escape hatch,
// which the lens result genuinely cannot carry.
//
// This file asked for `⟳` for a day after the button was removed. The absence is
// asked of the tree (`node_id`, no mutation) and it sits NEXT TO the control that
// IS there — an empty AccessKit tree would satisfy the absence just as well, so
// the escape hatch below is what keeps it from being a hollow guard.
assert!(
robot.node_id("⟳").is_none(),
"the ⟳ re-read button is BACK in the AccessKit tree — the pane reads itself now and \
a button is friction (dupes.rs:676)"
);
assert!(
robot.click_label("⚒ Fold locally for apply").is_ok(),
"the apply escape hatch is present (the lens carries no plan, so apply folds \
locally) — and it is the NON-VACUITY control for the ⟳ absence above"
);
// Keep painting; the worker lands the reading.
let deadline = Instant::now() + Duration::from_secs(30);
while robot.state_at("/pending") == Some(json!(true)) && Instant::now() < deadline {
robot.run(1);
std::thread::sleep(Duration::from_millis(25));
}
// ── the reading LANDED, and it is the SERVER's answer, not a local fold ──────────
assert_eq!(
robot.state_at("/pending"),
Some(json!(false)),
"the read must land within 30 s"
);
assert_eq!(
robot.state_at("/scanned"),
Some(json!(true)),
"the reading landed"
);
// `__over_wire__` is the whole proof: no `detect()` fold can synthesise it.
assert_eq!(
robot.state_at("/reading/__over_wire__"),
Some(json!(true)),
"the findings are READ from lens_similar_code over the wire, NOT folded locally: {}",
robot
.state_at("/reading")
.map(|v| v.to_string())
.unwrap_or_default()
);
assert_eq!(
robot.state_at("/cluster_count_total"),
Some(json!(2)),
"the server's cluster count, verbatim"
);
assert_eq!(
robot.state_at("/reading/top_clusters/0/canonical"),
Some(json!("nornir#progress")),
"the ranked clusters cross the wire intact"
);
// The fold path is GONE from the findings: detect() was never called on open.
assert_eq!(
robot.state_at("/folded_locally"),
Some(json!(false)),
"the findings path never folds locally"
);
assert_eq!(
robot.state_at("/apply_plan_count"),
Some(json!(0)),
"no local fold ⇒ no plan (until the escape hatch)"
);
// PROVENANCE is derived off lens_meta.state and honest — what the answer rests on.
let prov = robot
.state_at("/provenance")
.and_then(|v| v.as_str().map(String::from))
.unwrap_or_default();
assert!(prov.contains("similar_code"), "{prov}");
assert!(
prov.contains("partial (lower bound)"),
"the header names the answer's own state: {prov}"
);
assert!(
prov.contains("feeds missing: embeddings"),
"…and the missing feed, never hidden: {prov}"
);
drop(srv);
matrix(
"dupes_tab_reads_similarcode_over_the_wire",
true,
"the shipped 🧬 Dupes pane (dupes_pane / DupesPane::live), driven through the real \
widget tree against an in-proc Mimir.SimilarCode server (testkit::spawn_mock_mimir \
with reply_delay), reads lens_similar_code on OPEN off the egui thread (pending=true, \
frame returns before the reply) and carries the server's answer verbatim — an \
__over_wire__ sentinel no local fold can make — with folded_locally=false and a \
lens_meta.state-derived provenance header (partial (lower bound) · feeds missing). \
The old local Warehouse.Scan fold is gone from the findings path.",
);
}