use par_term::config::OptionKeyMode;
use par_term::input::InputHandler;
#[test]
fn test_input_handler_creation() {
let _handler = InputHandler::new();
}
#[test]
fn test_input_handler_default() {
let _handler = InputHandler::default();
}
#[test]
fn test_option_key_mode_default() {
let handler = InputHandler::new();
assert_eq!(handler.left_option_key_mode, OptionKeyMode::Esc);
assert_eq!(handler.right_option_key_mode, OptionKeyMode::Esc);
}
#[test]
fn test_update_option_key_modes() {
let mut handler = InputHandler::new();
handler.update_option_key_modes(OptionKeyMode::Normal, OptionKeyMode::Meta);
assert_eq!(handler.left_option_key_mode, OptionKeyMode::Normal);
assert_eq!(handler.right_option_key_mode, OptionKeyMode::Meta);
}
#[test]
fn test_option_key_mode_variants() {
assert_ne!(OptionKeyMode::Normal, OptionKeyMode::Meta);
assert_ne!(OptionKeyMode::Normal, OptionKeyMode::Esc);
assert_ne!(OptionKeyMode::Meta, OptionKeyMode::Esc);
assert_eq!(OptionKeyMode::Normal, OptionKeyMode::Normal);
assert_eq!(OptionKeyMode::Meta, OptionKeyMode::Meta);
assert_eq!(OptionKeyMode::Esc, OptionKeyMode::Esc);
}
#[test]
fn test_option_key_mode_serde() {
let modes = [
(OptionKeyMode::Normal, "normal"),
(OptionKeyMode::Meta, "meta"),
(OptionKeyMode::Esc, "esc"),
];
for (mode, expected_yaml) in modes {
let yaml = serde_yaml_ng::to_string(&mode).unwrap();
assert_eq!(yaml.trim(), expected_yaml);
let deserialized: OptionKeyMode = serde_yaml_ng::from_str(expected_yaml).unwrap();
assert_eq!(deserialized, mode);
}
}
use winit::event::{ElementState, KeyEvent, Modifiers};
use winit::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey, PhysicalKey};
fn make_key_event(logical_key: Key, physical_key: PhysicalKey) -> KeyEvent {
unsafe {
let mut event: KeyEvent = std::mem::zeroed();
std::ptr::write(&mut event.physical_key, physical_key);
std::ptr::write(&mut event.logical_key, logical_key);
std::ptr::write(&mut event.text, None);
std::ptr::write(&mut event.location, KeyLocation::Standard);
std::ptr::write(&mut event.state, ElementState::Pressed);
std::ptr::write(&mut event.repeat, false);
event
}
}
#[test]
fn test_tab_sends_horizontal_tab() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::default());
let event = make_key_event(Key::Named(NamedKey::Tab), PhysicalKey::Code(KeyCode::Tab));
let result = handler.handle_key_event(event);
assert_eq!(result, Some(vec![b'\t']), "Tab should send HT (0x09)");
}
#[test]
fn test_shift_tab_sends_csi_z() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = make_key_event(Key::Named(NamedKey::Tab), PhysicalKey::Code(KeyCode::Tab));
let result = handler.handle_key_event(event);
assert_eq!(
result,
Some(b"\x1b[Z".to_vec()),
"Shift+Tab should send CSI Z (reverse tab / backtab)"
);
}
#[test]
fn test_enter_sends_cr() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::default());
let event = make_key_event(
Key::Named(NamedKey::Enter),
PhysicalKey::Code(KeyCode::Enter),
);
let result = handler.handle_key_event(event);
assert_eq!(result, Some(vec![b'\r']), "Enter should send CR (0x0d)");
}
#[test]
fn test_shift_enter_sends_lf() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = make_key_event(
Key::Named(NamedKey::Enter),
PhysicalKey::Code(KeyCode::Enter),
);
let result = handler.handle_key_event(event);
assert_eq!(
result,
Some(vec![b'\n']),
"Shift+Enter should send LF (0x0a)"
);
}
#[test]
fn test_escape_sends_escape() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::default());
let event = make_key_event(
Key::Named(NamedKey::Escape),
PhysicalKey::Code(KeyCode::Escape),
);
let result = handler.handle_key_event(event);
assert_eq!(result, Some(vec![0x1b]), "Escape should send ESC (0x1b)");
}
fn char_event(ch: &str, code: KeyCode) -> KeyEvent {
make_key_event(Key::Character(ch.into()), PhysicalKey::Code(code))
}
#[test]
fn test_shift_digit_mode2_sends_shifted_char() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = char_event("!", KeyCode::Digit1);
let result = handler.handle_key_event_with_mode(event, 2, false);
assert_eq!(
result,
Some(b"!".to_vec()),
"Shift+1 in mode 2 must pass through the OS-resolved shifted char, not CSI 27;2;49~"
);
}
#[test]
fn test_shift_symbol_mode2_sends_shifted_char() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = char_event("{", KeyCode::BracketLeft);
let result = handler.handle_key_event_with_mode(event, 2, false);
assert_eq!(
result,
Some(b"{".to_vec()),
"Shift+[ in mode 2 must pass through '{{', not CSI 27;2;91~"
);
}
#[test]
fn test_shift_letter_mode2_sends_uppercase() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = char_event("A", KeyCode::KeyA);
let result = handler.handle_key_event_with_mode(event, 2, false);
assert_eq!(
result,
Some(b"A".to_vec()),
"Shift+a in mode 2 must send 'A'"
);
}
#[test]
fn test_shift_digit_mode1_sends_shifted_char() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = char_event("!", KeyCode::Digit1);
let result = handler.handle_key_event_with_mode(event, 1, false);
assert_eq!(result, Some(b"!".to_vec()));
}
#[test]
fn test_shift_digit_mode0_sends_shifted_char() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::SHIFT));
let event = char_event("!", KeyCode::Digit1);
let result = handler.handle_key_event_with_mode(event, 0, false);
assert_eq!(result, Some(b"!".to_vec()));
}
#[test]
fn test_ctrl_digit_mode2_still_encodes() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(ModifiersState::CONTROL));
let event = char_event("1", KeyCode::Digit1);
let result = handler.handle_key_event_with_mode(event, 2, false);
assert_eq!(
result,
Some(b"\x1b[27;5;49~".to_vec()),
"Ctrl+1 in mode 2 must still emit CSI 27;5;49~"
);
}
#[test]
fn test_ctrl_shift_digit_mode2_still_encodes() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(
ModifiersState::CONTROL | ModifiersState::SHIFT,
));
let event = char_event("!", KeyCode::Digit1);
let result = handler.handle_key_event_with_mode(event, 2, false);
assert_eq!(
result,
Some(b"\x1b[27;6;49~".to_vec()),
"Ctrl+Shift+1 in mode 2 must still emit a modifyOtherKeys sequence"
);
}
#[test]
fn test_ctrl_alt_letter_mode0_sends_esc_prefixed_control_byte() {
let mut handler = InputHandler::new();
handler.update_modifiers(Modifiers::from(
ModifiersState::CONTROL | ModifiersState::ALT,
));
let event = char_event("p", KeyCode::KeyP);
let result = handler.handle_key_event_with_mode(event, 0, false);
assert_eq!(
result,
Some(b"\x1b\x10".to_vec()),
"Ctrl+Alt+P in mode 0 must send ESC-prefixed Ctrl+P, not collapse to plain Ctrl+P"
);
}