use std::time::Duration;
use crate::brain::agent::service::nudge::{in_pressure_warning_band, should_emit_pressure_warning};
use crate::channels::telegram::flow::{
COMPACTING_HEADER_TEXT, FlowHeader, FlowLine, HeaderMarkup, compacted_flow_line,
compacting_flow_line, flow_header_text, render_flow_html_chrome_pref, render_flow_rich,
starts_with_icon,
};
use crate::channels::telegram::flow_chrome::{FlowSections, FooterParts, merged_footer};
#[test]
fn compacting_line_without_prediction() {
assert_eq!(
compacting_flow_line(68.0, None),
"⏳ Compacting context — 68% full…"
);
}
#[test]
fn compacting_line_shows_observed_eta() {
assert_eq!(
compacting_flow_line(68.0, Some(Duration::from_secs(42))),
"⏳ Compacting context — 68% full (≈42s)…"
);
}
#[test]
fn compacting_line_humanizes_minute_eta() {
assert_eq!(
compacting_flow_line(71.0, Some(Duration::from_secs(132))),
"⏳ Compacting context — 71% full (≈2 min 12s)…"
);
}
#[test]
fn compacting_line_rounds_fill_level() {
assert!(compacting_flow_line(67.7, None).contains("68% full"));
assert!(compacting_flow_line(99.4, None).contains("99% full"));
}
#[test]
fn compacting_footer_suppresses_duplicate_activity_segment() {
let lines = [FlowLine::Text(
"⏳ Compacting context — 66% full…".to_string(),
)];
let compacting = render_flow_html_chrome_pref(
&lines,
&FlowHeader::Live(Some(COMPACTING_HEADER_TEXT)),
None,
&FlowSections::default(),
usize::MAX,
5,
None,
true,
);
assert_eq!(
compacting.matches("Compacting context").count(),
1,
"pinned header is the sole compaction string while compacting: {compacting:?}"
);
let idle = render_flow_html_chrome_pref(
&lines,
&FlowHeader::Live(Some("⚙️")),
None,
&FlowSections::default(),
usize::MAX,
5,
None,
false,
);
assert_eq!(
idle.matches("Compacting context").count(),
2,
"without the flag the activity preview duplicates the body entry: {idle:?}"
);
}
#[test]
fn compacting_rich_footer_suppresses_duplicate_status() {
let lines = [FlowLine::Text(
"⏳ Compacting context — 66% full…".to_string(),
)];
let rich = render_flow_rich(&lines, Some(COMPACTING_HEADER_TEXT), true);
let header = rich.lines().next().unwrap_or_default();
assert_eq!(
header.matches("Compacting context").count(),
1,
"rich header dedupes too: {rich:?}"
);
assert!(
rich.contains("⏳ Compacting context — 66% full…"),
"body keeps the START line: {rich:?}"
);
let idle = render_flow_rich(&lines, Some(COMPACTING_HEADER_TEXT), false);
let idle_header = idle.lines().next().unwrap_or_default();
assert_eq!(
idle_header.matches("Compacting context").count(),
2,
"without the flag the activity preview duplicates the pin: {idle:?}"
);
}
#[test]
fn compacted_line_under_a_minute() {
assert_eq!(
compacted_flow_line(68.0, 26.0, Duration::from_secs(42)),
"✅ Compacted: 68% → 26% in 42s"
);
}
#[test]
fn compacted_line_multi_minute() {
assert_eq!(
compacted_flow_line(71.0, 24.0, Duration::from_secs(132)),
"✅ Compacted: 71% → 24% in 2 min 12s"
);
}
#[test]
fn compacted_line_floors_subsecond_elapsed_to_1s() {
assert_eq!(
compacted_flow_line(66.0, 30.0, Duration::from_millis(300)),
"✅ Compacted: 66% → 30% in 1s"
);
}
#[test]
fn header_const_is_number_free() {
assert_eq!(COMPACTING_HEADER_TEXT, "⏳ Compacting context…");
assert!(!COMPACTING_HEADER_TEXT.contains('%'));
assert!(!COMPACTING_HEADER_TEXT.chars().any(|c| c.is_ascii_digit()));
}
#[test]
fn pressure_band_boundaries() {
assert!(!in_pressure_warning_band(54.9));
assert!(in_pressure_warning_band(55.0));
assert!(in_pressure_warning_band(64.9));
assert!(!in_pressure_warning_band(65.0));
}
#[test]
fn pressure_warning_once_per_entry() {
assert!(should_emit_pressure_warning(60.0, false).is_some());
assert!(should_emit_pressure_warning(60.0, true).is_none());
assert!(should_emit_pressure_warning(40.0, false).is_none());
}
#[test]
fn starts_with_icon_classification() {
assert!(starts_with_icon("⏳ Compacting context…"));
assert!(starts_with_icon("✅ bash git status"));
assert!(starts_with_icon("❌ grep pattern"));
assert!(!starts_with_icon("bash gh pr list"));
assert!(!starts_with_icon("Reading the handler."));
assert!(!starts_with_icon("Чтение лога"));
assert!(!starts_with_icon(""));
}
#[test]
fn live_header_drops_gear_before_icon_status() {
assert_eq!(
flow_header_text(
11,
&FlowHeader::Live(Some("1:05")),
Some(COMPACTING_HEADER_TEXT),
HeaderMarkup::Html
),
"<b>⏳ Compacting context…</b> • <i>11 tool calls</i> • <i>1:05</i>"
);
assert_eq!(
flow_header_text(
3,
&FlowHeader::Live(Some("0:12")),
Some("Reading logs"),
HeaderMarkup::Html
),
"⚙️ <b>Reading logs</b> • <i>3 tool calls</i> • <i>0:12</i>"
);
}
#[test]
fn live_footer_drops_gear_before_icon_activity() {
let icon = merged_footer(
&FooterParts {
outcome: None,
plan_state: None,
working_on: None,
activity: Some("✅ bash git status"),
tool_count: 1,
has_log: true,
ctx: None,
elapsed_secs: 0,
bg: None,
},
HeaderMarkup::Markdown,
);
assert_eq!(icon, "✅ bash git status • 1 tool calls • ⏱ 0:00");
let plain = merged_footer(
&FooterParts {
outcome: None,
plan_state: None,
working_on: None,
activity: Some("Reading the handler."),
tool_count: 2,
has_log: true,
ctx: None,
elapsed_secs: 0,
bg: None,
},
HeaderMarkup::Markdown,
);
assert_eq!(plain, "⚙️ Reading the handler. • 2 tool calls • ⏱ 0:00");
}
#[test]
fn icon_led_segment_retires_the_bare_cog_fallback() {
let out = merged_footer(
&FooterParts {
outcome: None,
plan_state: None,
working_on: Some(COMPACTING_HEADER_TEXT),
activity: None,
tool_count: 0,
has_log: true,
ctx: None,
elapsed_secs: 65,
bg: None,
},
HeaderMarkup::Markdown,
);
assert_eq!(out, "⏳ Compacting context… • ⏱ 1:05");
}