use crate::tui::render::chat::{anchored_scroll_offset, format_turn_spinner_meta};
#[test]
fn header_stays_on_its_row_after_growth() {
let (offset, auto) = anchored_scroll_offset(40, 3, 100);
assert_eq!(offset, 63, "offset pins the header to its row");
assert!(!auto, "not at the bottom, so auto-scroll stays off");
}
#[test]
fn anchor_at_top_scrolls_all_the_way_up() {
let (offset, auto) = anchored_scroll_offset(0, 0, 100);
assert_eq!(offset, 100);
assert!(!auto);
}
#[test]
fn anchor_resolving_to_bottom_rearms_auto_scroll() {
let (offset, auto) = anchored_scroll_offset(100, 0, 40);
assert_eq!(offset, 0, "clamped to the bottom");
assert!(
auto,
"at the bottom, auto-scroll re-arms so streaming sticks"
);
}
#[test]
fn row_below_line_top_saturates_without_panic() {
let (offset, auto) = anchored_scroll_offset(2, 10, 50);
assert_eq!(offset, 50, "desired top saturates to 0 -> full scroll up");
assert!(!auto);
}
#[test]
fn spinner_meta_labels_turn_total() {
let m = format_turn_spinner_meta(8, 31872).unwrap();
assert!(m.contains("8s"), "{m}");
assert!(
m.contains("31872 tok this turn"),
"counter must read as a turn total, not a single thought: {m}"
);
assert!(m.starts_with(" (") && m.ends_with(')'), "{m}");
}
#[test]
fn spinner_meta_is_none_when_nothing_to_show() {
assert!(format_turn_spinner_meta(0, 0).is_none());
}
#[test]
fn spinner_meta_never_shows_ctx() {
let m = format_turn_spinner_meta(3, 120).unwrap();
assert!(m.contains("3s") && m.contains("120 tok this turn"), "{m}");
assert!(
!m.contains("ctx"),
"spinner must not repeat the ctx budget: {m}"
);
}
use crate::tui::render::chat::should_compensate_for_growth;
#[test]
fn streaming_growth_is_still_compensated() {
assert!(should_compensate_for_growth(false, 40, 100, 130, false));
}
#[test]
fn an_expand_is_never_compensated() {
assert!(
!should_compensate_for_growth(false, 40, 100, 400, true),
"a user-opened block must not shift the viewport"
);
}
#[test]
fn an_expand_is_not_compensated_even_when_it_grows_hugely() {
assert!(!should_compensate_for_growth(false, 5, 100, 5000, true));
}
#[test]
fn auto_scroll_never_compensates() {
assert!(!should_compensate_for_growth(true, 40, 100, 130, false));
}
#[test]
fn the_first_render_never_compensates() {
assert!(!should_compensate_for_growth(false, 40, 0, 500, false));
}
#[test]
fn shrinking_never_compensates() {
assert!(!should_compensate_for_growth(false, 40, 300, 100, false));
assert!(!should_compensate_for_growth(false, 40, 300, 100, true));
}
#[test]
fn at_the_bottom_there_is_nothing_to_hold_still() {
assert!(!should_compensate_for_growth(false, 0, 100, 130, false));
}