Split core and TUI crates
This commit is contained in:
144
crates/tele-tui/tests/helpers/snapshot_utils.rs
Normal file
144
crates/tele-tui/tests/helpers/snapshot_utils.rs
Normal file
@@ -0,0 +1,144 @@
|
||||
// Snapshot testing utilities
|
||||
|
||||
use ratatui::backend::TestBackend;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::style::{Color, Modifier};
|
||||
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
|
||||
}
|
||||
|
||||
/// Serializes only cells with non-default style, grouped by row and style.
|
||||
pub fn buffer_to_style_snapshot(buffer: &Buffer) -> String {
|
||||
let area = buffer.area();
|
||||
let mut rows = Vec::new();
|
||||
|
||||
for y in 0..area.height {
|
||||
let mut segments = Vec::new();
|
||||
let mut x = 0;
|
||||
|
||||
while x < area.width {
|
||||
let cell = &buffer[(x, y)];
|
||||
if is_default_style(cell) {
|
||||
x += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
let start = x;
|
||||
let fg = cell.fg;
|
||||
let bg = cell.bg;
|
||||
let modifier = cell.modifier;
|
||||
let mut text = String::new();
|
||||
|
||||
while x < area.width {
|
||||
let next = &buffer[(x, y)];
|
||||
if is_default_style(next)
|
||||
|| next.fg != fg
|
||||
|| next.bg != bg
|
||||
|| next.modifier != modifier
|
||||
{
|
||||
break;
|
||||
}
|
||||
text.push_str(next.symbol());
|
||||
x += 1;
|
||||
}
|
||||
|
||||
segments.push(format!(
|
||||
"{}..{} {:?}/{:?}/{:?}: {:?}",
|
||||
start,
|
||||
x.saturating_sub(1),
|
||||
fg,
|
||||
bg,
|
||||
modifier,
|
||||
text.trim_end()
|
||||
));
|
||||
}
|
||||
|
||||
if !segments.is_empty() {
|
||||
rows.push(format!("y={}: {}", y, segments.join(" | ")));
|
||||
}
|
||||
}
|
||||
|
||||
rows.join("\n")
|
||||
}
|
||||
|
||||
fn is_default_style(cell: &ratatui::buffer::Cell) -> bool {
|
||||
cell.fg == Color::Reset && cell.bg == Color::Reset && cell.modifier == Modifier::empty()
|
||||
}
|
||||
|
||||
/// Создаёт TestBackend с заданным размером и рендерит UI
|
||||
pub fn render_to_buffer<F>(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::layout::Rect;
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user