use crate::science::compose::Intent;
use crate::science::render::{Seat, group};
use crate::science::tests::candidate;
use crate::science::{Attempt, Outcome};
fn painted(rows: &[Attempt], seat: &mut Seat) -> String {
crate::paint_probe::paint(|ui| {
group(ui, rows, seat);
})
}
#[test]
fn no_candidates_paints_nothing_at_all() {
let mut seat = Seat::default();
assert_eq!(painted(&[], &mut seat), "");
let mut claim = candidate("at-1", None);
claim.diff.handle = None;
assert_eq!(painted(&[claim], &mut seat), "");
}
#[test]
fn the_card_states_the_cohort_and_compares_two_by_itself() {
let rows = vec![
candidate("at-1", Some("shared\nalpha")),
candidate("at-2", Some("shared\nbeta")),
];
let mut seat = Seat::default();
let text = painted(&rows, &mut seat);
assert!(text.contains("fan · 2 candidates on bl-1"), "{text}");
assert!(text.contains("base basebas"), "{text}");
assert!(text.contains("Judge"), "{text}");
assert!(text.contains("Synthesize"), "{text}");
assert!(text.contains("at-1"), "{text}");
assert!(text.contains("pending"), "{text}");
assert!(text.contains("3 steps · 1m01s wall · 77 tokens"), "{text}");
assert!(text.contains("+4 −1 across 1 files"), "{text}");
assert!(text.contains("shared\nalpha"), "{text}");
assert!(text.contains("Deliver"), "{text}");
assert!(text.contains("Retire"), "{text}");
assert!(text.contains("response diff · − at-1 · + at-2"), "{text}");
assert!(text.contains(" shared"), "{text}");
assert!(text.contains("− alpha"), "{text}");
assert!(text.contains("+ beta"), "{text}");
}
#[test]
fn every_outcome_and_absence_is_said_in_words() {
let mut delivered = candidate("at-1", Some("won"));
delivered.outcome = Outcome::Accepted {
commit: "cafecafe1234beef".to_owned(),
};
let mut stale = candidate("at-2", Some("lost"));
stale.outcome = Outcome::Rejected {
by: Some("at-1".to_owned()),
};
stale.wall_secs = 3905;
let mut discarded = candidate("at-3", None);
discarded.outcome = Outcome::Rejected { by: None };
discarded.conversation = None;
let mut reworked = candidate("at-4", None);
reworked.outcome = Outcome::Reworked;
reworked.wall_secs = 5;
let mut seat = Seat::default();
let text = painted(&[delivered, stale, discarded, reworked], &mut seat);
assert!(text.contains("delivered cafecaf"), "{text}");
assert!(text.contains("stale — at-1 delivered"), "{text}");
assert!(text.contains("discarded"), "{text}");
assert!(text.contains("reworked"), "{text}");
assert!(text.contains("no conversation bound yet"), "{text}");
assert!(text.contains("nothing said yet"), "{text}");
assert!(text.contains("1h05m wall"), "{text}");
assert!(text.contains("5s wall"), "{text}");
assert!(!text.contains("response diff"), "{text}");
assert!(!text.contains("record compacted"), "{text}");
}
#[test]
fn a_compacted_record_is_stated_beside_its_figures() {
let mut squashed = candidate("at-1", Some("done"));
squashed.compacted = 12;
let mut seat = Seat::default();
let text = painted(&[squashed], &mut seat);
assert!(
text.contains("record compacted — 12 entries gone"),
"{text}"
);
}
#[test]
fn clipping_mixed_bases_and_churn_absences_are_honest() {
let mut long = candidate("at-1", Some(&"x".repeat(400)));
long.base = None;
if let crate::workdiff::Change::Diff { files, .. } = &mut long.diff.change {
files.push(crate::workdiff::FileChurn {
path: "logo.png".to_owned(),
churn: crate::workdiff::Churn::Binary,
});
}
let mut absent = candidate("at-2", None);
absent.diff.change = crate::workdiff::Change::Absent {
target: "work/bl-1".to_owned(),
source: "attempt/at-2".to_owned(),
missing: vec!["attempt/at-2".to_owned()],
};
let mut unreadable = candidate("at-3", None);
unreadable.diff.change = crate::workdiff::Change::Unreadable;
let mut seat = Seat::default();
let text = painted(&[long, absent, unreadable], &mut seat);
assert!(!text.contains("base basebas"), "{text}");
assert!(text.contains("+4 −1 across 2 files"), "{text}");
assert!(text.contains(&format!("{}…", "x".repeat(280))), "{text}");
assert!(text.contains("no attempt/at-2 yet"), "{text}");
assert!(text.contains("project unreadable"), "{text}");
}
#[test]
fn picks_compare_and_a_third_pick_replaces_the_elder() {
let rows = vec![
candidate("at-1", Some(&"l\n".repeat(500))),
candidate("at-2", Some("r")),
candidate("at-3", Some("s")),
];
let mut seat = Seat {
compare: vec!["at-1".to_owned(), "at-2".to_owned()],
intent: None,
};
let text = painted(&rows, &mut seat);
assert!(text.contains("response diff · − at-1 · + at-2"), "{text}");
let tall = crate::paint_probe::painted_settled(1600.0, 20000.0, |ui| {
group(
ui,
rows.as_slice(),
&mut Seat {
compare: vec!["at-1".to_owned(), "at-2".to_owned()],
intent: None,
},
);
});
assert!(
tall.iter()
.any(|(text, _)| text.contains("responses longer than this comparison reads")),
"no truncation note in the tall frame"
);
click(&rows, &mut seat, "compare", 2);
assert_eq!(seat.compare, vec!["at-2".to_owned(), "at-3".to_owned()]);
click(&rows, &mut seat, "compare", 1);
assert_eq!(seat.compare, vec!["at-3".to_owned()]);
let text = painted(&rows, &mut seat);
assert!(!text.contains("response diff"), "{text}");
}
#[test]
fn every_affordance_answers_its_intent() {
let rows = vec![candidate("at-1", None), candidate("at-2", None)];
let mut seat = Seat::default();
click(&rows, &mut seat, "Judge", 0);
assert_eq!(seat.intent, Some(Intent::Judge));
click(&rows, &mut seat, "Synthesize", 0);
assert_eq!(seat.intent, Some(Intent::Synthesize));
click(&rows, &mut seat, "Deliver", 1);
assert_eq!(
seat.intent,
Some(Intent::Deliver {
handle: "at-2".to_owned()
})
);
click(&rows, &mut seat, "Retire", 0);
assert_eq!(
seat.intent,
Some(Intent::Retire {
handle: "at-1".to_owned()
})
);
}
fn click(rows: &[Attempt], seat: &mut Seat, label: &str, nth: usize) {
let painted = crate::paint_probe::painted_settled(1600.0, 4096.0, |ui| {
group(
ui,
rows,
&mut Seat {
compare: seat.compare.clone(),
intent: None,
},
);
});
let hit = painted.iter().filter(|(text, _)| text == label).nth(nth);
assert!(hit.is_some(), "{label} #{nth} is on screen");
let pos = hit.map(|(_, rect)| rect.center()).unwrap_or_default();
let ctx = egui::Context::default();
let button = |pressed| egui::Event::PointerButton {
pos,
button: egui::PointerButton::Primary,
pressed,
modifiers: egui::Modifiers::default(),
};
for events in [vec![], vec![button(true)], vec![button(false)], vec![]] {
let input = egui::RawInput {
events,
..crate::paint_probe::screen_sized(1600.0, 4096.0)
};
let _ = ctx.run(input, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
group(ui, rows, seat);
});
});
}
}