use super::choices;
use crate::fork::composer::Composer;
use crate::fork::render::render;
use crate::fork::{Attempt, Choices};
fn painted(composer: &mut Composer, choices: &Choices) -> String {
let mut copy = composer.clone();
crate::paint_probe::paint(|ui| {
copy = composer.clone();
render(ui, &mut copy, choices);
})
}
#[test]
fn the_composer_paints_every_fire_time_control() {
let mut c = Composer::seeded(&choices());
let text = painted(&mut c, &choices());
assert!(text.contains("Fork from here"), "{text}");
assert!(text.contains("here") && text.contains("strict"), "{text}");
assert!(
text.contains("worker — anthropic/claude-sonnet-5"),
"the model is visible at the point of choice:\n{text}"
);
assert!(text.contains("scribe — anthropic/opus"), "{text}");
assert!(
text.contains("bash") && text.contains("read_file"),
"{text}"
);
assert!(text.contains("×1"), "one candidate, said outright:\n{text}");
assert!(text.contains("Fire"), "{text}");
}
#[test]
fn a_fan_paints_one_block_per_candidate() {
let mut c = Composer::seeded(&choices());
c.resize(3);
let text = painted(&mut c, &choices());
assert!(text.contains("×3"), "{text}");
for n in ["#1", "#2", "#3"] {
assert!(text.contains(n), "{n} is missing:\n{text}");
}
}
#[test]
fn the_times_buttons_step_the_cohort_and_floor_at_one() {
let mut c = Composer::seeded(&choices());
click(&mut c, "+");
assert_eq!(c.attempts.len(), 2);
click(&mut c, "−");
assert_eq!(c.attempts.len(), 1);
click(&mut c, "−");
assert_eq!(c.attempts.len(), 1);
}
#[test]
fn picking_a_fork_point_carries_the_policy_with_it() {
let mut c = Composer::seeded(&choices());
c.attempts[0].role = "scribe".to_owned();
click(&mut c, "strict");
assert_eq!(c.attempts[0].from, "config/strict");
assert_eq!(c.attempts[0].role, "worker", "scribe is not on that config");
}
#[test]
fn picking_a_role_and_a_skill_edits_that_candidate() {
let mut c = Composer::seeded(&choices());
click(&mut c, "scribe — anthropic/opus");
assert_eq!(c.attempts[0].role, "scribe");
click(&mut c, "bash");
assert_eq!(c.attempts[0].skills, vec!["bash".to_owned()]);
click(&mut c, "bash");
assert!(c.attempts[0].skills.is_empty());
}
#[test]
fn fire_is_unreachable_until_the_composer_is_ready() {
let mut c = Composer::seeded(&choices());
assert!(!click(&mut c, "Fire"), "an empty goal cannot fire");
c.goal = "try it the other way".to_owned();
assert!(click(&mut c, "Fire"));
}
#[test]
fn a_candidate_on_an_unoffered_ref_offers_no_role() {
let mut c = Composer::seeded(&choices());
c.attempts[0] = Attempt {
from: "config/gone".to_owned(),
role: "worker".to_owned(),
skills: Vec::new(),
};
let text = painted(&mut c, &choices());
assert!(!text.contains(" — anthropic/"), "no model to name:\n{text}");
}
#[test]
fn moving_to_a_ref_that_declares_no_role_leaves_the_candidate_unfireable() {
let mut offered = choices();
offered.points.push(crate::fork::ForkPoint {
label: "bare".to_owned(),
refspec: "config/bare".to_owned(),
roles: Vec::new(),
});
let mut c = Composer::seeded(&offered);
c.goal = "try it the other way".to_owned();
assert!(c.ready());
click_at(&mut c, "bare", &offered);
assert_eq!(c.attempts[0].from, "config/bare");
assert_eq!(c.attempts[0].role, "", "no role to land on");
assert!(!c.ready());
}
fn click(composer: &mut Composer, label: &str) -> bool {
click_at(composer, label, &choices())
}
fn click_at(composer: &mut Composer, label: &str, choices: &Choices) -> bool {
let choices = choices.clone();
let ctx = egui::Context::default();
let run = |input: egui::RawInput, composer: &mut Composer| {
let mut fired = false;
let _ = ctx.run(input, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
fired = render(ui, composer, &choices);
});
});
fired
};
let screen = crate::paint_probe::screen;
let _ = run(screen(), composer);
let _ = run(screen(), composer);
let mut probe = composer.clone();
let painted = crate::paint_probe::painted_settled(1024.0, 4096.0, |ui| {
probe = composer.clone();
render(ui, &mut probe, &choices);
});
let pos = painted
.iter()
.find(|(text, _)| text == label)
.map(|(_, rect)| rect.center())
.expect("the label is on screen");
let button = |pressed| egui::Event::PointerButton {
pos,
button: egui::PointerButton::Primary,
pressed,
modifiers: egui::Modifiers::default(),
};
run(
egui::RawInput {
events: vec![egui::Event::PointerMoved(pos), button(true), button(false)],
..screen()
},
composer,
)
}