use super::*;
#[test]
fn test_new() {
let state = SelectState::new(vec!["A", "B", "C"]);
assert_eq!(state.options().len(), 3);
assert_eq!(state.selected_index(), None);
assert!(!state.is_open());
}
#[test]
fn test_with_selection() {
let state = SelectState::with_selection(vec!["A", "B", "C"], 1);
assert_eq!(state.selected_index(), Some(1));
assert_eq!(state.selected_value(), Some("B"));
}
#[test]
fn test_with_selection_out_of_bounds() {
let state = SelectState::with_selection(vec!["A", "B"], 5);
assert_eq!(state.selected_index(), None);
}
#[test]
fn test_default() {
let state = SelectState::default();
assert_eq!(state.options().len(), 0);
assert_eq!(state.selected_index(), None);
}
#[test]
fn test_set_options() {
let mut state = SelectState::new(vec!["A", "B"]);
state.set_options(vec!["X", "Y", "Z"]);
assert_eq!(state.options().len(), 3);
assert_eq!(state.options()[0], "X");
}
#[test]
fn test_set_options_resets_invalid_selection() {
let mut state = SelectState::with_selection(vec!["A", "B", "C"], 2);
state.set_options(vec!["X", "Y"]);
assert_eq!(state.selected_index(), None);
}
#[test]
fn test_set_selected() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
state.set_selected(Some(1));
assert_eq!(state.selected_index(), Some(1));
assert_eq!(state.selected_value(), Some("B"));
}
#[test]
fn test_set_selected_out_of_bounds() {
let mut state = SelectState::new(vec!["A", "B"]);
state.set_selected(Some(5));
assert_eq!(state.selected_index(), None);
}
#[test]
fn test_open_close() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
assert!(state.is_open());
Select::update(&mut state, SelectMessage::Close);
assert!(!state.is_open());
}
#[test]
fn test_toggle() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Toggle);
assert!(state.is_open());
Select::update(&mut state, SelectMessage::Toggle);
assert!(!state.is_open());
}
#[test]
fn test_open_empty_options() {
let mut state = SelectState::new(Vec::<String>::new());
Select::update(&mut state, SelectMessage::Open);
assert!(!state.is_open());
}
#[test]
fn test_select_next() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
let output = Select::update(&mut state, SelectMessage::Down);
assert_eq!(output, Some(SelectOutput::SelectionChanged(1)));
assert_eq!(state.highlighted_index, 1);
let output = Select::update(&mut state, SelectMessage::Down);
assert_eq!(output, Some(SelectOutput::SelectionChanged(2)));
assert_eq!(state.highlighted_index, 2);
let output = Select::update(&mut state, SelectMessage::Down);
assert_eq!(output, Some(SelectOutput::SelectionChanged(0)));
assert_eq!(state.highlighted_index, 0);
}
#[test]
fn test_select_previous() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
let output = Select::update(&mut state, SelectMessage::Up);
assert_eq!(output, Some(SelectOutput::SelectionChanged(2)));
assert_eq!(state.highlighted_index, 2);
let output = Select::update(&mut state, SelectMessage::Up);
assert_eq!(output, Some(SelectOutput::SelectionChanged(1)));
assert_eq!(state.highlighted_index, 1);
let output = Select::update(&mut state, SelectMessage::Up);
assert_eq!(output, Some(SelectOutput::SelectionChanged(0)));
assert_eq!(state.highlighted_index, 0);
}
#[test]
fn test_confirm_selection() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
Select::update(&mut state, SelectMessage::Down);
let output = Select::update(&mut state, SelectMessage::Confirm);
assert_eq!(output, Some(SelectOutput::Selected("B".to_string())));
assert_eq!(state.selected_index(), Some(1));
assert!(!state.is_open());
}
#[test]
fn test_confirm_same_selection() {
let mut state = SelectState::with_selection(vec!["A", "B", "C"], 1);
Select::update(&mut state, SelectMessage::Open);
let output = Select::update(&mut state, SelectMessage::Confirm);
assert_eq!(output, Some(SelectOutput::Submitted(1)));
assert!(!state.is_open());
}
#[test]
fn test_confirm_when_closed() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
let output = Select::update(&mut state, SelectMessage::Confirm);
assert_eq!(output, None);
}
#[test]
fn test_init() {
let state = Select::init();
assert_eq!(state.options().len(), 0);
}
#[test]
fn test_view_closed() {
let state = SelectState::new(vec!["Red", "Green", "Blue"]);
let (mut terminal, theme) = crate::component::test_utils::setup_render(30, 10);
terminal
.draw(|frame| {
Select::view(&state, &mut RenderContext::new(frame, frame.area(), &theme));
})
.unwrap();
insta::assert_snapshot!(terminal.backend().to_string());
}
#[test]
fn test_view_open() {
let mut state = SelectState::new(vec!["Red", "Green", "Blue"]);
Select::update(&mut state, SelectMessage::Open);
let (mut terminal, theme) = crate::component::test_utils::setup_render(30, 15);
terminal
.draw(|frame| {
Select::view(&state, &mut RenderContext::new(frame, frame.area(), &theme));
})
.unwrap();
insta::assert_snapshot!(terminal.backend().to_string());
}
#[test]
fn test_view_with_selection() {
let state = SelectState::with_selection(vec!["Small", "Medium", "Large"], 1);
let (mut terminal, theme) = crate::component::test_utils::setup_render(30, 10);
terminal
.draw(|frame| {
Select::view(&state, &mut RenderContext::new(frame, frame.area(), &theme));
})
.unwrap();
insta::assert_snapshot!(terminal.backend().to_string());
}
#[test]
fn test_view_focused() {
let state = SelectState::new(vec!["A", "B"]);
let (mut terminal, theme) = crate::component::test_utils::setup_render(30, 10);
terminal
.draw(|frame| {
Select::view(&state, &mut RenderContext::new(frame, frame.area(), &theme));
})
.unwrap();
insta::assert_snapshot!(terminal.backend().to_string());
}
#[test]
fn test_large_select_navigation() {
let options: Vec<String> = (0..100).map(|i| format!("Option {}", i)).collect();
let mut state = SelectState::new(options);
Select::update(&mut state, SelectMessage::Open);
assert!(state.is_open());
for _ in 0..50 {
Select::update(&mut state, SelectMessage::Down);
}
assert_eq!(state.highlighted_index, 50);
for _ in 0..50 {
Select::update(&mut state, SelectMessage::Down);
}
assert_eq!(state.highlighted_index, 0);
Select::update(&mut state, SelectMessage::Up);
assert_eq!(state.highlighted_index, 99);
let output = Select::update(&mut state, SelectMessage::Confirm);
assert_eq!(
output,
Some(SelectOutput::Selected("Option 99".to_string()))
);
assert_eq!(state.selected_index(), Some(99));
assert!(!state.is_open());
}
use crate::input::{Event, Key};
#[test]
fn test_handle_event_toggle_when_closed() {
let state = SelectState::new(vec!["A", "B", "C"]);
let msg = Select::handle_event(
&state,
&Event::key(Key::Enter),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Toggle));
let msg = Select::handle_event(
&state,
&Event::char(' '),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Toggle));
}
#[test]
fn test_handle_event_confirm_when_open() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
let msg = Select::handle_event(
&state,
&Event::key(Key::Enter),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Confirm));
}
#[test]
fn test_handle_event_close_when_open() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
let msg = Select::handle_event(
&state,
&Event::key(Key::Esc),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Close));
}
#[test]
fn test_handle_event_up_when_open() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
let msg = Select::handle_event(
&state,
&Event::key(Key::Up),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Up));
let msg = Select::handle_event(
&state,
&Event::char('k'),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Up));
}
#[test]
fn test_handle_event_down_when_open() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
let msg = Select::handle_event(
&state,
&Event::key(Key::Down),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Down));
let msg = Select::handle_event(
&state,
&Event::char('j'),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Down));
}
#[test]
fn test_handle_event_ignored_when_unfocused() {
let state = SelectState::new(vec!["A", "B", "C"]);
let msg = Select::handle_event(&state, &Event::key(Key::Enter), &EventContext::default());
assert_eq!(msg, None);
}
#[test]
fn test_handle_event_ignored_when_disabled() {
let state = SelectState::new(vec!["A", "B", "C"]);
let msg = Select::handle_event(
&state,
&Event::key(Key::Enter),
&EventContext::new().focused(true).disabled(true),
);
assert_eq!(msg, None);
}
#[test]
fn test_dispatch_event() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
Select::update(&mut state, SelectMessage::Open);
Select::update(&mut state, SelectMessage::Down);
let output = Select::dispatch_event(
&mut state,
&Event::key(Key::Enter),
&EventContext::new().focused(true),
);
assert_eq!(output, Some(SelectOutput::Selected("B".to_string())));
assert!(!state.is_open());
}
#[test]
fn test_instance_methods() {
let mut state = SelectState::new(vec!["A", "B", "C"]);
let msg = Select::handle_event(
&state,
&Event::key(Key::Enter),
&EventContext::new().focused(true),
);
assert_eq!(msg, Some(SelectMessage::Toggle));
let output = state.update(SelectMessage::Toggle);
assert!(output.is_none()); assert!(state.is_open());
let output = Select::dispatch_event(
&mut state,
&Event::key(Key::Down),
&EventContext::new().focused(true),
);
assert_eq!(output, Some(SelectOutput::SelectionChanged(1)));
}
#[test]
fn test_selected_item() {
let state = SelectState::with_selection(vec!["A", "B", "C"], 1);
assert_eq!(state.selected_item(), Some("B"));
assert_eq!(state.selected_item(), state.selected_value());
}
#[test]
fn test_selected_item_none() {
let state = SelectState::new(vec!["A", "B"]);
assert_eq!(state.selected_item(), None);
}
#[test]
fn test_with_placeholder() {
let state = SelectState::new(vec!["A", "B", "C"]).with_placeholder("Pick one...");
assert_eq!(state.placeholder(), "Pick one...");
}
#[test]
fn test_with_placeholder_chained() {
let state = SelectState::new(vec!["A", "B", "C"]).with_placeholder("Pick one...");
assert_eq!(state.placeholder(), "Pick one...");
}
#[test]
fn test_annotation_emitted() {
use crate::annotation::{WidgetType, with_annotations};
let state = SelectState::new(vec!["A".to_string(), "B".to_string()]);
let (mut terminal, theme) = crate::component::test_utils::setup_render(30, 10);
let registry = with_annotations(|| {
terminal
.draw(|frame| {
Select::view(&state, &mut RenderContext::new(frame, frame.area(), &theme));
})
.unwrap();
});
assert_eq!(registry.len(), 1);
let regions = registry.find_by_type(&WidgetType::Select);
assert_eq!(regions.len(), 1);
assert_eq!(regions[0].annotation.expanded, Some(false));
}