use std::collections::HashMap;
use std::time::{Duration, Instant};
use ratatui::widgets::ListState;
use ollama_rs::Ollama;
use lazyllama::app::App;
fn create_test_app() -> App {
App {
models: vec!["test_model_1".to_string(), "test_model_2".to_string()],
list_state: {
let mut state = ListState::default();
state.select(Some(0));
state
},
input: String::new(),
cursor_pos: 0,
selection_start: None,
history: String::new(),
model_inputs: HashMap::new(),
model_cursors: HashMap::new(),
model_selections: HashMap::new(),
model_histories: HashMap::new(),
model_scrolls: HashMap::new(),
scroll: 0,
input_scroll: 0,
autoscroll: true,
is_loading: false,
ollama: Ollama::default(),
start_time: Instant::now(),
last_cursor_blink: Instant::now(),
cursor_visible: true,
debug_keys: false,
debug_last_key: None,
render_count: 0,
settings: lazyllama::app::Settings::default(),
show_settings_dialog: false,
settings_selection: 0,
}
}
#[test]
fn test_insert_char() {
let mut app = create_test_app();
app.insert_char('H');
assert_eq!(app.input, "H");
assert_eq!(app.cursor_pos, 1);
app.insert_char('e');
assert_eq!(app.input, "He");
assert_eq!(app.cursor_pos, 2);
app.insert_char('ö');
assert_eq!(app.input, "Heö");
assert_eq!(app.cursor_pos, 3);
}
#[test]
fn test_backspace() {
let mut app = create_test_app();
app.input = "Hello".to_string();
app.cursor_pos = 5;
app.backspace();
assert_eq!(app.input, "Hell");
assert_eq!(app.cursor_pos, 4);
app.cursor_pos = 0;
app.backspace();
assert_eq!(app.input, "Hell");
assert_eq!(app.cursor_pos, 0);
}
#[test]
fn test_delete_forward() {
let mut app = create_test_app();
app.input = "Hello".to_string();
app.cursor_pos = 2;
app.delete_forward();
assert_eq!(app.input, "Helo");
assert_eq!(app.cursor_pos, 2);
app.cursor_pos = 4;
app.delete_forward();
assert_eq!(app.input, "Helo");
assert_eq!(app.cursor_pos, 4);
}
#[test]
fn test_move_cursor_left() {
let mut app = create_test_app();
app.input = "Test".to_string();
app.cursor_pos = 2;
app.move_cursor_left();
assert_eq!(app.cursor_pos, 1);
app.cursor_pos = 0;
app.move_cursor_left();
assert_eq!(app.cursor_pos, 0);
}
#[test]
fn test_move_cursor_right() {
let mut app = create_test_app();
app.input = "Test".to_string();
app.cursor_pos = 2;
app.move_cursor_right();
assert_eq!(app.cursor_pos, 3);
app.cursor_pos = 4;
app.move_cursor_right();
assert_eq!(app.cursor_pos, 4);
}
#[test]
fn test_move_cursor_home_end() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 5;
app.move_cursor_home();
assert_eq!(app.cursor_pos, 0);
app.move_cursor_end();
assert_eq!(app.cursor_pos, 11);
}
#[test]
fn test_word_navigation() {
let mut app = create_test_app();
app.input = "Hello World Test".to_string();
app.cursor_pos = 16;
app.move_cursor_word_left();
assert_eq!(app.cursor_pos, 12);
app.move_cursor_word_left();
assert_eq!(app.cursor_pos, 6);
app.move_cursor_word_left();
assert_eq!(app.cursor_pos, 0);
app.move_cursor_word_right();
assert_eq!(app.cursor_pos, 5);
app.move_cursor_word_right();
assert_eq!(app.cursor_pos, 11);
app.move_cursor_word_right();
assert_eq!(app.cursor_pos, 16); }
#[test]
fn test_delete_word_left() {
let mut app = create_test_app();
app.input = "Hello World Test".to_string();
app.cursor_pos = 16;
app.delete_word_left();
assert_eq!(app.input, "Hello World ");
assert_eq!(app.cursor_pos, 12);
app.delete_word_left();
assert_eq!(app.input, "Hello ");
assert_eq!(app.cursor_pos, 6);
}
#[test]
fn test_delete_word_right() {
let mut app = create_test_app();
app.input = "Hello World Test".to_string();
app.cursor_pos = 0;
app.delete_word_right();
assert_eq!(app.input, " World Test");
assert_eq!(app.cursor_pos, 0);
app.delete_word_right();
assert_eq!(app.input, " Test");
assert_eq!(app.cursor_pos, 0);
}
#[test]
fn test_is_word_char() {
assert!(App::is_word_char('a'));
assert!(App::is_word_char('Z'));
assert!(App::is_word_char('5'));
assert!(App::is_word_char('_'));
assert!(!App::is_word_char(' '));
assert!(!App::is_word_char('.'));
assert!(!App::is_word_char('-'));
}
#[test]
fn test_model_selection_next() {
let mut app = create_test_app();
app.models = vec!["model1".to_string(), "model2".to_string(), "model3".to_string()];
app.list_state.select(Some(0));
app.select_next_model();
assert_eq!(app.list_state.selected(), Some(1));
app.select_next_model();
assert_eq!(app.list_state.selected(), Some(2));
app.select_next_model();
assert_eq!(app.list_state.selected(), Some(0));
}
#[test]
fn test_model_selection_previous() {
let mut app = create_test_app();
app.models = vec!["model1".to_string(), "model2".to_string(), "model3".to_string()];
app.list_state.select(Some(2));
app.select_previous_model();
assert_eq!(app.list_state.selected(), Some(1));
app.select_previous_model();
assert_eq!(app.list_state.selected(), Some(0));
app.select_previous_model();
assert_eq!(app.list_state.selected(), Some(2));
}
#[test]
fn test_model_buffer_save_load() {
let mut app = create_test_app();
app.models = vec!["model1".to_string(), "model2".to_string()];
app.list_state.select(Some(0));
app.input = "Test input".to_string();
app.cursor_pos = 5;
app.history = "Test history".to_string();
app.scroll = 10;
app.save_current_model_buffers();
assert_eq!(app.model_inputs.get("model1"), Some(&"Test input".to_string()));
assert_eq!(app.model_cursors.get("model1"), Some(&5));
assert_eq!(app.model_histories.get("model1"), Some(&"Test history".to_string()));
assert_eq!(app.model_scrolls.get("model1"), Some(&10));
app.list_state.select(Some(1));
app.input = "Different input".to_string();
app.cursor_pos = 8;
app.history = "Different history".to_string();
app.scroll = 5;
app.list_state.select(Some(0));
app.load_current_model_buffers();
assert_eq!(app.input, "Test input");
assert_eq!(app.cursor_pos, 5);
assert_eq!(app.history, "Test history");
assert_eq!(app.scroll, 10);
}
#[test]
fn test_cursor_blink_timing() {
let mut app = create_test_app();
assert!(app.cursor_visible);
assert!(!app.update_cursor_blink());
assert!(app.cursor_visible);
app.last_cursor_blink = Instant::now() - Duration::from_millis(600);
assert!(app.update_cursor_blink());
assert!(!app.cursor_visible);
app.reset_cursor_blink();
assert!(app.cursor_visible);
}
#[test]
fn test_char_index_to_byte_index() {
let mut app = create_test_app();
app.input = "Hëllö Wörld".to_string();
assert_eq!(app.char_index_to_byte_index(0), 0); assert_eq!(app.char_index_to_byte_index(1), 1); assert_eq!(app.char_index_to_byte_index(2), 3); assert_eq!(app.char_index_to_byte_index(11), app.input.len()); }
#[test]
fn test_cursor_clamp() {
let mut app = create_test_app();
app.input = "Test".to_string();
app.cursor_pos = 10;
app.clamp_cursor();
assert_eq!(app.cursor_pos, 4); }
#[test]
fn test_empty_model_list_handling() {
let mut app = create_test_app();
app.models.clear();
app.list_state.select(None);
app.select_next_model();
app.select_previous_model();
app.save_current_model_buffers();
app.load_current_model_buffers();
assert_eq!(app.models.len(), 0);
}
#[test]
fn test_unicode_text_editing() {
let mut app = create_test_app();
app.insert_char('🦀'); app.insert_char('ü'); app.insert_char('A');
assert_eq!(app.input, "🦀üA");
assert_eq!(app.cursor_pos, 3);
app.move_cursor_left();
app.delete_forward();
assert_eq!(app.input, "🦀ü");
assert_eq!(app.cursor_pos, 2);
}
#[test]
fn test_clear_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 5;
app.selection_start = Some(0);
app.clear_selection();
assert_eq!(app.selection_start, None);
assert_eq!(app.cursor_pos, 5);
app.clear_selection();
assert_eq!(app.selection_start, None);
}
#[test]
fn test_get_selection_range() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
assert_eq!(app.get_selection_range(), None);
app.selection_start = Some(0);
app.cursor_pos = 5;
assert_eq!(app.get_selection_range(), Some((0, 5)));
app.selection_start = Some(8);
app.cursor_pos = 3;
assert_eq!(app.get_selection_range(), Some((3, 8)));
app.selection_start = Some(5);
app.cursor_pos = 5;
assert_eq!(app.get_selection_range(), Some((5, 5)));
}
#[test]
fn test_get_selected_text() {
let mut app = create_test_app();
app.input = "Hello 🦀 World".to_string();
assert_eq!(app.get_selected_text(), None);
app.selection_start = Some(0);
app.cursor_pos = 5;
assert_eq!(app.get_selected_text(), Some("Hello".to_string()));
app.selection_start = Some(6);
app.cursor_pos = 7;
assert_eq!(app.get_selected_text(), Some("🦀".to_string()));
app.selection_start = Some(13);
app.cursor_pos = 8;
assert_eq!(app.get_selected_text(), Some("World".to_string()));
}
#[test]
fn test_move_cursor_left_with_selection() {
let mut app = create_test_app();
app.input = "Hello".to_string();
app.cursor_pos = 5;
app.move_cursor_left_with_selection();
assert_eq!(app.selection_start, Some(5));
assert_eq!(app.cursor_pos, 4);
app.move_cursor_left_with_selection();
assert_eq!(app.selection_start, Some(5));
assert_eq!(app.cursor_pos, 3);
assert_eq!(app.get_selected_text(), Some("lo".to_string()));
app.cursor_pos = 0;
app.move_cursor_left_with_selection();
assert_eq!(app.cursor_pos, 0);
}
#[test]
fn test_move_cursor_right_with_selection() {
let mut app = create_test_app();
app.input = "Hello".to_string();
app.cursor_pos = 0;
app.move_cursor_right_with_selection();
assert_eq!(app.selection_start, Some(0));
assert_eq!(app.cursor_pos, 1);
app.move_cursor_right_with_selection();
assert_eq!(app.selection_start, Some(0));
assert_eq!(app.cursor_pos, 2);
assert_eq!(app.get_selected_text(), Some("He".to_string()));
app.cursor_pos = 5;
app.move_cursor_right_with_selection();
assert_eq!(app.cursor_pos, 5);
}
#[test]
fn test_move_cursor_word_left_with_selection() {
let mut app = create_test_app();
app.input = "Hello World Test".to_string();
app.cursor_pos = 16;
app.move_cursor_word_left_with_selection();
assert_eq!(app.cursor_pos, 12); assert_eq!(app.get_selected_text(), Some("Test".to_string()));
app.move_cursor_word_left_with_selection();
assert_eq!(app.cursor_pos, 6); assert_eq!(app.get_selected_text(), Some("World Test".to_string()));
}
#[test]
fn test_move_cursor_word_right_with_selection() {
let mut app = create_test_app();
app.input = "Hello World Test".to_string();
app.cursor_pos = 0;
app.move_cursor_word_right_with_selection();
assert_eq!(app.cursor_pos, 5); assert_eq!(app.get_selected_text(), Some("Hello".to_string()));
app.move_cursor_word_right_with_selection();
assert_eq!(app.cursor_pos, 11); assert_eq!(app.get_selected_text(), Some("Hello World".to_string()));
}
#[test]
fn test_move_cursor_home_with_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 6;
app.move_cursor_home_with_selection();
assert_eq!(app.cursor_pos, 0);
assert_eq!(app.get_selected_text(), Some("Hello ".to_string()));
app.move_cursor_home_with_selection();
assert_eq!(app.cursor_pos, 0);
}
#[test]
fn test_move_cursor_end_with_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 5;
app.move_cursor_end_with_selection();
assert_eq!(app.cursor_pos, 11);
assert_eq!(app.get_selected_text(), Some(" World".to_string()));
app.move_cursor_end_with_selection();
assert_eq!(app.cursor_pos, 11);
}
#[test]
fn test_insert_text_at_cursor() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 6;
app.insert_text_at_cursor("Beautiful ");
assert_eq!(app.input, "Hello Beautiful World");
assert_eq!(app.cursor_pos, 16);
app.input = "Hello World".to_string();
app.cursor_pos = 11;
app.selection_start = Some(6);
app.insert_text_at_cursor("Rust");
assert_eq!(app.input, "Hello Rust");
assert_eq!(app.cursor_pos, 10);
assert_eq!(app.selection_start, None);
}
#[test]
fn test_typing_clears_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 11;
app.selection_start = Some(6);
app.insert_char('!');
assert_eq!(app.input, "Hello !");
assert_eq!(app.cursor_pos, 7);
assert_eq!(app.selection_start, None);
}
#[test]
fn test_movement_clears_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 11;
app.selection_start = Some(6);
app.move_cursor_left();
assert_eq!(app.selection_start, None);
assert_eq!(app.cursor_pos, 10);
app.selection_start = Some(5);
app.move_cursor_word_left();
assert_eq!(app.selection_start, None);
app.selection_start = Some(5);
app.move_cursor_home();
assert_eq!(app.selection_start, None);
}
#[test]
fn test_copy_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
let result = app.copy_selection();
assert!(result.is_err());
app.cursor_pos = 5;
app.selection_start = Some(0);
let result = app.copy_selection();
match result {
Ok(_) => {
assert_eq!(app.selection_start, Some(0));
assert_eq!(app.cursor_pos, 5);
}
Err(_) => {
}
}
}
#[test]
fn test_paste_from_clipboard() {
let mut app = create_test_app();
app.input = "Hello".to_string();
app.cursor_pos = 5;
let result = app.paste_from_clipboard();
match result {
Ok(_) => {
assert!(app.cursor_pos >= 5);
}
Err(_) => {
}
}
}
#[test]
fn test_bidirectional_selection() {
let mut app = create_test_app();
app.input = "Hello World".to_string();
app.cursor_pos = 0;
app.selection_start = None;
app.move_cursor_right_with_selection();
app.move_cursor_right_with_selection();
app.move_cursor_right_with_selection();
let forward_text = app.get_selected_text();
app.cursor_pos = 3;
app.selection_start = None;
app.move_cursor_left_with_selection();
app.move_cursor_left_with_selection();
app.move_cursor_left_with_selection();
let backward_text = app.get_selected_text();
assert_eq!(forward_text, backward_text);
assert_eq!(forward_text, Some("Hel".to_string()));
}