diff --git a/src/models/mod.rs b/src/models/mod.rs index 36ab62f..77bdcd6 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -43,6 +43,10 @@ macro_rules! stateful_iterable { impl Scrollable for $name { fn scroll_down(&mut self) { + if self.items.is_empty() { + return; + } + let selected_row = match self.state.selected() { Some(i) => { if i >= self.items.len() - 1 { @@ -58,6 +62,10 @@ macro_rules! stateful_iterable { } fn scroll_up(&mut self) { + if self.items.is_empty() { + return; + } + let selected_row = match self.state.selected() { Some(i) => { if i == 0 { @@ -73,10 +81,18 @@ macro_rules! stateful_iterable { } fn scroll_to_top(&mut self) { + if self.items.is_empty() { + return; + } + self.state.select(Some(0)); } fn scroll_to_bottom(&mut self) { + if self.items.is_empty() { + return; + } + self.state.select(Some(self.items.len() - 1)); } } @@ -141,12 +157,20 @@ impl ScrollableText { impl Scrollable for ScrollableText { fn scroll_down(&mut self) { + if self.items.is_empty() { + return; + } + if self.offset < (self.items.len() - 1) as u16 { self.offset += 1; } } fn scroll_up(&mut self) { + if self.items.is_empty() { + return; + } + if self.offset > 0 { self.offset -= 1; } diff --git a/src/models/model_tests.rs b/src/models/model_tests.rs index 439ce4b..7554d70 100644 --- a/src/models/model_tests.rs +++ b/src/models/model_tests.rs @@ -6,8 +6,8 @@ mod tests { use crate::app::radarr::ActiveRadarrBlock; use crate::models::{ - BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulTable, - TabRoute, TabState, + BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulList, + StatefulTable, TabRoute, TabState, }; const BLOCKS: [ActiveRadarrBlock; 6] = [ @@ -19,6 +19,27 @@ mod tests { ActiveRadarrBlock::AddMovieConfirmPrompt, ]; + #[test] + fn test_stateful_table_scrolling_on_empty_table_performs_no_op() { + let mut stateful_table: StatefulTable = StatefulTable::default(); + + assert_eq!(stateful_table.state.selected(), None); + + stateful_table.scroll_up(); + + assert_eq!(stateful_table.state.selected(), None); + + stateful_table.scroll_down(); + + assert_eq!(stateful_table.state.selected(), None); + + stateful_table.scroll_to_top(); + + assert_eq!(stateful_table.state.selected(), None); + + stateful_table.scroll_to_bottom(); + } + #[test] fn test_stateful_table_scroll() { let mut stateful_table = create_test_stateful_table(); @@ -111,6 +132,104 @@ mod tests { assert_eq!(stateful_table.state.selected(), Some(0)); } + #[test] + fn test_stateful_list_scrolling_on_empty_table_performs_no_op() { + let mut stateful_list: StatefulList = StatefulList::default(); + + assert_eq!(stateful_list.state.selected(), None); + + stateful_list.scroll_up(); + + assert_eq!(stateful_list.state.selected(), None); + + stateful_list.scroll_down(); + + assert_eq!(stateful_list.state.selected(), None); + + stateful_list.scroll_to_top(); + + assert_eq!(stateful_list.state.selected(), None); + + stateful_list.scroll_to_bottom(); + } + + #[test] + fn test_stateful_list_scroll() { + let mut stateful_list = create_test_stateful_list(); + + assert_eq!(stateful_list.state.selected(), Some(0)); + + stateful_list.scroll_down(); + + assert_eq!(stateful_list.state.selected(), Some(1)); + + stateful_list.scroll_down(); + + assert_eq!(stateful_list.state.selected(), Some(0)); + + stateful_list.scroll_up(); + + assert_eq!(stateful_list.state.selected(), Some(1)); + + stateful_list.scroll_up(); + + assert_eq!(stateful_list.state.selected(), Some(0)); + + stateful_list.scroll_to_bottom(); + + assert_eq!(stateful_list.state.selected(), Some(1)); + + stateful_list.scroll_to_top(); + + assert_eq!(stateful_list.state.selected(), Some(0)); + } + + #[test] + fn test_stateful_list_set_items() { + let items_vec = vec!["Test 1", "Test 2", "Test 3"]; + let mut stateful_list: StatefulList<&str> = StatefulList::default(); + + stateful_list.set_items(items_vec.clone()); + + assert_eq!(stateful_list.state.selected(), Some(0)); + + stateful_list.state.select(Some(1)); + stateful_list.set_items(items_vec.clone()); + + assert_eq!(stateful_list.state.selected(), Some(1)); + + stateful_list.state.select(Some(3)); + stateful_list.set_items(items_vec); + + assert_eq!(stateful_list.state.selected(), Some(2)); + } + + #[test] + fn test_stateful_list_current_selection() { + let mut stateful_list = create_test_stateful_list(); + + assert_str_eq!(stateful_list.current_selection(), &stateful_list.items[0]); + + stateful_list.state.select(Some(1)); + + assert_str_eq!(stateful_list.current_selection(), &stateful_list.items[1]); + } + + #[test] + fn test_stateful_list_scroll_up() { + let mut stateful_table = create_test_stateful_table(); + + assert_eq!(stateful_table.state.selected(), Some(0)); + + stateful_table.scroll_up(); + + assert_eq!(stateful_table.state.selected(), Some(1)); + + stateful_table.scroll_up(); + + assert_eq!(stateful_table.state.selected(), Some(0)); + } + #[test] fn test_scrollable_text_with_string() { let scrollable_text = ScrollableText::with_string("Test \n String \n".to_owned()); @@ -157,6 +276,19 @@ mod tests { assert_eq!(scrollable_text.offset, 0); } + #[test] + fn test_scrollable_text_scroll_up_or_down_performs_no_op_on_empty_text() { + let mut scrollable_text = ScrollableText::default(); + + scrollable_text.scroll_up(); + + assert_eq!(scrollable_text.offset, 0); + + scrollable_text.scroll_down(); + + assert_eq!(scrollable_text.offset, 0); + } + #[test] fn test_horizontally_scrollable_text_from_string() { let test_text = "Test string"; @@ -534,4 +666,11 @@ mod tests { stateful_table } + + fn create_test_stateful_list() -> StatefulList<&'static str> { + let mut stateful_list = StatefulList::default(); + stateful_list.set_items(vec!["Test 1", "Test 2"]); + + stateful_list + } }