//! Main-screen chrome helpers: ASCII wordmark, compact fallback, help text. use onionwire::tui::{ Pane, banner_for_width, compact_banner, help_overlay_text, main_footer_hints, onion_glyph, status_footer, wordmark_banner, }; #[test] fn wordmark_banner_is_nonempty_and_fits_80() { let banner = wordmark_banner(); assert!(!banner.is_empty()); for line in banner.lines() { assert!( line.chars().count() <= 80, "wordmark line exceeds 80 chars: {line:?} ({})", line.chars().count() ); } } #[test] fn compact_banner_is_nonempty_and_fits_40() { let compact = compact_banner(); assert!(!compact.is_empty()); assert!( compact.chars().count() <= 40, "compact banner exceeds 40 chars ({})", compact.chars().count() ); } #[test] fn onion_glyph_is_nonempty() { assert!(!onion_glyph().is_empty()); } #[test] fn help_overlay_lists_core_bindings() { let help = help_overlay_text(); assert!(!help.is_empty()); for needle in [ "Tab", "F2", "F3", "F4", "F5", "/profile", "/pay", "/tip", "/backup", "/restore", "Ctrl-Q", "?", ] { assert!(help.contains(needle), "help overlay missing {needle:?}"); } for line in help.lines() { assert!( line.chars().count() <= 80, "help line exceeds 80 chars: {line:?}" ); } } #[test] fn banner_for_width_collapses_when_narrow() { let full = wordmark_banner(); let max_line = full.lines().map(|l| l.chars().count()).max().unwrap(); assert_eq!(banner_for_width(max_line as u16), full); assert_eq!(banner_for_width(max_line as u16 - 1), compact_banner()); assert_eq!(banner_for_width(80), full); assert_eq!(banner_for_width(120), full); } #[test] fn chrome_renders_at_80x24_and_120x40() { use ratatui::Terminal; use ratatui::backend::TestBackend; use ratatui::layout::{Constraint, Layout}; use ratatui::widgets::Paragraph; let fp = "abcdef0123456789"; let onion = "abcdefghijklmnopqrstuvwxyz234567abcdefghijklmnopq.onion"; for (w, h) in [(80u16, 24u16), (120, 40)] { let backend = TestBackend::new(w, h); let mut terminal = Terminal::new(backend).expect("terminal"); terminal .draw(|f| { let banner = banner_for_width(f.area().width); let banner_h = banner.lines().count() as u16; let chunks = Layout::vertical([ Constraint::Length(banner_h), Constraint::Min(3), Constraint::Length(1), ]) .split(f.area()); f.render_widget(Paragraph::new(banner), chunks[0]); let footer = status_footer(f.area().width, fp, onion, None, main_footer_hints()); f.render_widget(Paragraph::new(footer), chunks[2]); }) .expect("draw"); let buf = terminal.backend().buffer(); let row0: String = (0..w).map(|x| buf[(x, 0)].symbol().to_string()).collect(); assert!( row0.contains("ONIONWIRE"), "banner missing on row 0 at {w}x{h}: {row0:?}" ); let footer: String = (0..w) .map(|x| buf[(x, h - 1)].symbol().to_string()) .collect(); assert!( footer.contains("? help"), "footer missing ? help at {w}x{h}: {footer:?}" ); assert!( footer.contains("TOR"), "footer missing TOR at {w}x{h}: {footer:?}" ); } } #[test] fn main_footer_keeps_help_at_80_and_120() { let fp = "abcdef0123456789deadbeef"; let onion = "abcdefghijklmnopqrstuvwxyz234567abcdefghijklmnopq.onion"; let hints = main_footer_hints(); assert!(hints.contains("? help")); for w in [80u16, 120] { let line = status_footer(w, fp, onion, None, hints); assert!( line.chars().count() <= w as usize, "footer wider than {w}: {} {line:?}", line.chars().count() ); assert!( line.contains("? help"), "footer missing ? help at {w}: {line:?}" ); assert!(line.contains("TOR"), "footer missing TOR at {w}: {line:?}"); assert!( line.contains("me:"), "footer missing identity at {w}: {line:?}" ); } let crowded = status_footer(80, fp, onion, Some("rotated ยท notified 1/2 friends"), hints); assert!( crowded.chars().count() <= 80, "crowded footer wider than 80: {} {crowded:?}", crowded.chars().count() ); assert!( crowded.contains("? help"), "status note crowded out ? help: {crowded:?}" ); assert!( crowded.contains("TOR"), "crowded footer missing TOR: {crowded:?}" ); } #[test] fn pane_focus_cycles_roster_chat_composer() { assert_eq!(Pane::Roster.next(), Pane::Chat); assert_eq!(Pane::Chat.next(), Pane::Composer); assert_eq!(Pane::Composer.next(), Pane::Roster); assert_eq!(Pane::Roster.prev(), Pane::Composer); assert_eq!(Pane::Chat.prev(), Pane::Roster); assert_eq!(Pane::Composer.prev(), Pane::Chat); } #[test] fn restore_terminal_is_callable_without_panic() { onionwire::tui::restore_terminal(); }