mod common;
use common::dump_frame;
use gwk_domain::ids::Timestamp;
use gwk_theme::marks::GlyphSet;
use gwk_theme::tier::ColorTier;
use gwk_tui::board::{BoardTarget, BoardView};
use gwk_tui::console::{FleetContext, LoadState, render_fleet};
use gwk_tui::input::HitMap;
fn render(width: u16, height: u16, tier: ColorTier, glyphs: GlyphSet) -> String {
render_at(width, height, tier, glyphs, "2026-08-11T17:30:00Z")
}
fn render_at(width: u16, height: u16, tier: ColorTier, glyphs: GlyphSet, now: &str) -> String {
let state = common::estate::estate_board_state(BoardView::Fleet);
let context = FleetContext {
now: Timestamp::new(now),
load: LoadState::Ready,
};
dump_frame(width, height, tier, glyphs, |area, buf, tier, glyphs| {
let mut hits = HitMap::<BoardTarget>::new();
render_fleet(
area,
buf,
&state,
&context,
state
.attempts
.get(1)
.map(|attempt| BoardTarget::Attempt(attempt.id.clone()))
.as_ref(),
tier,
glyphs,
&mut hits,
);
})
}
#[test]
fn fleet_joins_cost_sessions_leases_and_unclaimed_resources() {
let rendered = render(120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(rendered.contains("at-tui-impl"), "{rendered}");
assert!(
rendered.contains("$2.10"),
"joined session cost is absent:\n{rendered}"
);
assert!(rendered.contains("UNCLAIMED"), "{rendered}");
assert!(rendered.contains("ls-release"), "{rendered}");
assert!(rendered.contains("wt-release"), "{rendered}");
assert!(rendered.contains("SPEND / HOUR"), "{rendered}");
}
#[test]
fn fleet_floor_drops_whole_low_priority_columns() {
let rendered = render(80, 24, ColorTier::Truecolor, GlyphSet::Unicode);
let header = rendered.lines().nth(2).unwrap_or_default();
assert!(header.contains("ATTEMPT"), "{header}");
assert!(header.contains("STATE"), "{header}");
assert!(header.contains("SPEND"), "{header}");
assert!(!header.contains("TOKENS"), "{header}");
assert!(rendered.contains("> at-pty-impl"), "{rendered}");
}
#[test]
fn fleet_degrades_marks_without_losing_state_words() {
let rendered = render(120, 40, ColorTier::Mono, GlyphSet::Ascii);
assert!(rendered.contains("- running"), "{rendered}");
assert!(rendered.contains("X failed"), "{rendered}");
}
#[test]
fn fleet_age_cell_never_cuts_mid_value_at_the_design_width() {
let rendered = render_at(
120,
40,
ColorTier::Truecolor,
GlyphSet::Unicode,
"2026-08-12T05:45:00Z",
);
assert!(rendered.contains("21h00"), "{rendered}");
let rendered = render_at(
120,
40,
ColorTier::Truecolor,
GlyphSet::Unicode,
"2026-08-23T05:45:00Z",
);
assert!(!rendered.contains("11d2"), "{rendered}");
}
fn render_without_costs(width: u16, height: u16, tier: ColorTier, glyphs: GlyphSet) -> String {
let mut state = common::estate::estate_board_state(BoardView::Fleet);
state.costs.clear();
let context = FleetContext {
now: Timestamp::new("2026-08-11T17:30:00Z"),
load: LoadState::Ready,
};
dump_frame(width, height, tier, glyphs, |area, buf, tier, glyphs| {
let mut hits = HitMap::<BoardTarget>::new();
render_fleet(area, buf, &state, &context, None, tier, glyphs, &mut hits);
})
}
#[test]
fn fleet_states_an_empty_cost_ledger_rather_than_pricing_it_at_zero() {
for (width, height, tier, glyphs) in [
(120u16, 40u16, ColorTier::Truecolor, GlyphSet::Unicode),
(80, 24, ColorTier::Truecolor, GlyphSet::Unicode),
(120, 40, ColorTier::Mono, GlyphSet::Ascii),
] {
let rendered = render_without_costs(width, height, tier, glyphs);
let at = format!("at {width}x{height} {}", tier.as_str());
assert!(
!rendered.contains("$0.00"),
"a zero fold priced itself {at}:\n{rendered}"
);
assert!(
rendered.contains("no spend recorded"),
"the header does not say the ledger is empty {at}:\n{rendered}"
);
assert!(
!rendered.contains("> $0"),
"the spend chart drew a scale over nothing {at}:\n{rendered}"
);
assert!(
rendered.contains("no scale to draw"),
"the chart is silent about why it is blank {at}:\n{rendered}"
);
assert!(
rendered.contains("0 priced"),
"the honest row counts went missing {at}:\n{rendered}"
);
}
}
#[test]
fn fleet_keeps_pricing_a_ledger_that_has_entries() {
let rendered = render(120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(rendered.contains("$"), "{rendered}");
assert!(!rendered.contains("no spend recorded"), "{rendered}");
assert!(!rendered.contains("no scale to draw"), "{rendered}");
}
fn render_state(
state: &gwk_tui::board::BoardState,
width: u16,
height: u16,
tier: ColorTier,
glyphs: GlyphSet,
) -> String {
let context = FleetContext {
now: Timestamp::new("2026-08-11T17:30:00Z"),
load: LoadState::Ready,
};
dump_frame(width, height, tier, glyphs, |area, buf, tier, glyphs| {
let mut hits = HitMap::<BoardTarget>::new();
render_fleet(area, buf, state, &context, None, tier, glyphs, &mut hits);
})
}
fn partial_page() -> gwk_tui::board::BoardState {
let mut state = common::estate::estate_board_state(BoardView::Fleet);
state.complete = false;
state
.sessions
.retain(|session| session.id.as_str() != "es-pty-impl");
state
}
fn row<'a>(rendered: &'a str, id: &str) -> &'a str {
rendered
.lines()
.find(|line| line.contains(id))
.unwrap_or_else(|| panic!("no row for {id}:\n{rendered}"))
}
#[test]
fn fleet_column_does_not_claim_liveness_it_cannot_read() {
let header = render(120, 40, ColorTier::Truecolor, GlyphSet::Unicode)
.lines()
.nth(2)
.unwrap_or_default()
.to_owned();
assert!(header.contains("NOEND"), "{header}");
assert!(
!header.contains("SES"),
"the column still names the noun rather than the field:\n{header}"
);
assert!(header.contains("SUB"), "a neighbouring column fell out");
assert!(header.contains("LEASE"), "a neighbouring column fell out");
}
#[test]
fn a_running_attempt_with_no_session_reads_as_unknown_not_as_zero() {
for (tier, glyphs) in [
(ColorTier::Truecolor, GlyphSet::Unicode),
(ColorTier::Mono, GlyphSet::Ascii),
] {
let rendered = render_state(&partial_page(), 120, 40, tier, glyphs);
let at = tier.as_str();
assert!(
row(&rendered, "at-pty-impl").contains('?'),
"a running attempt with no session record read as a measured zero at {at}:\n{rendered}"
);
assert!(
!row(&rendered, "at-tui-impl").contains('?'),
"the unknown mark leaked onto a bound attempt at {at}:\n{rendered}"
);
assert!(
!row(&rendered, "at-ship-done").contains('?'),
"the unknown mark leaked onto a finished attempt at {at}:\n{rendered}"
);
let mut settled = partial_page();
for session in &mut settled.sessions {
if session.attempt_id.as_str() == "at-tui-impl" {
session.ended_at = Some(Timestamp::new("2026-08-11T17:00:00Z"));
}
}
let rendered = render_state(&settled, 120, 40, tier, glyphs);
assert!(
!row(&rendered, "at-tui-impl").contains('?'),
"a measured zero was reported as an absence at {at}:\n{rendered}"
);
}
}
#[test]
fn the_lens_states_the_three_facts_the_log_does_not_carry() {
for (tier, glyphs) in [
(ColorTier::Truecolor, GlyphSet::Unicode),
(ColorTier::Mono, GlyphSet::Ascii),
] {
let rendered = render_state(&partial_page(), 120, 40, tier, glyphs);
let at = tier.as_str();
assert!(
rendered.contains("UNKNOWN 3 facts not in the log"),
"no unknowns block at {at}:\n{rendered}"
);
for note in [
"liveness: no end stamp on 2 of 4 sessions -- unended is not alive",
"engine binding: none on this page for 1 running attempt",
"fleet size: read short of the last page -- counts are floors",
] {
assert!(
rendered.contains(note),
"the lens is silent about {note:?} at {at}:\n{rendered}"
);
}
}
}
#[test]
fn the_block_keeps_its_subjects_when_the_floor_takes_its_words() {
let rendered = render_state(&partial_page(), 80, 24, ColorTier::Mono, GlyphSet::Ascii);
assert!(
rendered.contains("UNKNOWN liveness, engine binding, fleet size"),
"the floor dropped the subjects too:\n{rendered}"
);
assert!(
!rendered.contains("unended is not alive"),
"the floor kept the worded form and paid four rows for it:\n{rendered}"
);
assert!(
rendered.contains("at-pty-impl"),
"the block displaced its own subject:\n{rendered}"
);
}
#[test]
fn a_page_with_nothing_unknown_carries_no_block_at_all() {
let mut state = common::estate::estate_board_state(BoardView::Fleet);
for session in &mut state.sessions {
if session.ended_at.is_none() {
session.ended_at = Some(Timestamp::new("2026-08-11T17:00:00Z"));
}
}
let rendered = render_state(&state, 120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(
!rendered.contains("UNKNOWN"),
"a page carrying every fact still apologised for one:\n{rendered}"
);
assert!(rendered.contains("UNCLAIMED"), "{rendered}");
}
#[test]
fn a_partial_read_folds_to_a_floor_and_says_which() {
let partial = render_state(
&partial_page(),
120,
40,
ColorTier::Truecolor,
GlyphSet::Unicode,
);
assert!(
partial.contains("at least 11 attempts"),
"a partial page presented its counts as totals:\n{partial}"
);
let complete = render(120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(
complete.contains("11 attempts") && !complete.contains("at least"),
"a complete read hedged a count it had actually finished:\n{complete}"
);
}
#[test]
fn an_empty_ledger_and_an_empty_page_are_different_sentences() {
let mut complete = common::estate::estate_board_state(BoardView::Fleet);
complete.costs.clear();
let rendered = render_state(&complete, 120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(rendered.contains("no spend recorded"), "{rendered}");
let mut partial = complete.clone();
partial.complete = false;
let rendered = render_state(&partial, 120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(
rendered.contains("no spend on this page"),
"a partial read claimed the whole ledger was empty:\n{rendered}"
);
assert!(!rendered.contains("no spend recorded"), "{rendered}");
}
#[test]
fn the_header_chrome_never_paints_over_the_summary_it_follows() {
let rendered = render_state(
&partial_page(),
100,
30,
ColorTier::Truecolor,
GlyphSet::Unicode,
);
let header = rendered.lines().next().unwrap_or_default();
assert!(
header.contains("$5.30 today"),
"the chrome tail ate the spend figure:\n{header}"
);
assert!(header.contains("17:30"), "the clock fell off:\n{header}");
assert!(
!header.contains("as-of"),
"the tail kept its low-priority parts and collided anyway:\n{header}"
);
}
fn contradictory_page() -> gwk_tui::board::BoardState {
let mut state = common::estate::estate_board_state(BoardView::Fleet);
let duplicate = state
.sessions
.first()
.cloned()
.expect("the estate fixture carries at least one session");
state.sessions.push(duplicate);
state
}
#[test]
fn the_alarm_reads_before_the_rows_it_impeaches() {
let rendered = render_state(
&contradictory_page(),
120,
40,
ColorTier::Truecolor,
GlyphSet::Unicode,
);
let alarm = rendered
.lines()
.position(|line| line.contains("INTEGRITY"))
.unwrap_or_else(|| panic!("no integrity alarm on a contradictory page:\n{rendered}"));
let columns = rendered
.lines()
.position(|line| line.contains("ATTEMPT") && line.contains("STATE"))
.unwrap_or_else(|| panic!("no column heads:\n{rendered}"));
assert!(
alarm < columns,
"the alarm printed at line {alarm}, below the column heads at {columns}:\n{rendered}"
);
assert!(rendered.contains("duplicate"), "{rendered}");
}
#[test]
fn a_clean_page_paints_no_alarm_and_loses_no_rows() {
let clean = common::estate::estate_board_state(BoardView::Fleet);
let with_alarm = render_state(
&contradictory_page(),
120,
40,
ColorTier::Truecolor,
GlyphSet::Unicode,
);
let without = render_state(&clean, 120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
assert!(
!without.contains("INTEGRITY"),
"a clean page raised an alarm:\n{without}"
);
let clean_columns = without
.lines()
.position(|line| line.contains("ATTEMPT") && line.contains("STATE"));
let alarmed_columns = with_alarm
.lines()
.position(|line| line.contains("ATTEMPT") && line.contains("STATE"));
assert_eq!(clean_columns, Some(2), "{without}");
assert!(
alarmed_columns > clean_columns,
"the alarm did not push the table down at all — it is painting over it"
);
}
#[test]
fn the_alarm_is_carried_by_words_not_colour() {
let state = contradictory_page();
let colour = render_state(&state, 120, 40, ColorTier::Truecolor, GlyphSet::Unicode);
let mono = render_state(&state, 120, 40, ColorTier::Mono, GlyphSet::Ascii);
let words = |frame: &str| {
frame
.lines()
.filter(|line| line.contains("INTEGRITY") || line.contains("duplicate"))
.map(str::trim_end)
.map(str::to_owned)
.collect::<Vec<_>>()
};
assert!(!words(&colour).is_empty(), "{colour}");
assert_eq!(
words(&colour),
words(&mono),
"the alarm said different things in mono:\n{mono}"
);
}
#[test]
fn the_alarm_degrades_rather_than_eating_the_fleet() {
let rendered = render_state(
&contradictory_page(),
80,
24,
ColorTier::Truecolor,
GlyphSet::Unicode,
);
assert!(
rendered.contains("INTEGRITY"),
"the alarm vanished at the floor — the one thing it may never do:\n{rendered}"
);
let itemized = rendered.lines().filter(|l| l.contains("duplicate")).count();
assert_eq!(itemized, 0, "the floor kept the itemization:\n{rendered}");
assert!(rendered.contains("at-tui-impl"), "{rendered}");
}