use justerm_core::{Engine, Modifiers, MouseAction, MouseButton, MouseEvent, TermDamage};
fn left_press() -> MouseEvent {
MouseEvent {
button: Some(MouseButton::Left),
action: MouseAction::Press,
col: 0,
row: 0,
px: 0,
py: 0,
mods: Modifiers::empty(),
}
}
#[test]
fn ris_recovers_stuck_mouse_tracking() {
let mut t = Engine::new(10, 3);
t.feed(b"\x1b[?1000h\x1b[?1006h"); assert!(t.encode_mouse(left_press()).is_some()); t.feed(b"\x1bc"); assert!(
t.encode_mouse(left_press()).is_none(),
"RIS must reset mouse tracking to Off",
);
}
#[test]
fn ris_clears_screen_scrollback_and_homes_cursor() {
let mut t = Engine::new(4, 2);
t.feed(b"a\r\nb\r\nc\r\nd"); assert!(t.scrollback_len() > 0);
t.feed(b"\x1bc"); assert_eq!(t.scrollback_len(), 0, "scrollback cleared");
assert_eq!(t.grid().cell(0, 0).c(), ' ', "screen cleared");
t.feed(b"X"); assert_eq!(t.grid().cell(0, 0).c(), 'X');
}
#[test]
fn ris_preserves_replies_queued_before_it() {
let mut t = Engine::new(10, 2);
t.feed(b"\x1b[c\x1bc"); assert_eq!(t.drain_replies(), b"\x1b[?62;22c");
}
#[test]
fn ris_signals_full_damage() {
let mut t = Engine::new(4, 2);
t.feed(b"abc");
t.reset_damage(); t.feed(b"\x1bc"); assert!(matches!(t.damage(), TermDamage::Full));
}
#[test]
fn decstr_keeps_screen_and_does_not_reset_mouse() {
let mut t = Engine::new(5, 2);
t.feed(b"hi"); t.feed(b"\x1b[?1000h\x1b[?1006h"); t.feed(b"\x1b[!p"); assert_eq!(
t.grid().cell(0, 0).c(),
'h',
"DECSTR must not clear the screen"
);
assert_eq!(t.grid().cell(0, 1).c(), 'i');
assert!(
t.encode_mouse(left_press()).is_some(),
"DECSTR must NOT reset mouse tracking (only RIS does)",
);
}
#[test]
fn decstr_turns_autowrap_back_on() {
let mut t = Engine::new(10, 2);
t.feed(b"\x1b[?7l"); t.feed(b"\x1b[!p"); t.feed(b"\x1b[?7$p"); assert_eq!(t.drain_replies(), b"\x1b[?7;1$y"); }
#[test]
fn decstr_keeps_the_active_cursor_position() {
let mut t = Engine::new(10, 2);
t.feed(b"hi"); t.feed(b"\x1b[!p"); t.feed(b"X"); assert_eq!(t.grid().cell(0, 2).c(), 'X');
}
#[test]
fn ris_returns_from_alt_screen_to_primary() {
let mut t = Engine::new(4, 2);
t.feed(b"\x1b[?1049h"); t.feed(b"\x1bc"); t.feed(b"a\r\nb\r\nc\r\nd"); assert!(
t.scrollback_len() > 0,
"RIS must return to the primary screen"
);
}
#[test]
fn decstr_resets_insert_mode_to_replace() {
let mut t = Engine::new(5, 1);
t.feed(b"abc\x1b[1;1H");
t.feed(b"\x1b[4h"); t.feed(b"\x1b[!p"); t.feed(b"X");
assert_eq!(t.grid().cell(0, 1).c(), 'b'); }