Refactored table filtering and searching so that they are now relative to the table being filtered/searched on. Also created two new widgets for error messages and popups to make life easier moving forward. Going to refactor table sorting into StatefulTable's as well so all tables can be searched, filtered, and sorted moving forwards.
This commit is contained in:
+196
-35
@@ -3,47 +3,51 @@ use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use ratatui::widgets::{ListState, TableState};
|
||||
use regex::Regex;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_json::Number;
|
||||
|
||||
pub mod radarr_models;
|
||||
pub mod servarr_data;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "model_tests.rs"]
|
||||
mod model_tests;
|
||||
|
||||
// Allowing dead code for now since we'll eventually be implementing additional Servarr support and we'll need it then
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum Route {
|
||||
Radarr(ActiveRadarrBlock, Option<ActiveRadarrBlock>),
|
||||
Sonarr,
|
||||
Readarr,
|
||||
Lidarr,
|
||||
Whisparr,
|
||||
Bazarr,
|
||||
Prowlarr,
|
||||
Tautulli,
|
||||
}
|
||||
|
||||
pub trait Scrollable {
|
||||
fn scroll_down(&mut self);
|
||||
fn scroll_up(&mut self);
|
||||
fn scroll_to_top(&mut self);
|
||||
fn scroll_to_bottom(&mut self);
|
||||
}
|
||||
|
||||
macro_rules! stateful_iterable {
|
||||
($name:ident, $state:ty) => {
|
||||
#[derive(Default)]
|
||||
pub struct $name<T> {
|
||||
pub state: $state,
|
||||
pub items: Vec<T>,
|
||||
pub filter: Option<HorizontallyScrollableText>,
|
||||
pub search: Option<HorizontallyScrollableText>,
|
||||
pub filtered_items: Option<Vec<T>>,
|
||||
pub filtered_state: Option<$state>,
|
||||
}
|
||||
|
||||
impl<T> Scrollable for $name<T> {
|
||||
fn scroll_down(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let selected_row = match self.filtered_state.as_ref().unwrap().selected() {
|
||||
Some(i) => {
|
||||
if i >= filtered_items.len() - 1 {
|
||||
0
|
||||
} else {
|
||||
i + 1
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.select(Some(selected_row));
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -63,6 +67,30 @@ macro_rules! stateful_iterable {
|
||||
}
|
||||
|
||||
fn scroll_up(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let selected_row = match self.filtered_state.as_ref().unwrap().selected() {
|
||||
Some(i) => {
|
||||
if i == 0 {
|
||||
filtered_items.len() - 1
|
||||
} else {
|
||||
i - 1
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.select(Some(selected_row));
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -82,6 +110,15 @@ macro_rules! stateful_iterable {
|
||||
}
|
||||
|
||||
fn scroll_to_top(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.filtered_state.as_mut().unwrap().select(Some(0));
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -90,6 +127,19 @@ macro_rules! stateful_iterable {
|
||||
}
|
||||
|
||||
fn scroll_to_bottom(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.select(Some(filtered_items.len() - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -98,6 +148,7 @@ macro_rules! stateful_iterable {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> $name<T>
|
||||
where
|
||||
T: Clone + PartialEq + Eq + Debug,
|
||||
@@ -119,25 +170,128 @@ macro_rules! stateful_iterable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_filtered_items(&mut self, filtered_items: Vec<T>) {
|
||||
self.filtered_items = Some(filtered_items);
|
||||
let mut filtered_state: $state = Default::default();
|
||||
filtered_state.select(Some(0));
|
||||
self.filtered_state = Some(filtered_state);
|
||||
}
|
||||
|
||||
pub fn select_index(&mut self, index: Option<usize>) {
|
||||
if let Some(filtered_state) = &mut self.filtered_state {
|
||||
filtered_state.select(index);
|
||||
} else {
|
||||
self.state.select(index);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_selection(&self) -> &T {
|
||||
&self.items[self.state.selected().unwrap_or(0)]
|
||||
if let Some(filtered_items) = &self.filtered_items {
|
||||
&filtered_items[self
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected()
|
||||
.unwrap_or(0)]
|
||||
} else {
|
||||
&self.items[self.state.selected().unwrap_or(0)]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_filter(&mut self, filter_field: fn(&T) -> &str) -> bool {
|
||||
let filter_matches = match self.filter {
|
||||
Some(ref filter) if !filter.text.is_empty() => {
|
||||
let scrubbed_filter = strip_non_search_characters(&filter.text.clone());
|
||||
|
||||
self
|
||||
.items
|
||||
.iter()
|
||||
.filter(|item| {
|
||||
strip_non_search_characters(filter_field(&item)).contains(&scrubbed_filter)
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
self.filter = None;
|
||||
|
||||
if filter_matches.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.set_filtered_items(filter_matches);
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn reset_filter(&mut self) {
|
||||
self.filter = None;
|
||||
self.filtered_items = None;
|
||||
self.filtered_state = None;
|
||||
}
|
||||
|
||||
pub fn apply_search(&mut self, search_field: fn(&T) -> &str) -> bool {
|
||||
let search_index = if let Some(search) = self.search.as_ref() {
|
||||
let search_string = search.text.clone().to_lowercase();
|
||||
|
||||
self
|
||||
.filtered_items
|
||||
.as_ref()
|
||||
.unwrap_or(&self.items)
|
||||
.iter()
|
||||
.position(|item| {
|
||||
strip_non_search_characters(search_field(&item)).contains(&search_string)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.search = None;
|
||||
|
||||
if search_index.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.select_index(search_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn reset_search(&mut self) {
|
||||
self.search = None;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "model_tests.rs"]
|
||||
mod model_tests;
|
||||
|
||||
// Allowing dead code for now since we'll eventually be implementing additional Servarr support, and we'll need it then
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum Route {
|
||||
Radarr(ActiveRadarrBlock, Option<ActiveRadarrBlock>),
|
||||
Sonarr,
|
||||
Readarr,
|
||||
Lidarr,
|
||||
Whisparr,
|
||||
Bazarr,
|
||||
Prowlarr,
|
||||
Tautulli,
|
||||
}
|
||||
|
||||
pub trait Scrollable {
|
||||
fn scroll_down(&mut self);
|
||||
fn scroll_up(&mut self);
|
||||
fn scroll_to_top(&mut self);
|
||||
fn scroll_to_bottom(&mut self);
|
||||
}
|
||||
|
||||
stateful_iterable!(StatefulList, ListState);
|
||||
stateful_iterable!(StatefulTable, TableState);
|
||||
|
||||
impl<T> StatefulTable<T>
|
||||
where
|
||||
T: Clone + PartialEq + Eq + Debug,
|
||||
{
|
||||
pub fn select_index(&mut self, index: Option<usize>) {
|
||||
self.state.select(index);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ScrollableText {
|
||||
pub items: Vec<String>,
|
||||
@@ -429,3 +583,10 @@ where
|
||||
"Unable to convert Number to i64: {num:?}"
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn strip_non_search_characters(input: &str) -> String {
|
||||
Regex::new(r"[^a-zA-Z0-9.,/'\-:\s]")
|
||||
.unwrap()
|
||||
.replace_all(&input.to_lowercase(), "")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
+754
-8
@@ -3,14 +3,15 @@ mod tests {
|
||||
use std::cell::RefCell;
|
||||
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use ratatui::widgets::{ListState, TableState};
|
||||
use serde::de::value::Error as ValueError;
|
||||
use serde::de::value::F64Deserializer;
|
||||
use serde::de::value::I64Deserializer;
|
||||
use serde::de::IntoDeserializer;
|
||||
use serde_json::to_string;
|
||||
|
||||
use crate::models::from_i64;
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use crate::models::{from_i64, strip_non_search_characters};
|
||||
use crate::models::{
|
||||
BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulList,
|
||||
StatefulTable, TabRoute, TabState,
|
||||
@@ -46,6 +47,59 @@ mod tests {
|
||||
stateful_table.scroll_to_bottom();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_filtered_scrolling_on_empty_table_performs_no_op() {
|
||||
let mut filtered_stateful_table: StatefulTable<String> = StatefulTable {
|
||||
filtered_items: Some(Vec::new()),
|
||||
filtered_state: Some(TableState::default()),
|
||||
..StatefulTable::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_down();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_to_top();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_to_bottom();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_scroll() {
|
||||
let mut stateful_table = create_test_stateful_table();
|
||||
@@ -77,6 +131,86 @@ mod tests {
|
||||
assert_eq!(stateful_table.state.selected(), Some(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_filtered_items_scroll() {
|
||||
let mut filtered_stateful_table = create_test_filtered_stateful_table();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_down();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_down();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_to_bottom();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_to_top();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_set_items() {
|
||||
let items_vec = vec!["Test 1", "Test 2", "Test 3"];
|
||||
@@ -97,6 +231,27 @@ mod tests {
|
||||
assert_eq!(stateful_table.state.selected(), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_set_filtered_items() {
|
||||
let filtered_items_vec = vec!["Test 1", "Test 2", "Test 3"];
|
||||
let mut filtered_stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
|
||||
filtered_stateful_table.set_filtered_items(filtered_items_vec.clone());
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
assert_eq!(
|
||||
filtered_stateful_table.filtered_items,
|
||||
Some(filtered_items_vec.clone())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_current_selection() {
|
||||
let mut stateful_table = create_test_stateful_table();
|
||||
@@ -108,6 +263,27 @@ mod tests {
|
||||
assert_str_eq!(stateful_table.current_selection(), &stateful_table.items[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_table_current_selection() {
|
||||
let mut filtered_stateful_table = create_test_filtered_stateful_table();
|
||||
|
||||
assert_str_eq!(
|
||||
filtered_stateful_table.current_selection(),
|
||||
&filtered_stateful_table.filtered_items.as_ref().unwrap()[0]
|
||||
);
|
||||
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.select(Some(1));
|
||||
|
||||
assert_str_eq!(
|
||||
filtered_stateful_table.current_selection(),
|
||||
&filtered_stateful_table.filtered_items.as_ref().unwrap()[1]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_select_index() {
|
||||
let mut stateful_table = create_test_stateful_table();
|
||||
@@ -123,6 +299,42 @@ mod tests {
|
||||
assert_eq!(stateful_table.state.selected(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_table_select_index() {
|
||||
let mut filtered_stateful_table = create_test_filtered_stateful_table();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_table.select_index(Some(1));
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_table.select_index(None);
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_scroll_up() {
|
||||
let mut stateful_table = create_test_stateful_table();
|
||||
@@ -139,7 +351,150 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_scrolling_on_empty_table_performs_no_op() {
|
||||
fn test_filtered_stateful_table_scroll_up() {
|
||||
let mut filtered_stateful_table = create_test_filtered_stateful_table();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_table.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_table
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_apply_filter() {
|
||||
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
stateful_table.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_table.filter = Some("i".into());
|
||||
let expected_items = vec!["this", "is"];
|
||||
let mut expected_state = TableState::default();
|
||||
expected_state.select(Some(0));
|
||||
|
||||
let has_matches = stateful_table.apply_filter(|&item| item);
|
||||
|
||||
assert_eq!(stateful_table.filter, None);
|
||||
assert_eq!(stateful_table.filtered_items, Some(expected_items));
|
||||
assert_eq!(stateful_table.filtered_state, Some(expected_state));
|
||||
assert!(has_matches);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_apply_filter_no_matches() {
|
||||
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
stateful_table.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_table.filter = Some("z".into());
|
||||
|
||||
let has_matches = stateful_table.apply_filter(|&item| item);
|
||||
|
||||
assert_eq!(stateful_table.filter, None);
|
||||
assert_eq!(stateful_table.filtered_items, None);
|
||||
assert_eq!(stateful_table.filtered_state, None);
|
||||
assert!(!has_matches);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_reset_filter() {
|
||||
let mut stateful_table = create_test_filtered_stateful_table();
|
||||
stateful_table.reset_filter();
|
||||
|
||||
assert_eq!(stateful_table.filter, None);
|
||||
assert_eq!(stateful_table.filtered_items, None);
|
||||
assert_eq!(stateful_table.filtered_state, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_apply_search() {
|
||||
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
stateful_table.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_table.search = Some("test".into());
|
||||
let mut expected_state = TableState::default();
|
||||
expected_state.select(Some(3));
|
||||
|
||||
let has_match = stateful_table.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_table.search, None);
|
||||
assert_eq!(stateful_table.state, expected_state);
|
||||
assert!(has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_apply_search_no_match() {
|
||||
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
stateful_table.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_table.search = Some("shi-mon-a!".into());
|
||||
|
||||
let has_match = stateful_table.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_table.search, None);
|
||||
assert!(!has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_table_apply_search() {
|
||||
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
stateful_table.set_filtered_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_table.search = Some("test".into());
|
||||
let mut expected_state = TableState::default();
|
||||
expected_state.select(Some(3));
|
||||
|
||||
let has_match = stateful_table.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_table.search, None);
|
||||
assert_eq!(stateful_table.filtered_state, Some(expected_state));
|
||||
assert!(has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_table_apply_search_no_match() {
|
||||
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
|
||||
stateful_table.set_filtered_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_table.search = Some("shi-mon-a!".into());
|
||||
let mut expected_state = TableState::default();
|
||||
expected_state.select(Some(0));
|
||||
|
||||
let has_match = stateful_table.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_table.search, None);
|
||||
assert_eq!(stateful_table.filtered_state, Some(expected_state));
|
||||
assert!(!has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_table_reset_search() {
|
||||
let mut stateful_table = create_test_stateful_table();
|
||||
stateful_table.search = Some("test".into());
|
||||
stateful_table.reset_search();
|
||||
|
||||
assert_eq!(stateful_table.search, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_scrolling_on_empty_list_performs_no_op() {
|
||||
let mut stateful_list: StatefulList<String> = StatefulList::default();
|
||||
|
||||
assert_eq!(stateful_list.state.selected(), None);
|
||||
@@ -159,6 +514,59 @@ mod tests {
|
||||
stateful_list.scroll_to_bottom();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_scrolling_on_empty_list_performs_no_op() {
|
||||
let mut filtered_stateful_list: StatefulList<String> = StatefulList {
|
||||
filtered_items: Some(Vec::new()),
|
||||
filtered_state: Some(ListState::default()),
|
||||
..StatefulList::default()
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_down();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_to_top();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_to_bottom();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_scroll() {
|
||||
let mut stateful_list = create_test_stateful_list();
|
||||
@@ -190,6 +598,86 @@ mod tests {
|
||||
assert_eq!(stateful_list.state.selected(), Some(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_scroll() {
|
||||
let mut filtered_stateful_list = create_test_filtered_stateful_list();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_down();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_down();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_to_bottom();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_to_top();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_set_items() {
|
||||
let items_vec = vec!["Test 1", "Test 2", "Test 3"];
|
||||
@@ -210,6 +698,27 @@ mod tests {
|
||||
assert_eq!(stateful_list.state.selected(), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_set_filtered_items() {
|
||||
let filtered_items_vec = vec!["Test 1", "Test 2", "Test 3"];
|
||||
let mut filtered_stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
|
||||
filtered_stateful_list.set_filtered_items(filtered_items_vec.clone());
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
assert_eq!(
|
||||
filtered_stateful_list.filtered_items,
|
||||
Some(filtered_items_vec.clone())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_current_selection() {
|
||||
let mut stateful_list = create_test_stateful_list();
|
||||
@@ -221,19 +730,234 @@ mod tests {
|
||||
assert_str_eq!(stateful_list.current_selection(), &stateful_list.items[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_current_selection() {
|
||||
let mut filtered_stateful_list = create_test_filtered_stateful_list();
|
||||
|
||||
assert_str_eq!(
|
||||
filtered_stateful_list.current_selection(),
|
||||
&filtered_stateful_list.filtered_items.as_ref().unwrap()[0]
|
||||
);
|
||||
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.select(Some(1));
|
||||
|
||||
assert_str_eq!(
|
||||
filtered_stateful_list.current_selection(),
|
||||
&filtered_stateful_list.filtered_items.as_ref().unwrap()[1]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_select_index() {
|
||||
let mut stateful_list = create_test_stateful_list();
|
||||
|
||||
assert_eq!(stateful_list.state.selected(), Some(0));
|
||||
|
||||
stateful_list.select_index(Some(1));
|
||||
|
||||
assert_eq!(stateful_list.state.selected(), Some(1));
|
||||
|
||||
stateful_list.select_index(None);
|
||||
|
||||
assert_eq!(stateful_list.state.selected(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_select_index() {
|
||||
let mut filtered_stateful_list = create_test_filtered_stateful_list();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_list.select_index(Some(1));
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_list.select_index(None);
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_scroll_up() {
|
||||
let mut stateful_table = create_test_stateful_table();
|
||||
let mut stateful_list = create_test_stateful_list();
|
||||
|
||||
assert_eq!(stateful_table.state.selected(), Some(0));
|
||||
assert_eq!(stateful_list.state.selected(), Some(0));
|
||||
|
||||
stateful_table.scroll_up();
|
||||
stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(stateful_table.state.selected(), Some(1));
|
||||
assert_eq!(stateful_list.state.selected(), Some(1));
|
||||
|
||||
stateful_table.scroll_up();
|
||||
stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(stateful_table.state.selected(), Some(0));
|
||||
assert_eq!(stateful_list.state.selected(), Some(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_scroll_up() {
|
||||
let mut filtered_stateful_list = create_test_filtered_stateful_list();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(1)
|
||||
);
|
||||
|
||||
filtered_stateful_list.scroll_up();
|
||||
|
||||
assert_eq!(
|
||||
filtered_stateful_list
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.selected(),
|
||||
Some(0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_apply_filter() {
|
||||
let mut stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
stateful_list.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_list.filter = Some("i".into());
|
||||
let expected_items = vec!["this", "is"];
|
||||
let mut expected_state = ListState::default();
|
||||
expected_state.select(Some(0));
|
||||
|
||||
let has_matches = stateful_list.apply_filter(|&item| item);
|
||||
|
||||
assert_eq!(stateful_list.filter, None);
|
||||
assert_eq!(stateful_list.filtered_items, Some(expected_items));
|
||||
assert_eq!(stateful_list.filtered_state, Some(expected_state));
|
||||
assert!(has_matches);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_apply_filter_no_matches() {
|
||||
let mut stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
stateful_list.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_list.filter = Some("z".into());
|
||||
|
||||
let has_matches = stateful_list.apply_filter(|&item| item);
|
||||
|
||||
assert_eq!(stateful_list.filter, None);
|
||||
assert_eq!(stateful_list.filtered_items, None);
|
||||
assert_eq!(stateful_list.filtered_state, None);
|
||||
assert!(!has_matches);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_reset_filter() {
|
||||
let mut stateful_list = create_test_filtered_stateful_list();
|
||||
stateful_list.reset_filter();
|
||||
|
||||
assert_eq!(stateful_list.filter, None);
|
||||
assert_eq!(stateful_list.filtered_items, None);
|
||||
assert_eq!(stateful_list.filtered_state, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_apply_search() {
|
||||
let mut stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
stateful_list.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_list.search = Some("test".into());
|
||||
let mut expected_state = ListState::default();
|
||||
expected_state.select(Some(3));
|
||||
|
||||
let has_match = stateful_list.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_list.search, None);
|
||||
assert_eq!(stateful_list.state, expected_state);
|
||||
assert!(has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_apply_search_no_match() {
|
||||
let mut stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
stateful_list.set_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_list.search = Some("shi-mon-a!".into());
|
||||
|
||||
let has_match = stateful_list.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_list.search, None);
|
||||
assert!(!has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_apply_search() {
|
||||
let mut stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
stateful_list.set_filtered_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_list.search = Some("test".into());
|
||||
let mut expected_state = ListState::default();
|
||||
expected_state.select(Some(3));
|
||||
|
||||
let has_match = stateful_list.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_list.search, None);
|
||||
assert_eq!(stateful_list.filtered_state, Some(expected_state));
|
||||
assert!(has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filtered_stateful_list_apply_search_no_match() {
|
||||
let mut stateful_list: StatefulList<&str> = StatefulList::default();
|
||||
stateful_list.set_filtered_items(vec!["this", "is", "a", "test"]);
|
||||
stateful_list.search = Some("shi-mon-a!".into());
|
||||
let mut expected_state = ListState::default();
|
||||
expected_state.select(Some(0));
|
||||
|
||||
let has_match = stateful_list.apply_search(|&item| item);
|
||||
|
||||
assert_eq!(stateful_list.search, None);
|
||||
assert_eq!(stateful_list.filtered_state, Some(expected_state));
|
||||
assert!(!has_match);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stateful_list_reset_search() {
|
||||
let mut stateful_list = create_test_stateful_list();
|
||||
stateful_list.search = Some("test".into());
|
||||
stateful_list.reset_search();
|
||||
|
||||
assert_eq!(stateful_list.search, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -771,10 +1495,32 @@ mod tests {
|
||||
stateful_table
|
||||
}
|
||||
|
||||
fn create_test_filtered_stateful_table() -> StatefulTable<&'static str> {
|
||||
let mut stateful_table = StatefulTable::default();
|
||||
stateful_table.set_filtered_items(vec!["Test 1", "Test 2"]);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fn create_test_filtered_stateful_list() -> StatefulList<&'static str> {
|
||||
let mut stateful_list = StatefulList::default();
|
||||
stateful_list.set_filtered_items(vec!["Test 1", "Test 2"]);
|
||||
|
||||
stateful_list
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_non_alphanumeric_characters() {
|
||||
assert_eq!(
|
||||
strip_non_search_characters("Te$t S7r!ng::'~-@_`,(.)/*}^&%#+="),
|
||||
"tet s7rng::'-,./".to_owned()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,11 +133,7 @@ impl From<&RadarrData<'_>> for EditMovieModal {
|
||||
minimum_availability,
|
||||
quality_profile_id,
|
||||
..
|
||||
} = if let Some(filtered_movies) = radarr_data.filtered_movies.as_ref() {
|
||||
filtered_movies.current_selection()
|
||||
} else {
|
||||
radarr_data.movies.current_selection()
|
||||
};
|
||||
} = radarr_data.movies.current_selection();
|
||||
|
||||
edit_movie_modal
|
||||
.minimum_availability_list
|
||||
@@ -249,11 +245,7 @@ impl From<&RadarrData<'_>> for EditCollectionModal {
|
||||
minimum_availability,
|
||||
quality_profile_id,
|
||||
..
|
||||
} = if let Some(filtered_collections) = radarr_data.filtered_collections.as_ref() {
|
||||
filtered_collections.current_selection()
|
||||
} else {
|
||||
radarr_data.collections.current_selection()
|
||||
};
|
||||
} = radarr_data.collections.current_selection();
|
||||
|
||||
edit_collection_modal.path = root_folder_path.clone().unwrap_or_default().into();
|
||||
edit_collection_modal.monitored = Some(*monitored);
|
||||
|
||||
@@ -117,7 +117,7 @@ mod test {
|
||||
(1111, "Any".to_owned()),
|
||||
]),
|
||||
tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]),
|
||||
filtered_movies: None,
|
||||
movies: StatefulTable::default(),
|
||||
..create_test_radarr_data()
|
||||
};
|
||||
let movie = Movie {
|
||||
@@ -130,9 +130,7 @@ mod test {
|
||||
};
|
||||
|
||||
if test_filtered_movies {
|
||||
let mut filtered_movies = StatefulTable::default();
|
||||
filtered_movies.set_items(vec![movie]);
|
||||
radarr_data.filtered_movies = Some(filtered_movies);
|
||||
radarr_data.movies.set_filtered_items(vec![movie]);
|
||||
} else {
|
||||
radarr_data.movies.set_items(vec![movie]);
|
||||
}
|
||||
@@ -209,7 +207,7 @@ mod test {
|
||||
(2222, "HD - 1080p".to_owned()),
|
||||
(1111, "Any".to_owned()),
|
||||
]),
|
||||
filtered_collections: None,
|
||||
collections: StatefulTable::default(),
|
||||
..create_test_radarr_data()
|
||||
};
|
||||
let collection = Collection {
|
||||
@@ -222,9 +220,7 @@ mod test {
|
||||
};
|
||||
|
||||
if test_filtered_collections {
|
||||
let mut filtered_collections = StatefulTable::default();
|
||||
filtered_collections.set_items(vec![collection]);
|
||||
radarr_data.filtered_collections = Some(filtered_collections);
|
||||
radarr_data.collections.set_filtered_items(vec![collection]);
|
||||
} else {
|
||||
radarr_data.collections.set_items(vec![collection]);
|
||||
}
|
||||
|
||||
@@ -50,16 +50,13 @@ pub struct RadarrData<'a> {
|
||||
pub updates: ScrollableText,
|
||||
pub main_tabs: TabState,
|
||||
pub movie_info_tabs: TabState,
|
||||
pub search: Option<HorizontallyScrollableText>,
|
||||
pub filter: Option<HorizontallyScrollableText>,
|
||||
pub add_movie_search: Option<HorizontallyScrollableText>,
|
||||
pub add_movie_modal: Option<AddMovieModal>,
|
||||
pub add_searched_movies: Option<StatefulTable<AddMovieSearchResult>>,
|
||||
pub edit_movie_modal: Option<EditMovieModal>,
|
||||
pub edit_collection_modal: Option<EditCollectionModal>,
|
||||
pub edit_indexer_modal: Option<EditIndexerModal>,
|
||||
pub edit_root_folder: Option<HorizontallyScrollableText>,
|
||||
pub filtered_collections: Option<StatefulTable<Collection>>,
|
||||
pub filtered_movies: Option<StatefulTable<Movie>>,
|
||||
pub indexer_settings: Option<IndexerSettings>,
|
||||
pub indexer_test_all_results: Option<StatefulTable<IndexerTestResultModalItem>>,
|
||||
pub movie_details_modal: Option<MovieDetailsModal>,
|
||||
@@ -67,8 +64,6 @@ pub struct RadarrData<'a> {
|
||||
pub prompt_confirm_action: Option<RadarrEvent>,
|
||||
pub delete_movie_files: bool,
|
||||
pub add_list_exclusion: bool,
|
||||
pub is_searching: bool,
|
||||
pub is_filtering: bool,
|
||||
}
|
||||
|
||||
impl<'a> RadarrData<'a> {
|
||||
@@ -77,22 +72,6 @@ impl<'a> RadarrData<'a> {
|
||||
self.add_list_exclusion = false;
|
||||
}
|
||||
|
||||
pub fn reset_search(&mut self) {
|
||||
self.is_searching = false;
|
||||
self.search = None;
|
||||
self.filter = None;
|
||||
self.filtered_movies = None;
|
||||
self.filtered_collections = None;
|
||||
self.add_searched_movies = None;
|
||||
}
|
||||
|
||||
pub fn reset_filter(&mut self) {
|
||||
self.is_filtering = false;
|
||||
self.filter = None;
|
||||
self.filtered_movies = None;
|
||||
self.filtered_collections = None;
|
||||
}
|
||||
|
||||
pub fn reset_movie_info_tabs(&mut self) {
|
||||
self.movie_details_modal = None;
|
||||
self.movie_info_tabs.index = 0;
|
||||
@@ -119,21 +98,16 @@ impl<'a> Default for RadarrData<'a> {
|
||||
tasks: StatefulTable::default(),
|
||||
queued_events: StatefulTable::default(),
|
||||
updates: ScrollableText::default(),
|
||||
search: None,
|
||||
filter: None,
|
||||
add_movie_search: None,
|
||||
add_movie_modal: None,
|
||||
add_searched_movies: None,
|
||||
edit_movie_modal: None,
|
||||
edit_collection_modal: None,
|
||||
edit_indexer_modal: None,
|
||||
edit_root_folder: None,
|
||||
filtered_collections: None,
|
||||
filtered_movies: None,
|
||||
indexer_settings: None,
|
||||
indexer_test_all_results: None,
|
||||
movie_details_modal: None,
|
||||
is_searching: false,
|
||||
is_filtering: false,
|
||||
prompt_confirm: false,
|
||||
prompt_confirm_action: None,
|
||||
delete_movie_files: false,
|
||||
@@ -505,16 +479,3 @@ impl From<(ActiveRadarrBlock, Option<ActiveRadarrBlock>)> for Route {
|
||||
Route::Radarr(value.0, value.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // Returning to this work tomorrow
|
||||
pub struct EditIndexerSettings {
|
||||
pub allow_hardcoded_subs: bool,
|
||||
pub availability_delay: HorizontallyScrollableText,
|
||||
pub id: HorizontallyScrollableText,
|
||||
pub maximum_size: HorizontallyScrollableText,
|
||||
pub minimum_age: HorizontallyScrollableText,
|
||||
pub prefer_indexer_flags: bool,
|
||||
pub retention: HorizontallyScrollableText,
|
||||
pub rss_sync_interval: HorizontallyScrollableText,
|
||||
pub whitelisted_hardcoded_subs: HorizontallyScrollableText,
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ mod tests {
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData};
|
||||
use crate::models::Route;
|
||||
|
||||
use crate::assert_movie_info_tabs_reset;
|
||||
use crate::models::BlockSelectionState;
|
||||
use crate::{assert_filter_reset, assert_movie_info_tabs_reset, assert_search_reset};
|
||||
|
||||
#[test]
|
||||
fn test_from_tuple_to_route_with_context() {
|
||||
@@ -43,24 +43,6 @@ mod tests {
|
||||
assert!(!radarr_data.add_list_exclusion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reset_search() {
|
||||
let mut radarr_data = utils::create_test_radarr_data();
|
||||
|
||||
radarr_data.reset_search();
|
||||
|
||||
assert_search_reset!(radarr_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reset_filter() {
|
||||
let mut radarr_data = utils::create_test_radarr_data();
|
||||
|
||||
radarr_data.reset_filter();
|
||||
|
||||
assert_filter_reset!(radarr_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reset_movie_info_tabs() {
|
||||
let mut radarr_data = utils::create_test_radarr_data();
|
||||
@@ -91,21 +73,16 @@ mod tests {
|
||||
assert!(radarr_data.tasks.items.is_empty());
|
||||
assert!(radarr_data.queued_events.items.is_empty());
|
||||
assert!(radarr_data.updates.get_text().is_empty());
|
||||
assert!(radarr_data.search.is_none());
|
||||
assert!(radarr_data.filter.is_none());
|
||||
assert!(radarr_data.add_movie_search.is_none());
|
||||
assert!(radarr_data.add_movie_modal.is_none());
|
||||
assert!(radarr_data.add_searched_movies.is_none());
|
||||
assert!(radarr_data.edit_movie_modal.is_none());
|
||||
assert!(radarr_data.edit_collection_modal.is_none());
|
||||
assert!(radarr_data.edit_root_folder.is_none());
|
||||
assert!(radarr_data.edit_indexer_modal.is_none());
|
||||
assert!(radarr_data.filtered_collections.is_none());
|
||||
assert!(radarr_data.filtered_movies.is_none());
|
||||
assert!(radarr_data.indexer_settings.is_none());
|
||||
assert!(radarr_data.indexer_test_all_results.is_none());
|
||||
assert!(radarr_data.movie_details_modal.is_none());
|
||||
assert!(!radarr_data.is_searching);
|
||||
assert!(!radarr_data.is_filtering);
|
||||
assert!(radarr_data.prompt_confirm_action.is_none());
|
||||
assert!(!radarr_data.prompt_confirm);
|
||||
assert!(!radarr_data.delete_movie_files);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#[cfg(test)]
|
||||
pub mod utils {
|
||||
use crate::models::radarr_models::{
|
||||
AddMovieSearchResult, Collection, CollectionMovie, Credit, Movie, MovieHistoryItem, Release,
|
||||
ReleaseField,
|
||||
AddMovieSearchResult, CollectionMovie, Credit, MovieHistoryItem, Release, ReleaseField,
|
||||
};
|
||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
|
||||
@@ -31,30 +30,15 @@ pub mod utils {
|
||||
movie_details_modal.sort_ascending = Some(true);
|
||||
|
||||
let mut radarr_data = RadarrData {
|
||||
is_searching: true,
|
||||
is_filtering: true,
|
||||
delete_movie_files: true,
|
||||
add_list_exclusion: true,
|
||||
search: Some("test search".into()),
|
||||
filter: Some("test filter".into()),
|
||||
add_movie_search: Some("test search".into()),
|
||||
edit_root_folder: Some("test path".into()),
|
||||
movie_details_modal: Some(movie_details_modal),
|
||||
filtered_movies: Some(StatefulTable::default()),
|
||||
filtered_collections: Some(StatefulTable::default()),
|
||||
add_searched_movies: Some(StatefulTable::default()),
|
||||
..RadarrData::default()
|
||||
};
|
||||
radarr_data.movie_info_tabs.index = 1;
|
||||
radarr_data
|
||||
.filtered_movies
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_items(vec![Movie::default()]);
|
||||
radarr_data
|
||||
.filtered_collections
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_items(vec![Collection::default()]);
|
||||
radarr_data
|
||||
.add_searched_movies
|
||||
.as_mut()
|
||||
@@ -70,28 +54,6 @@ pub mod utils {
|
||||
radarr_data
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_search_reset {
|
||||
($radarr_data:expr) => {
|
||||
assert!(!$radarr_data.is_searching);
|
||||
assert!($radarr_data.search.is_none());
|
||||
assert!($radarr_data.filter.is_none());
|
||||
assert!($radarr_data.filtered_movies.is_none());
|
||||
assert!($radarr_data.filtered_collections.is_none());
|
||||
assert!($radarr_data.add_searched_movies.is_none());
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_filter_reset {
|
||||
($radarr_data:expr) => {
|
||||
assert!(!$radarr_data.is_filtering);
|
||||
assert!($radarr_data.filter.is_none());
|
||||
assert!($radarr_data.filtered_movies.is_none());
|
||||
assert!($radarr_data.filtered_collections.is_none());
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_movie_info_tabs_reset {
|
||||
($radarr_data:expr) => {
|
||||
|
||||
Reference in New Issue
Block a user