use super::fixture::{MINT_SEED, MINTED, MINTED_FIRST, fake_lernie, seed_world, world};
use super::screen::{Screen, press};
use crate::start::Prepared;
use tempfile::tempdir;
fn predicted(screen: &str) -> String {
screen
.lines()
.find(|line| line.starts_with("will be named "))
.expect("the composer previews the name its Enter would mint")
.to_owned()
}
fn fire(screen: &Screen, world: &mut super::fixture::World, goal: &str) {
screen.frame(world, vec![egui::Event::Text(goal.to_owned())]);
screen.frame(world, vec![press(egui::Key::Enter, egui::Modifiers::NONE)]);
world.converge();
}
fn fresh(screen: &Screen, world: &mut super::fixture::World) {
screen.release(world);
screen.frame(world, vec![press(egui::Key::N, egui::Modifiers::NONE)]);
}
#[test]
fn consecutive_fires_each_predict_and_spend_a_seed_of_their_own() {
let bin = tempdir().unwrap();
let mut world = world();
seed_world(&world);
let screen = Screen::with_lernie(fake_lernie(bin.path()));
assert!(screen.idle(&mut world), "the cursor starts in the composer");
let first = predicted(&screen.text(&mut world));
let seed = world.state.start.mint_seed;
assert_eq!(seed, MINT_SEED, "the world starts from the pinned seed");
assert_eq!(
first,
format!("will be named {MINTED_FIRST}"),
"and the pinned seed's one draw is the word the suite may name"
);
fire(&screen, &mut world, "open the gate");
let respun = world.state.start.mint_seed;
assert_ne!(
respun, seed,
"a landed fire retires the seed it spent (bl-28ba)"
);
fresh(&screen, &mut world);
assert_eq!(
predicted(&screen.text(&mut world)),
format!("will be named {}", MINTED[1]),
"so the next agent is predicted a fresh name, not the walk's next slot"
);
fire(&screen, &mut world, "shut the gate");
assert_ne!(
world.state.start.mint_seed, respun,
"and every fire after it retires its own"
);
fresh(&screen, &mut world);
assert_eq!(
predicted(&screen.text(&mut world)),
format!("will be named {}", MINTED[2]),
"three fires, three named-in-advance names"
);
assert_eq!(
MINTED
.iter()
.collect::<std::collections::HashSet<_>>()
.len(),
MINTED.len(),
"three fires, three unrelated names"
);
}
#[test]
fn a_launch_that_never_left_the_ground_keeps_its_prediction() {
let mut world = world();
let screen = Screen::new();
let ws = world.ws.clone();
world.state.start.pending = Some(Prepared {
workspace: crate::naming::leaf(&ws),
binding: None,
goal: "fix the gate".to_owned(),
origin: crate::opslog::Origin::Balls,
});
let before = predicted(&screen.text(&mut world));
let seed = world.state.start.mint_seed;
super::super::start_pane::send_pending(&mut world.model, &mut world.state);
let after = predicted(&screen.text(&mut world));
assert_eq!(
world.state.start.mint_seed, seed,
"a failed launch spends no seed — nothing took the name it predicted"
);
assert!(
world.state.start.pending.is_some(),
"the goal stands, so the prediction over it must too"
);
assert_eq!(
after, before,
"and the retry is offered the same name the first attempt promised"
);
}
#[test]
fn the_ball_rungs_send_retires_the_seed_the_same_way() {
let bin = tempdir().unwrap();
let mut world = world();
seed_world(&world);
let lernie = fake_lernie(bin.path());
let ws = world.ws.clone();
world.state.start.pending = Some(Prepared {
workspace: crate::naming::leaf(&ws),
binding: None,
goal: "fix the gate".to_owned(),
origin: crate::opslog::Origin::Balls,
});
let seed = world.state.start.mint_seed;
let screen = Screen::with_lernie(lernie);
screen.idle(&mut world);
super::super::start_pane::send_pending(&mut world.model, &mut world.state);
screen.idle(&mut world);
assert_ne!(
world.state.start.mint_seed, seed,
"a landed ball-rung fire retires its seed too"
);
assert!(
world.state.start.pending.is_none(),
"and the draft it fired is spent with it"
);
}