mod subtree;
mod threading;
mod width;
use super::{NO_CONVERSATIONS, NOT_ANSWERED, age, headline};
use crate::paint_probe::frame::Window;
use crate::reply::convs::{AgentState, Tone};
use crate::test_support::window::{click, conv, pane, seated, seen};
use crate::ui::Model;
pub(super) fn beneath(ui: &mut egui::Ui, model: &mut Model) {
let aim = model.aim.clone().expect("the fixture is aimed at a wall");
super::under(ui, model, &aim, false);
}
#[test]
fn the_empty_states_say_two_different_things() {
let mut waiting = seated();
waiting.convs.clear();
waiting.answered = None;
let painted = pane(|ui| beneath(ui, &mut waiting));
assert!(painted.contains(NOT_ANSWERED), "{painted}");
assert!(!painted.contains(NO_CONVERSATIONS), "{painted}");
let mut empty = seated();
empty.convs.clear();
empty.answered = empty.aim.clone();
let painted = pane(|ui| beneath(ui, &mut empty));
assert!(painted.contains(NO_CONVERSATIONS), "{painted}");
}
#[test]
fn aiming_elsewhere_leaves_the_pane_waiting_rather_than_reporting_nothing() {
let mut model = seated();
assert_eq!(model.answered, None, "seated() has not been answered");
model.absorb(
&model.roster[0].channel.clone(),
crate::reply::Read::Answer(crate::reply::Reply::Conversations(vec![conv("id", "one")])),
);
assert_eq!(model.answered, model.aim, "the answer is about the aim");
model.aim_at("(this box's own engine)", "elsewhere");
assert_eq!(model.answered, None, "and it is retired with the rows");
let painted = pane(|ui| beneath(ui, &mut model));
assert!(painted.contains(NOT_ANSWERED), "{painted}");
}
#[test]
fn a_headline_says_the_state_the_age_and_only_the_counts_that_matter() {
let quiet = headline(&conv("id", "port the probe"));
assert_eq!(quiet, "port the probe [quiescent] 42s");
let busy = headline(&crate::reply::convs::ConvRow {
state: AgentState::Live,
attention: 2,
members: 4,
age_secs: 7200,
..conv("id", "port the probe")
});
assert!(quiet.len() < busy.len());
assert!(busy.contains("[live]"), "{busy}");
assert!(busy.contains("2h"), "{busy}");
assert!(busy.contains("2 waiting"), "{busy}");
assert!(busy.contains("4 members"), "{busy}");
}
#[test]
fn an_age_is_compact_and_never_negative() {
for (secs, said) in [
(-3, "0s"),
(0, "0s"),
(42, "42s"),
(59, "59s"),
(60, "1m"),
(3599, "59m"),
(3600, "1h"),
(86_399, "23h"),
(86_400, "1d"),
(172_800, "2d"),
] {
assert_eq!(age(secs), said, "{secs}");
}
}
#[test]
fn a_member_is_indented_and_its_preview_is_weak_ink_at_the_row_s_own_edge() {
let mut model = seated();
model.convs = vec![crate::reply::convs::ConvRow {
depth: 2,
tone: Tone::Weak,
preview: "the galley lies about elision".to_owned(),
..conv("child", "a member")
}];
let window = Window::sized(900.0, 600.0);
let runs = seen(&window, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| beneath(ui, &mut model));
});
let at = |needle: &str| {
runs.iter()
.find(|run| run.text.contains(needle))
.unwrap_or_else(|| panic!("{needle:?} is not on the glass"))
.clone()
};
let words = at("a member");
let preview = at("the galley lies about elision");
assert_eq!(preview.ink, crate::ui::theme::INK_WEAK);
assert!(
(preview.laid.min.x - words.laid.min.x).abs() < 0.5,
"the preview starts under the words: {:?} vs {:?}",
preview.laid,
words.laid
);
assert!(
words.laid.min.y < preview.laid.min.y,
"and under them, not beside"
);
}
#[test]
fn a_failed_row_paints_its_clause_above_its_preview_and_in_its_own_tone() {
let mut model = seated();
model.convs = vec![crate::reply::convs::ConvRow {
tone: Tone::Bad,
failure: "no credential for provider row \"work\"".to_owned().into(),
preview: "the last thing it managed to say".to_owned(),
..conv("id", "a refusing conversation")
}];
let window = Window::sized(900.0, 600.0);
let runs = seen(&window, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| beneath(ui, &mut model));
});
let at = |needle: &str| {
runs.iter()
.find(|run| run.text.contains(needle))
.unwrap_or_else(|| panic!("{needle:?} is not on the glass"))
.clone()
};
let clause = at("no credential for provider row");
assert_eq!(clause.ink, crate::ui::theme::tone_ink(&Tone::Bad));
assert!(
clause.laid.min.y < at("the last thing it managed to say").laid.min.y,
"the clause stands above the preview: {:?}",
clause.laid
);
}
#[test]
fn a_click_selects_the_conversation_and_drops_the_last_one_s_transcript() {
let mut model = seated();
model.conversation = None;
let window = Window::new();
click(&window, &headline(&model.convs[0].clone()), |ctx| {
egui::CentralPanel::default().show(ctx, |ui| beneath(ui, &mut model));
});
assert_eq!(model.conversation.as_deref(), Some("20260830T051200Z-a1b2"));
assert!(model.transcript.entries.is_empty());
assert_eq!(model.live, None);
}
#[test]
fn an_unobserved_state_is_marked_rather_than_painted_as_definite() {
let unsure = headline(&crate::reply::convs::ConvRow {
uncertain: true,
..conv("id", "port the probe")
});
assert_eq!(unsure, "port the probe [quiescent?] 42s");
}
#[test]
fn a_started_conversation_stands_in_the_list_before_the_engine_can_answer() {
let mut model = Model {
conversation: Some("brisk-otter".to_owned()),
start: Some(crate::ui::model::Start {
address: "home".to_owned(),
goal: "port the paint probe".to_owned(),
phase: crate::ui::model::Phase::Started("brisk-otter".to_owned()),
spread: None,
}),
..seated()
};
let painted = pane(|ui| beneath(ui, &mut model));
assert!(painted.contains("brisk-otter [quiescent?]"), "{painted}");
assert!(painted.contains("port the paint probe"), "{painted}");
assert!(
!painted.contains("[live]"),
"no driver this seat has seen: {painted}"
);
}