mod shape;
use super::{goal, render};
use crate::paint_probe::frame::{Window, locate_in, press};
use crate::test_support::window::{pane, seated};
use crate::ui::model::{Phase, Start};
use crate::ui::theme::glyph;
use crate::ui::{Aim, Model};
use serde_json::json;
fn unselected() -> Model {
Model {
conversation: None,
..seated()
}
}
fn aimed() -> Aim {
unselected().aim.expect("the fixture is aimed")
}
#[test]
fn a_wall_with_nothing_selected_offers_a_start() {
let mut model = unselected();
let painted = pane(|ui| render(ui, &mut model, &aimed()));
for expected in [goal("home", false).as_str(), glyph::PROMPT] {
assert!(
painted.lines().any(|line| line.starts_with(expected)),
"{expected:?}:\n{painted}"
);
}
}
#[test]
fn starting_composes_the_staging_act_and_posts_nothing() {
let mut model = unselected();
model.draft = "do the thing".to_owned();
let window = Window::new();
window.frame(Vec::new(), |ctx| {
egui::CentralPanel::default().show(ctx, |ui| render(ui, &mut model, &aimed()));
});
window.focus(egui::Id::new(crate::ui::keys::BOX_ID));
window.frame(vec![press(egui::Key::Enter)], |ctx| {
egui::CentralPanel::default().show(ctx, |ui| render(ui, &mut model, &aimed()));
});
assert_eq!(
model.outbox,
vec![crate::ui::Posted::act(
json!({"op": "prepare", "workspace": "home", "payload": {"rung": "bare"}})
)]
);
assert_eq!(
model.start.as_ref().map(|start| start.goal.clone()),
Some("do the thing".to_owned())
);
}
#[test]
fn enter_begins_what_was_typed() {
let mut model = unselected();
let window = Window::new();
let mut body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| render(ui, &mut model, &aimed()));
};
let at = crate::paint_probe::frame::led_in(&window, &goal("home", false), &mut body)
.expect("the box");
crate::paint_probe::frame::click(&window, at, &mut body);
window.frame(
vec![egui::Event::Text("do the thing".to_owned())],
&mut body,
);
window.frame(vec![press(egui::Key::Enter)], &mut body);
window.frame(Vec::new(), &mut body);
assert_eq!(model.outbox.len(), 1, "{:?}", model.outbox);
assert_eq!(model.outbox[0].envelope["op"], json!("prepare"));
}
#[test]
fn enter_on_a_slash_line_begins_nothing() {
let mut model = unselected();
model.draft = "/plan".to_owned();
let window = Window::new();
let mut body = |ctx: &egui::Context| {
egui::CentralPanel::default().show(ctx, |ui| render(ui, &mut model, &aimed()));
};
let at = locate_in(&window, "/plan", &mut body).expect("the box");
crate::paint_probe::frame::click(&window, at, &mut body);
window.frame(vec![press(egui::Key::Enter)], &mut body);
assert!(model.outbox.is_empty(), "{:?}", model.outbox);
assert_eq!(model.start, None);
}
#[test]
fn a_start_in_flight_paints_its_sentence_and_offers_no_second_start() {
for phase in [Phase::Staging, Phase::Firing] {
let mut model = Model {
start: Some(Start {
address: "home".to_owned(),
goal: "do the thing".to_owned(),
phase,
spread: None,
}),
..unselected()
};
let painted = pane(|ui| render(ui, &mut model, &aimed()));
assert!(
painted.contains("starting in home: do the thing…"),
"{painted}"
);
assert!(
!painted.lines().any(|line| line == glyph::PROMPT),
"no control to press:\n{painted}"
);
}
}
#[test]
fn a_finished_start_paints_its_name_over_the_box_that_begins_the_next() {
let mut model = Model {
start: Some(Start {
address: "home".to_owned(),
goal: "do the thing".to_owned(),
phase: Phase::Started("brisk-otter".to_owned()),
spread: None,
}),
..unselected()
};
let painted = pane(|ui| render(ui, &mut model, &aimed()));
assert!(
painted.contains("started «brisk-otter» in home"),
"{painted}"
);
assert!(
painted.lines().any(|line| line == glyph::PROMPT),
"{painted}"
);
}
#[test]
fn a_refused_start_paints_its_sentence_over_the_box_that_carries_the_goal_back() {
let mut model = Model {
start: Some(Start {
address: "home".to_owned(),
goal: "do the thing".to_owned(),
phase: Phase::Refused("sign in first: no provider holds a credential".to_owned()),
spread: None,
}),
draft: "do the thing".to_owned(),
..unselected()
};
let painted = pane(|ui| render(ui, &mut model, &aimed()));
assert!(
painted.contains("not started in home: sign in first: no provider holds a credential"),
"{painted}"
);
assert!(
painted.lines().any(|line| line == glyph::PROMPT),
"{painted}"
);
assert!(
painted.contains("do the thing"),
"the goal is in the box:\n{painted}"
);
}
#[test]
fn the_hint_names_the_wall_and_the_plan() {
let mut model = unselected();
let painted = pane(|ui| render(ui, &mut model, &aimed()));
assert!(painted.contains("on home is for"), "{painted}");
model.plan = true;
let planned = pane(|ui| render(ui, &mut model, &aimed()));
assert!(planned.contains(&goal("home", true)), "{planned}");
}