// Snapshot testing utilities use ratatui::backend::TestBackend; use ratatui::buffer::Buffer; use ratatui::layout::Rect; use ratatui::Terminal; /// Конвертирует Buffer в читаемую строку для snapshot тестов pub fn buffer_to_string(buffer: &Buffer) -> String { let area = buffer.area(); let mut result = String::new(); for y in 0..area.height { let mut line = String::new(); for x in 0..area.width { line.push_str(buffer[(x, y)].symbol()); } // Убираем trailing spaces в конце строки result.push_str(line.trim_end()); if y < area.height - 1 { result.push('\n'); } } result } /// Создаёт TestBackend с заданным размером и рендерит UI pub fn render_to_buffer(width: u16, height: u16, render_fn: F) -> Buffer where F: FnOnce(&mut ratatui::Frame), { let backend = TestBackend::new(width, height); let mut terminal = Terminal::new(backend).unwrap(); terminal.draw(render_fn).unwrap(); terminal.backend().buffer().clone() } /// Макрос для упрощения snapshot тестов #[macro_export] macro_rules! assert_ui_snapshot { ($name:expr, $width:expr, $height:expr, $render_fn:expr) => {{ use $crate::helpers::snapshot_utils::{buffer_to_string, render_to_buffer}; let buffer = render_to_buffer($width, $height, $render_fn); let output = buffer_to_string(&buffer); insta::assert_snapshot!($name, output); }}; } #[cfg(test)] mod tests { use super::*; use ratatui::widgets::{Block, Borders}; #[test] fn test_buffer_to_string_simple() { let buffer = render_to_buffer(10, 3, |f| { let block = Block::default().borders(Borders::ALL).title("Hi"); f.render_widget(block, f.area()); }); let result = buffer_to_string(&buffer); assert!(result.contains("Hi")); assert!(result.contains("┌")); assert!(result.contains("└")); } #[test] fn test_buffer_to_string_removes_trailing_spaces() { let buffer = render_to_buffer(20, 3, |f| { let block = Block::default().title("Test"); f.render_widget(block, Rect::new(0, 0, 10, 3)); }); let result = buffer_to_string(&buffer); let lines: Vec<&str> = result.lines().collect(); // Проверяем что trailing spaces убраны for line in lines { assert!(!line.ends_with(' ') || line.trim().is_empty()); } } }