use super::*;
fn focused_state(value: &str) -> InputFieldState {
InputFieldState::with_value(value)
}
#[test]
fn test_undo_single_insert() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Insert(' '));
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_redo_after_undo() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Insert('!'));
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
InputField::update(&mut state, InputFieldMessage::Redo);
assert_eq!(state.value(), "hello!");
}
#[test]
fn test_undo_empty_stack_no_change() {
let mut state = InputFieldState::with_value("hello");
let output = InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(output, None);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_redo_empty_stack_no_change() {
let mut state = InputFieldState::with_value("hello");
let output = InputField::update(&mut state, InputFieldMessage::Redo);
assert_eq!(output, None);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_grouped_inserts_undo_together() {
let mut state = InputFieldState::new();
for c in "hello".chars() {
InputField::update(&mut state, InputFieldMessage::Insert(c));
}
assert_eq!(state.value(), "hello");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "");
}
#[test]
fn test_whitespace_breaks_insert_group() {
let mut state = InputFieldState::new();
for c in "hi ".chars() {
InputField::update(&mut state, InputFieldMessage::Insert(c));
}
for c in "you".chars() {
InputField::update(&mut state, InputFieldMessage::Insert(c));
}
assert_eq!(state.value(), "hi you");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hi ");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hi");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "");
}
#[test]
fn test_grouped_deletes_undo_together() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Backspace);
InputField::update(&mut state, InputFieldMessage::Backspace);
assert_eq!(state.value(), "hel");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_delete_forward_grouped() {
let mut state = InputFieldState::with_value("hello");
state.set_cursor_position(0);
InputField::update(&mut state, InputFieldMessage::Delete);
InputField::update(&mut state, InputFieldMessage::Delete);
assert_eq!(state.value(), "llo");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_insert_then_delete_separate_groups() {
let mut state = InputFieldState::new();
for c in "hello".chars() {
InputField::update(&mut state, InputFieldMessage::Insert(c));
}
InputField::update(&mut state, InputFieldMessage::Backspace);
assert_eq!(state.value(), "hell");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "");
}
#[test]
fn test_clear_is_own_undo_entry() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Clear);
assert_eq!(state.value(), "");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_set_value_is_own_undo_entry() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::SetValue("world".into()));
assert_eq!(state.value(), "world");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
}
#[test]
fn test_delete_word_back_is_own_undo_entry() {
let mut state = InputFieldState::with_value("hello world");
InputField::update(&mut state, InputFieldMessage::DeleteWordBack);
assert_eq!(state.value(), "hello ");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello world");
}
#[test]
fn test_delete_word_forward_is_own_undo_entry() {
let mut state = InputFieldState::with_value("hello world");
state.set_cursor_position(0);
InputField::update(&mut state, InputFieldMessage::DeleteWordForward);
assert_eq!(state.value(), "world");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello world");
}
#[test]
fn test_undo_restores_cursor_position() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Insert('!'));
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.cursor_byte_offset(), 5);
}
#[test]
fn test_redo_restores_cursor_position() {
let mut state = InputFieldState::new();
for c in "hi".chars() {
InputField::update(&mut state, InputFieldMessage::Insert(c));
}
let cursor_after = state.cursor_byte_offset();
InputField::update(&mut state, InputFieldMessage::Undo);
InputField::update(&mut state, InputFieldMessage::Redo);
assert_eq!(state.cursor_byte_offset(), cursor_after);
}
#[test]
fn test_new_edit_clears_redo() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Insert('!'));
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello");
InputField::update(&mut state, InputFieldMessage::Insert('?'));
let output = InputField::update(&mut state, InputFieldMessage::Redo);
assert_eq!(output, None);
assert_eq!(state.value(), "hello?");
}
#[test]
fn test_ctrl_z_maps_to_undo() {
let state = focused_state("hello");
let msg = InputField::handle_event(
&state,
&Event::ctrl('z'),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(InputFieldMessage::Undo));
}
#[test]
fn test_ctrl_y_maps_to_redo() {
let state = focused_state("hello");
let msg = InputField::handle_event(
&state,
&Event::ctrl('y'),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(InputFieldMessage::Redo));
}
#[test]
fn test_can_undo() {
let mut state = InputFieldState::with_value("hello");
assert!(!state.can_undo());
InputField::update(&mut state, InputFieldMessage::Insert('!'));
assert!(state.can_undo());
InputField::update(&mut state, InputFieldMessage::Undo);
assert!(!state.can_undo());
}
#[test]
fn test_can_redo() {
let mut state = InputFieldState::with_value("hello");
assert!(!state.can_redo());
InputField::update(&mut state, InputFieldMessage::Insert('!'));
InputField::update(&mut state, InputFieldMessage::Undo);
assert!(state.can_redo());
InputField::update(&mut state, InputFieldMessage::Redo);
assert!(!state.can_redo());
}
#[test]
fn test_multiple_undo_redo_cycles() {
let mut state = InputFieldState::new();
InputField::update(&mut state, InputFieldMessage::Insert('a'));
InputField::update(&mut state, InputFieldMessage::Insert(' '));
InputField::update(&mut state, InputFieldMessage::Insert('b'));
assert_eq!(state.value(), "a b");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "a ");
InputField::update(&mut state, InputFieldMessage::Redo);
assert_eq!(state.value(), "a b");
InputField::update(&mut state, InputFieldMessage::Undo);
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "a");
}
#[test]
fn test_clear_history_on_set_value() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Insert('!'));
InputField::update(&mut state, InputFieldMessage::SetValue("new".into()));
assert_eq!(state.value(), "new");
InputField::update(&mut state, InputFieldMessage::Undo);
assert_eq!(state.value(), "hello!");
}
#[test]
fn test_undo_clears_selection() {
let mut state = InputFieldState::with_value("hello");
InputField::update(&mut state, InputFieldMessage::Insert('!'));
InputField::update(&mut state, InputFieldMessage::SelectAll);
assert!(state.has_selection());
InputField::update(&mut state, InputFieldMessage::Undo);
assert!(!state.has_selection());
}