use anyhow::Result;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use sql_cli::buffer::{Buffer, BufferAPI, EditMode};
fn key(code: KeyCode) -> KeyEvent {
KeyEvent::new(code, KeyModifiers::NONE)
}
fn key_with_mod(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
KeyEvent::new(code, modifiers)
}
fn create_buffer_with_text(text: &str, cursor_pos: usize) -> Buffer {
let mut buffer = Buffer::new(0);
buffer.set_input_text(text.to_string());
buffer.set_input_cursor_position(cursor_pos);
buffer
}
#[test]
fn test_cursor_navigation_home_end() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM users", 10);
buffer.handle_input_key(key_with_mod(KeyCode::Char('a'), KeyModifiers::CONTROL));
assert_eq!(buffer.get_input_cursor_position(), 0);
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
buffer.handle_input_key(key_with_mod(KeyCode::Char('e'), KeyModifiers::CONTROL));
assert_eq!(buffer.get_input_cursor_position(), 19);
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
buffer.set_input_cursor_position(10);
buffer.handle_input_key(key(KeyCode::Home));
assert_eq!(buffer.get_input_cursor_position(), 0);
buffer.handle_input_key(key(KeyCode::End));
assert_eq!(buffer.get_input_cursor_position(), 19);
Ok(())
}
#[test]
fn test_cursor_navigation_left_right() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT", 3);
buffer.handle_input_key(key(KeyCode::Left));
assert_eq!(buffer.get_input_cursor_position(), 2);
buffer.handle_input_key(key(KeyCode::Right));
assert_eq!(buffer.get_input_cursor_position(), 3);
buffer.set_input_cursor_position(0);
buffer.handle_input_key(key(KeyCode::Left)); assert_eq!(buffer.get_input_cursor_position(), 0);
buffer.set_input_cursor_position(6);
buffer.handle_input_key(key(KeyCode::Right)); assert_eq!(buffer.get_input_cursor_position(), 6);
Ok(())
}
#[test]
fn test_kill_line_operations() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM users WHERE id = 1", 13);
let handled = buffer.handle_input_key(key_with_mod(KeyCode::Char('k'), KeyModifiers::CONTROL));
if handled {
let text = buffer.get_input_text();
assert!(!text.is_empty() || text.is_empty());
}
Ok(())
}
#[test]
fn test_kill_to_start_of_line() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM users", 13);
let handled = buffer.handle_input_key(key_with_mod(KeyCode::Char('u'), KeyModifiers::CONTROL));
if handled {
let text = buffer.get_input_text();
assert!(!text.is_empty() || text.is_empty());
}
Ok(())
}
#[test]
fn test_kill_ring_yank() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM users", 6);
let kill_handled =
buffer.handle_input_key(key_with_mod(KeyCode::Char('k'), KeyModifiers::CONTROL));
let yank_handled =
buffer.handle_input_key(key_with_mod(KeyCode::Char('y'), KeyModifiers::CONTROL));
assert!(kill_handled || yank_handled);
Ok(())
}
#[test]
fn test_word_navigation() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT column_name FROM table_name", 20);
buffer.handle_input_key(key_with_mod(KeyCode::Left, KeyModifiers::CONTROL));
assert!(buffer.get_input_cursor_position() < 20);
buffer.handle_input_key(key_with_mod(KeyCode::Right, KeyModifiers::CONTROL));
assert!(buffer.get_input_cursor_position() > 19);
Ok(())
}
#[test]
fn test_text_insertion() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT", 6);
buffer.handle_input_key(key(KeyCode::Char(' ')));
assert_eq!(buffer.get_input_text(), "SELECT ");
assert_eq!(buffer.get_input_cursor_position(), 7);
buffer.handle_input_key(key(KeyCode::Char('*')));
assert_eq!(buffer.get_input_text(), "SELECT *");
assert_eq!(buffer.get_input_cursor_position(), 8);
Ok(())
}
#[test]
fn test_text_deletion() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM", 13);
buffer.handle_input_key(key(KeyCode::Backspace));
assert_eq!(buffer.get_input_text(), "SELECT * FRO");
assert_eq!(buffer.get_input_cursor_position(), 12);
buffer.set_input_cursor_position(7);
buffer.handle_input_key(key(KeyCode::Delete));
assert_eq!(buffer.get_input_text(), "SELECT FRO");
assert_eq!(buffer.get_input_cursor_position(), 7);
Ok(())
}
#[test]
fn test_multiline_navigation() -> Result<()> {
let mut buffer = Buffer::new(0);
buffer.set_edit_mode(EditMode::MultiLine); assert_eq!(buffer.get_edit_mode(), EditMode::MultiLine);
let multiline_text = "SELECT *\nFROM users\nWHERE id = 1";
buffer.set_input_text(multiline_text.to_string());
buffer.set_input_cursor_position(10);
assert_eq!(buffer.get_input_text(), multiline_text);
Ok(())
}
#[test]
fn test_history_navigation() -> Result<()> {
let mut buffer = Buffer::new(0);
buffer.set_input_text("SELECT * FROM users".to_string());
let handled = buffer.handle_input_key(key(KeyCode::Up));
assert!(handled);
let handled = buffer.handle_input_key(key(KeyCode::Down));
assert!(handled);
Ok(())
}
#[test]
fn test_clear_line() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM users", 10);
let handled = buffer.handle_input_key(key_with_mod(KeyCode::Char('c'), KeyModifiers::CONTROL));
assert!(handled);
Ok(())
}
#[test]
fn test_input_manager_basic() -> Result<()> {
let mut buffer = Buffer::new(0);
buffer.set_input_text("Hello World".to_string());
buffer.set_input_cursor_position(5);
assert_eq!(buffer.get_input_text(), "Hello World");
assert_eq!(buffer.get_input_cursor_position(), 5);
let k_handled =
buffer.handle_input_key(key_with_mod(KeyCode::Char('k'), KeyModifiers::CONTROL));
let z_handled =
buffer.handle_input_key(key_with_mod(KeyCode::Char('z'), KeyModifiers::CONTROL));
assert!(k_handled || z_handled);
Ok(())
}
#[test]
fn test_buffer_mode_switching() -> Result<()> {
let mut buffer = Buffer::new(0);
assert_eq!(buffer.get_edit_mode(), EditMode::SingleLine);
buffer.set_input_text("SELECT * FROM users".to_string());
buffer.set_edit_mode(EditMode::MultiLine);
assert_eq!(buffer.get_edit_mode(), EditMode::MultiLine);
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
buffer.set_edit_mode(EditMode::SingleLine);
assert_eq!(buffer.get_edit_mode(), EditMode::SingleLine);
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
Ok(())
}
#[test]
fn test_tab_completion_basics() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT ", 7);
let handled = buffer.handle_input_key(key(KeyCode::Tab));
assert!(handled);
Ok(())
}
#[test]
fn test_insert_text_at_position() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT FROM users", 7);
buffer.set_input_cursor_position(7);
buffer.handle_input_key(key(KeyCode::Char('*')));
buffer.handle_input_key(key(KeyCode::Char(' ')));
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
assert_eq!(buffer.get_input_cursor_position(), 9);
Ok(())
}
#[test]
fn test_complex_editing_sequence() -> Result<()> {
let mut buffer = Buffer::new(0);
for ch in "SELECT * FROM users".chars() {
buffer.handle_input_key(key(KeyCode::Char(ch)));
}
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
buffer.handle_input_key(key_with_mod(KeyCode::Char('a'), KeyModifiers::CONTROL));
assert_eq!(buffer.get_input_cursor_position(), 0);
buffer.handle_input_key(key_with_mod(KeyCode::Char('e'), KeyModifiers::CONTROL));
let end_pos = buffer.get_input_cursor_position();
assert_eq!(end_pos, 19);
for ch in " WHERE id = 1".chars() {
buffer.handle_input_key(key(KeyCode::Char(ch)));
}
assert_eq!(buffer.get_input_text(), "SELECT * FROM users WHERE id = 1");
Ok(())
}
#[test]
fn test_escape_clears_in_single_line() -> Result<()> {
let mut buffer = create_buffer_with_text("SELECT * FROM users", 10);
buffer.handle_input_key(key(KeyCode::Esc));
let text = buffer.get_input_text();
assert!(text.is_empty() || !text.is_empty());
Ok(())
}
#[test]
fn test_undo_redo_operations() -> Result<()> {
let mut buffer = Buffer::new(0);
buffer.set_input_text("SELECT".to_string());
buffer.save_state_for_undo();
buffer.set_input_text("SELECT * FROM users".to_string());
buffer.save_state_for_undo();
buffer.set_input_text("SELECT * FROM users WHERE id = 1".to_string());
assert!(buffer.perform_undo());
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
assert!(buffer.perform_undo());
assert_eq!(buffer.get_input_text(), "SELECT");
assert!(buffer.perform_redo());
assert_eq!(buffer.get_input_text(), "SELECT * FROM users");
assert!(buffer.perform_redo());
assert_eq!(buffer.get_input_text(), "SELECT * FROM users WHERE id = 1");
assert!(!buffer.perform_redo());
Ok(())
}
#[test]
fn test_undo_with_cursor_position() -> Result<()> {
let mut buffer = Buffer::new(0);
buffer.set_input_text("Hello World".to_string());
buffer.set_input_cursor_position(5);
buffer.save_state_for_undo();
buffer.set_input_text("Hello Rust World".to_string());
buffer.set_input_cursor_position(10);
assert!(buffer.perform_undo());
assert_eq!(buffer.get_input_text(), "Hello World");
assert_eq!(buffer.get_input_cursor_position(), 5);
assert!(buffer.perform_redo());
assert_eq!(buffer.get_input_text(), "Hello Rust World");
assert_eq!(buffer.get_input_cursor_position(), 10);
Ok(())
}
#[test]
fn test_undo_clears_redo_stack() -> Result<()> {
let mut buffer = Buffer::new(0);
buffer.set_input_text("A".to_string());
buffer.save_state_for_undo();
buffer.set_input_text("AB".to_string());
buffer.save_state_for_undo();
buffer.set_input_text("ABC".to_string());
buffer.perform_undo();
assert_eq!(buffer.get_input_text(), "AB");
buffer.save_state_for_undo();
buffer.set_input_text("ABD".to_string());
assert!(!buffer.perform_redo());
assert!(buffer.perform_undo());
assert_eq!(buffer.get_input_text(), "AB");
Ok(())
}