use cltree::vterm::VirtualTerminal;
use ratatui::prelude::*;
#[test]
fn test_basic_text_output() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"Hello, World!");
let grid = vt.grid();
let text: String = grid[0].iter().take(13).map(|c| c.ch.as_str()).collect();
assert_eq!(text, "Hello, World!");
}
#[test]
fn test_cursor_position_after_text() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"ABC");
assert_eq!(vt.cursor().x, 3);
assert_eq!(vt.cursor().y, 0);
}
#[test]
fn test_cup_cursor_positioning() {
let mut vt = VirtualTerminal::new(20, 10);
vt.feed(b"\x1b[5;10H");
assert_eq!(vt.cursor().y, 4);
assert_eq!(vt.cursor().x, 9);
vt.feed(b"X");
assert_eq!(vt.grid()[4][9].ch, "X");
}
#[test]
fn test_cursor_movement_relative() {
let mut vt = VirtualTerminal::new(20, 10);
vt.feed(b"\x1b[5;10H");
vt.feed(b"\x1b[2A");
assert_eq!(vt.cursor().y, 2);
assert_eq!(vt.cursor().x, 9);
vt.feed(b"\x1b[1B");
assert_eq!(vt.cursor().y, 3);
vt.feed(b"\x1b[3C");
assert_eq!(vt.cursor().x, 12);
vt.feed(b"\x1b[5D");
assert_eq!(vt.cursor().x, 7);
}
#[test]
fn test_erase_display_below() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"AAAAAAAAAA\r\nBBBBBBBBBB\r\nCCCCCCCCCC");
vt.feed(b"\x1b[2;6H\x1b[0J");
assert_eq!(vt.grid()[0][0].ch, "A");
assert_eq!(vt.grid()[1][4].ch, "B");
assert_eq!(vt.grid()[1][5].ch, " ");
assert_eq!(vt.grid()[2][0].ch, " ");
}
#[test]
fn test_erase_display_above() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"AAAAAAAAAA\r\nBBBBBBBBBB\r\nCCCCCCCCCC");
vt.feed(b"\x1b[2;4H\x1b[1J");
assert_eq!(vt.grid()[0][0].ch, " ");
assert_eq!(vt.grid()[1][3].ch, " ");
assert_eq!(vt.grid()[1][4].ch, "B");
assert_eq!(vt.grid()[2][0].ch, "C");
}
#[test]
fn test_erase_display_all() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"AAAAAAAAAA\r\nBBBBBBBBBB\r\nCCCCCCCCCC");
vt.feed(b"\x1b[2J");
for row in vt.grid() {
for cell in row {
assert_eq!(cell.ch, " ");
}
}
}
#[test]
fn test_erase_line() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"ABCDEFGHIJ");
vt.feed(b"\x1b[1;6H\x1b[0K");
assert_eq!(vt.grid()[0][4].ch, "E");
assert_eq!(vt.grid()[0][5].ch, " ");
assert_eq!(vt.grid()[0][9].ch, " ");
vt.feed(b"\x1b[1;4H\x1b[1K");
assert_eq!(vt.grid()[0][0].ch, " ");
assert_eq!(vt.grid()[0][3].ch, " ");
assert_eq!(vt.grid()[0][4].ch, "E");
}
#[test]
fn test_sgr_foreground_colors() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"\x1b[31mR");
assert_eq!(vt.grid()[0][0].style.fg, Some(Color::Red));
vt.feed(b"\x1b[32mG");
assert_eq!(vt.grid()[0][1].style.fg, Some(Color::Green));
vt.feed(b"\x1b[0mN");
assert_eq!(vt.grid()[0][2].style, Style::default());
}
#[test]
fn test_sgr_bold_italic() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"\x1b[1;3mBI");
let style = vt.grid()[0][0].style;
assert!(style.add_modifier.contains(Modifier::BOLD));
assert!(style.add_modifier.contains(Modifier::ITALIC));
}
#[test]
fn test_sgr_256_color() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"\x1b[38;5;196mX");
assert_eq!(vt.grid()[0][0].style.fg, Some(Color::Indexed(196)));
}
#[test]
fn test_sgr_rgb_color() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"\x1b[38;2;255;128;0mX");
assert_eq!(vt.grid()[0][0].style.fg, Some(Color::Rgb(255, 128, 0)));
}
#[test]
fn test_scroll_on_overflow() {
let mut vt = VirtualTerminal::new(5, 3);
vt.feed(b"A\r\nB\r\nC\r\nD\r\nE");
assert_eq!(vt.scrollback().len(), 2);
assert_eq!(vt.scrollback()[0][0].ch, "A");
assert_eq!(vt.scrollback()[1][0].ch, "B");
assert_eq!(vt.grid()[0][0].ch, "C");
assert_eq!(vt.grid()[1][0].ch, "D");
assert_eq!(vt.grid()[2][0].ch, "E");
}
#[test]
fn test_line_wrap() {
let mut vt = VirtualTerminal::new(5, 3);
vt.feed(b"ABCDEFGH");
assert_eq!(vt.grid()[0][4].ch, "E");
assert_eq!(vt.grid()[1][0].ch, "F");
assert_eq!(vt.grid()[1][2].ch, "H");
}
#[test]
fn test_alternate_screen_buffer() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"Main content");
vt.feed(b"\x1b[?1049h");
assert_eq!(vt.grid()[0][0].ch, " ");
vt.feed(b"Alt content");
assert_eq!(vt.grid()[0][0].ch, "A");
vt.feed(b"\x1b[?1049l");
assert_eq!(vt.grid()[0][0].ch, "M");
assert_eq!(vt.grid()[0][1].ch, "a");
}
#[test]
fn test_cursor_visibility() {
let mut vt = VirtualTerminal::new(10, 5);
assert!(vt.cursor().visible);
vt.feed(b"\x1b[?25l");
assert!(!vt.cursor().visible);
vt.feed(b"\x1b[?25h");
assert!(vt.cursor().visible);
}
#[test]
fn test_resize() {
let mut vt = VirtualTerminal::new(10, 5);
vt.feed(b"Hello World");
vt.resize(5, 3);
assert_eq!(vt.cols(), 5);
assert_eq!(vt.rows(), 3);
assert_eq!(vt.grid()[0][0].ch, "H");
assert_eq!(vt.grid()[0][4].ch, "o");
}
#[test]
fn test_carriage_return_overwrite() {
let mut vt = VirtualTerminal::new(10, 5);
vt.feed(b"Hello\rWorld");
assert_eq!(vt.grid()[0][0].ch, "W");
assert_eq!(vt.grid()[0][1].ch, "o");
assert_eq!(vt.grid()[0][2].ch, "r");
}
#[test]
fn test_tab_stops() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"A\tB");
assert_eq!(vt.grid()[0][0].ch, "A");
assert_eq!(vt.grid()[0][8].ch, "B");
}
#[test]
fn test_backspace() {
let mut vt = VirtualTerminal::new(10, 5);
vt.feed(b"AB\x08C");
assert_eq!(vt.grid()[0][0].ch, "A");
assert_eq!(vt.grid()[0][1].ch, "C"); }
#[test]
fn test_delete_characters() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"ABCDEF");
vt.feed(b"\x1b[1;3H\x1b[2P");
assert_eq!(vt.grid()[0][0].ch, "A");
assert_eq!(vt.grid()[0][1].ch, "B");
assert_eq!(vt.grid()[0][2].ch, "E");
assert_eq!(vt.grid()[0][3].ch, "F");
}
#[test]
fn test_insert_lines() {
let mut vt = VirtualTerminal::new(5, 3);
vt.feed(b"A\r\nB\r\nC");
vt.feed(b"\x1b[2;1H\x1b[1L");
assert_eq!(vt.grid()[0][0].ch, "A");
assert_eq!(vt.grid()[1][0].ch, " "); assert_eq!(vt.grid()[2][0].ch, "B"); }
#[test]
fn test_delete_lines() {
let mut vt = VirtualTerminal::new(5, 3);
vt.feed(b"A\r\nB\r\nC");
vt.feed(b"\x1b[2;1H\x1b[1M");
assert_eq!(vt.grid()[0][0].ch, "A");
assert_eq!(vt.grid()[1][0].ch, "C"); assert_eq!(vt.grid()[2][0].ch, " "); }
#[test]
fn test_save_restore_cursor() {
let mut vt = VirtualTerminal::new(10, 5);
vt.feed(b"\x1b[3;5H");
vt.feed(b"\x1b7");
vt.feed(b"\x1b[1;1H"); assert_eq!(vt.cursor().y, 0);
assert_eq!(vt.cursor().x, 0);
vt.feed(b"\x1b8");
assert_eq!(vt.cursor().y, 2);
assert_eq!(vt.cursor().x, 4);
}
#[test]
fn test_scroll_offset() {
let mut vt = VirtualTerminal::new(5, 3);
for i in 0..10 {
vt.feed(format!("{}\r\n", i).as_bytes());
}
assert!(vt.scrollback().len() > 0);
vt.set_scroll_offset(3);
assert_eq!(vt.scroll_offset(), 3);
vt.set_scroll_offset(10000);
assert_eq!(vt.scroll_offset(), vt.scrollback().len());
}
#[test]
fn test_cha_cursor_horizontal_absolute() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"ABCDEFGHIJ");
vt.feed(b"\x1b[5G");
assert_eq!(vt.cursor().x, 4);
}
#[test]
fn test_vpa_vertical_position_absolute() {
let mut vt = VirtualTerminal::new(20, 10);
vt.feed(b"\x1b[5d");
assert_eq!(vt.cursor().y, 4);
}
#[test]
fn test_erase_characters() {
let mut vt = VirtualTerminal::new(10, 3);
vt.feed(b"ABCDEFGHIJ");
vt.feed(b"\x1b[1;4H\x1b[3X");
assert_eq!(vt.grid()[0][2].ch, "C");
assert_eq!(vt.grid()[0][3].ch, " ");
assert_eq!(vt.grid()[0][4].ch, " ");
assert_eq!(vt.grid()[0][5].ch, " ");
assert_eq!(vt.grid()[0][6].ch, "G");
}
#[test]
fn test_complex_sgr_sequence() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed(b"\x1b[1;31;44mX");
let style = vt.grid()[0][0].style;
assert!(style.add_modifier.contains(Modifier::BOLD));
assert_eq!(style.fg, Some(Color::Red));
assert_eq!(style.bg, Some(Color::Blue));
}
#[test]
fn test_combining_character() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed("é".as_bytes());
assert_eq!(vt.grid()[0][0].ch, "é");
assert_eq!(vt.cursor().x, 1); }
#[test]
fn test_variation_selector() {
let mut vt = VirtualTerminal::new(20, 5);
vt.feed("⚛\u{FE0F}".as_bytes());
assert!(vt.grid()[0][0].ch.contains('⚛'));
assert!(vt.grid()[0][0].ch.contains('\u{FE0F}'));
}