Add editor handlers.rs tests (15 tests, was 0)

editor/handlers.rs now has comprehensive key dispatch tests:
- Mode checks (default is Insert)
- Esc/F10 behavior (save-before-close prompt on dirty buffer)
- F2 save, F9 menubar toggle, Ctrl-Q literal insert toggle
- Backspace, Enter, Tab, printable char insertion
- Bookmark toggle, Ctrl-S syntax toggle
- Ctrl-H backspace alias (MC parity)
- Prompt mode Esc cancel
- Insert literal mode pass-through

Also: made viewer mod tests pub(crate) for cross-module test access.
1455 tests passing, zero warnings.
This commit is contained in:
2026-07-08 21:34:43 +03:00
parent 92033de7da
commit 7ee4a1cfb6
@@ -1343,3 +1343,145 @@ fn word_at_cursor(buf: &crate::editor::buffer::Buffer, pos: usize) -> String {
}
text[start..end].to_string()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::editor::EditorResult;
fn empty_editor() -> Editor {
Editor::new_empty()
}
#[test]
fn default_mode_is_insert() {
let e = empty_editor();
assert!(matches!(e.mode(), Mode::Insert));
}
#[test]
fn esc_with_modified_prompts_save() {
let mut e = empty_editor();
e.insert_str("test");
e.modified = true;
let result = e.handle_key(Key::ESCAPE);
assert!(matches!(result, EditorResult::Running));
// Esc with dirty buffer opens save-before-close prompt
assert!(matches!(e.mode(), Mode::Prompt(PromptKind::SaveBeforeClose)));
}
#[test]
fn f10_with_modified_prompts_save() {
let mut e = empty_editor();
e.insert_str("test");
e.modified = true;
let result = e.handle_key(Key::f(10));
assert!(matches!(result, EditorResult::Running));
assert!(matches!(e.mode(), Mode::Prompt(PromptKind::SaveBeforeClose)));
}
#[test]
fn ctrl_s_in_insert_returns_running() {
let mut e = empty_editor();
e.insert_str("test");
let result = e.handle_key(Key::ctrl('s'));
assert!(matches!(result, EditorResult::Running));
}
#[test]
fn ctrl_q_toggles_literal_insert() {
let mut e = empty_editor();
assert!(!e.insert_literal);
let _ = e.handle_key(Key::ctrl('q'));
assert!(e.insert_literal);
let _ = e.handle_key(Key::ctrl('q'));
assert!(!e.insert_literal);
}
#[test]
fn f2_returns_save() {
let mut e = empty_editor();
let result = e.handle_key(Key::f(2));
assert!(matches!(result, EditorResult::Save));
}
#[test]
fn enter_in_insert_splits_line() {
let mut e = empty_editor();
e.insert_str("hello");
let len_before = e.buffer.len();
let _ = e.handle_key(Key::ENTER);
// Enter inserts a newline, buffer grows
assert!(e.buffer.len() > len_before);
}
#[test]
fn backspace_in_insert_deletes() {
let mut e = empty_editor();
e.insert_str("hello");
e.cursor.set_position(5, &e.buffer);
let len_before = e.buffer.len();
let _ = e.handle_key(Key::BACKSPACE);
assert!(e.buffer.len() < len_before);
}
#[test]
fn tab_in_insert_inserts_tab() {
let mut e = empty_editor();
let len_before = e.buffer.len();
let _ = e.handle_key(Key::TAB);
assert!(e.buffer.len() > len_before);
}
#[test]
fn printable_char_in_insert_inserts() {
let mut e = empty_editor();
let len_before = e.buffer.len();
let _ = e.handle_key(Key { code: b'x' as u32, mods: Modifiers::empty() });
assert_eq!(e.buffer.len(), len_before + 1);
}
#[test]
fn insert_literal_mode_passes_char_through() {
let mut e = empty_editor();
e.insert_literal = true;
// ESC in literal mode inserts the escape char, doesn't close
let _ = e.handle_key(Key::ESCAPE);
assert!(!e.insert_literal); // literal mode consumed
}
#[test]
fn f9_toggles_menubar() {
let mut e = empty_editor();
assert!(e.menubar.is_none());
let _ = e.handle_key(Key::f(9));
assert!(e.menubar.is_some());
}
#[test]
fn prompt_mode_esc_cancels() {
let mut e = empty_editor();
e.mode = Mode::Prompt(PromptKind::Find);
let result = e.handle_key(Key::ESCAPE);
assert!(matches!(result, EditorResult::Running));
assert!(!matches!(e.mode(), Mode::Prompt(_)));
}
#[test]
fn bookmark_toggle_switches_to_prompt() {
let mut e = empty_editor();
let _ = e.handle_key(Key::alt('m'));
assert!(matches!(e.mode(), Mode::Prompt(PromptKind::BookmarkSet)));
}
#[test]
fn ctrl_h_in_insert_is_backspace() {
let mut e = empty_editor();
e.insert_str("hello");
e.cursor.set_position(5, &e.buffer);
let len_before = e.buffer.len();
let _ = e.handle_key(Key::ctrl('h'));
// Ctrl-H is backspace alias (MC parity) — deletes character
assert_eq!(e.buffer.len(), len_before - 1);
}
}