use justerm_core::Engine;
#[test]
fn vt52_cursor_up() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[6;1H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bA"); assert_eq!(t.cursor().row, 4);
}
#[test]
fn vt52_exit_returns_to_ansi() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[6;1H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bA"); assert_eq!(t.cursor().row, 4);
t.feed(b"\x1b<"); t.feed(b"\x1bA"); assert_eq!(t.cursor().row, 4, "ESC A must be inert once back in ANSI");
}
#[test]
fn vt52_cursor_down_right_left() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[6;6H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bB"); assert_eq!((t.cursor().row, t.cursor().col), (6, 5));
t.feed(b"\x1bC"); assert_eq!((t.cursor().row, t.cursor().col), (6, 6));
t.feed(b"\x1bD"); assert_eq!((t.cursor().row, t.cursor().col), (6, 5));
}
#[test]
fn vt52_home() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[6;6H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bH"); assert_eq!((t.cursor().row, t.cursor().col), (0, 0));
}
#[test]
fn vt52_reverse_line_feed() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[4;1H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bI"); assert_eq!(t.cursor().row, 2);
}
#[test]
fn vt52_erase_to_end_of_line() {
let mut t = Engine::new(80, 24);
t.feed(b"hello"); t.feed(b"\x1b[1;3H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bK"); assert_eq!(t.grid().cell(0, 1).c(), 'e', "before cursor is untouched");
assert_eq!(t.grid().cell(0, 2).c(), ' ', "from cursor is cleared");
assert_eq!(t.grid().cell(0, 4).c(), ' ');
}
#[test]
fn vt52_erase_to_end_of_screen() {
let mut t = Engine::new(80, 24);
t.feed(b"a\r\nb\r\nc"); t.feed(b"\x1b[2;1H"); t.feed(b"\x1b[?2l"); t.feed(b"\x1bJ"); assert_eq!(t.grid().cell(0, 0).c(), 'a', "above cursor untouched");
assert_eq!(t.grid().cell(1, 0).c(), ' ', "from cursor cleared");
assert_eq!(t.grid().cell(2, 0).c(), ' ', "below cursor cleared");
}
#[test]
fn vt52_direct_cursor_address() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l"); t.feed(b"\x1bY\x22\x24");
assert_eq!((t.cursor().row, t.cursor().col), (2, 4));
assert_eq!(
t.grid().cell(0, 0).c(),
' ',
"coords must not reach the screen"
);
}
#[test]
fn vt52_direct_address_split_across_feeds() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l");
t.feed(b"\x1bY"); t.feed(b"\x22"); t.feed(b"\x24"); assert_eq!((t.cursor().row, t.cursor().col), (2, 4));
}
#[test]
fn vt52_identify_replies() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l"); t.feed(b"\x1bZ"); assert_eq!(t.drain_replies(), b"\x1b/Z");
}
#[test]
fn vt52_alternate_keypad() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l"); t.feed(b"\x1b="); t.feed(b"\x1b[?66$p"); assert_eq!(t.drain_replies(), b"\x1b[?66;1$y", "keypad set");
t.feed(b"\x1b>"); t.feed(b"\x1b[?66$p");
assert_eq!(t.drain_replies(), b"\x1b[?66;2$y", "keypad reset");
}
#[test]
fn vt52_graphics_is_a_documented_noop() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l"); t.feed(b"\x1bF"); t.feed(b"q"); assert_eq!(
t.grid().cell(0, 0).c(),
'q',
"graphics mode is not implemented"
);
}
#[test]
fn vt52_decrqm_reports_decanm() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2$p"); assert_eq!(t.drain_replies(), b"\x1b[?2;1$y", "ANSI → set");
t.feed(b"\x1b[?2l"); t.feed(b"\x1b[?2$p");
assert_eq!(t.drain_replies(), b"\x1b[?2;2$y", "VT52 → reset");
}
#[test]
fn vt52_ris_returns_to_ansi() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l"); t.feed(b"\x1bc"); t.feed(b"\x1b[?2$p");
assert_eq!(t.drain_replies(), b"\x1b[?2;1$y", "RIS → ANSI");
t.feed(b"\x1b[6;1H"); t.feed(b"\x1bA"); assert_eq!(t.cursor().row, 5, "ESC A inert after RIS");
}
#[test]
fn vt52_direct_address_is_clamped() {
let mut t = Engine::new(80, 24);
t.feed(b"\x1b[?2l");
t.feed(b"\x1bY~~"); assert_eq!((t.cursor().row, t.cursor().col), (23, 79));
t.feed(b"\x1bY\x20\x20"); assert_eq!((t.cursor().row, t.cursor().col), (0, 0));
}