mod focus;
use super::{HERE, Pane, moved};
use crate::paint_probe::frame::{Window, press};
use crate::test_support::window::{conv, own, seated, wall};
use crate::ui::{Channel, Chunk, Model, Notice, convs, roster};
fn stocked() -> Model {
Model {
roster: vec![
own(),
Chunk {
channel: Channel {
name: "elsewhere".to_owned(),
named_there: Some("theirs".to_owned()),
dials: None,
},
walls: vec![wall("theirs"), wall("not-ours")],
..Chunk::default()
},
],
convs: vec![conv("a", "one"), conv("b", "two")],
..seated()
}
}
fn typed(model: &mut Model, keys: &[egui::Key]) -> String {
let window = Window::new();
let mut painted = String::new();
for key in keys {
painted = crate::paint_probe::text_of(&window.frame(vec![press(*key)], |ctx| {
crate::ui::render(ctx, model);
}));
}
painted
}
#[test]
fn the_pane_the_arrows_belong_to_is_marked_on_the_glass() {
let mut model = stocked();
let painted = typed(&mut model, &[egui::Key::ArrowRight]);
assert!(
painted
.lines()
.any(|line| line == format!("{HERE} {}", convs::HEADING)),
"{painted}"
);
assert!(
painted.lines().any(|line| line == roster::HEADING),
"the pane that does not hold the arrows wears no mark:\n{painted}"
);
let painted = typed(&mut model, &[egui::Key::ArrowLeft]);
assert!(
painted
.lines()
.any(|line| line == format!("{HERE} {}", roster::HEADING)),
"{painted}"
);
}
#[test]
fn the_arrows_walk_the_engine_rows_and_the_open_engine_s_walls() {
let mut model = Model {
aim: None,
..stocked()
};
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(
model.standing.as_deref(),
Some("(this box's own engine)"),
"a list nobody has entered opens at its first row, which is an engine"
);
assert_eq!(model.aim, None, "and standing there selects nothing");
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(
model.aim.as_ref().map(|aim| aim.address.clone()),
Some("home".to_owned()),
"the open engine's wall is the next stop, and landing on it aims it"
);
assert_eq!(model.standing, None, "an aim is where the cursor is");
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(
model.standing.as_deref(),
Some("elsewhere"),
"and the closed engine's own row is next, never its walls"
);
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(
model.standing.as_deref(),
Some("elsewhere"),
"the end saturates rather than wrapping"
);
typed(&mut model, &[egui::Key::ArrowUp]);
assert_eq!(
model.aim.as_ref().map(|aim| aim.address.clone()),
Some("home".to_owned())
);
}
#[test]
fn enter_on_the_row_the_walk_stands_on_opens_that_engine() {
let mut model = Model {
aim: None,
..stocked()
};
typed(
&mut model,
&[
egui::Key::ArrowDown,
egui::Key::ArrowDown,
egui::Key::ArrowDown,
egui::Key::Enter,
],
);
assert_eq!(model.engines.open.as_deref(), Some("elsewhere"));
assert_eq!(
model.aim.as_ref().map(|aim| aim.address.clone()),
Some("elsewhere".to_owned()),
"opening aims the engine's first addressable wall"
);
}
#[test]
fn the_arrows_walk_the_conversation_list_and_the_walk_is_the_selection() {
let mut model = Model {
conversation: None,
..stocked()
};
typed(&mut model, &[egui::Key::ArrowRight, egui::Key::ArrowDown]);
assert_eq!(model.conversation.as_deref(), Some("a"));
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(model.conversation.as_deref(), Some("b"));
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(model.conversation.as_deref(), Some("b"));
}
#[test]
fn escape_puts_the_notice_down() {
let mut model = Model {
notice: Some(Notice::Refused("unknown workspace".to_owned())),
..stocked()
};
let painted = typed(&mut model, &[egui::Key::Escape]);
assert_eq!(model.notice, None);
assert!(
!painted.contains("the engine refused"),
"the bar is off the glass:\n{painted}"
);
}
#[test]
fn nothing_is_bound_while_a_box_is_taking_text() {
const STOPS: usize = 64;
let mut model = stocked();
let window = Window::new();
let mut body = |ctx: &egui::Context| crate::ui::render(ctx, &mut model);
window.frame(Vec::new(), &mut body);
let mut wanted = false;
for _ in 0..STOPS {
window.frame(vec![press(egui::Key::Tab)], &mut body);
wanted = window.focused() == Some(egui::Id::new(super::BOX_ID));
if wanted {
break;
}
}
assert!(wanted, "the composer's box never took the keyboard");
window.frame(vec![press(egui::Key::ArrowDown)], &mut body);
window.frame(Vec::new(), &mut body);
assert_eq!(
model.conversation.as_deref(),
seated().conversation.as_deref(),
"the arrow went into the draft, not into a list"
);
}
#[test]
fn a_cursor_saturates_and_an_empty_list_has_nowhere_to_go() {
assert_eq!(moved(0, None, 1), None);
assert_eq!(moved(3, None, -1), Some(0), "an unentered list opens at 0");
assert_eq!(moved(3, Some(0), -1), Some(0));
assert_eq!(moved(3, Some(2), 1), Some(2));
assert_eq!(moved(3, Some(1), 1), Some(2));
}
#[test]
fn a_fresh_window_opens_with_the_roster_holding_the_arrows() {
assert_eq!(Model::default().focus, Pane::Roster);
assert_eq!(
roster::track(&Model::default()),
Vec::new(),
"a box that has been asked nothing offers no row to walk"
);
}
#[test]
fn the_arrows_walk_the_started_conversation_s_row_like_any_other() {
let mut model = Model {
conversation: Some("brisk-otter".to_owned()),
start: Some(crate::ui::model::Start {
address: "home".to_owned(),
goal: "port it".to_owned(),
phase: crate::ui::model::Phase::Started("brisk-otter".to_owned()),
spread: None,
}),
..stocked()
};
let painted = typed(&mut model, &[egui::Key::ArrowRight]);
assert!(painted.contains("brisk-otter"), "{painted}");
typed(&mut model, &[egui::Key::ArrowDown]);
assert_eq!(
model.conversation.as_deref(),
Some("a"),
"one step down out of the pending row and into the list"
);
}
#[test]
fn the_two_parameter_boxes_stand_the_arrows_down_as_the_draft_does() {
for (fill, id) in [
(crate::ui::Fill::Reason, super::REASON_ID),
(crate::ui::Fill::Arming, super::ARM_ID),
] {
let mut model = stocked();
model.focus = Pane::Conversations;
model.fill_in("a", fill);
let window = Window::new();
let mut body = |ctx: &egui::Context| crate::ui::render(ctx, &mut model);
window.frame(Vec::new(), &mut body);
assert_eq!(
window.focused(),
Some(egui::Id::new(id)),
"the box took the keyboard"
);
window.frame(vec![press(egui::Key::ArrowDown)], &mut body);
window.frame(Vec::new(), &mut body);
assert_eq!(
model.conversation.as_deref(),
Some("a"),
"the arrow went into the box, not into the list"
);
}
}