Partial implementation of Tasks and Logs and test refactor

This commit is contained in:
2023-08-08 10:50:06 -06:00
parent 9d943a266e
commit 519778c0ca
42 changed files with 9914 additions and 9436 deletions
+212
View File
@@ -0,0 +1,212 @@
#[cfg(test)]
mod tests {
use anyhow::anyhow;
use pretty_assertions::{assert_eq, assert_str_eq};
use tokio::sync::mpsc;
use crate::app::radarr::{ActiveRadarrBlock, RadarrData};
use crate::app::{App, Data, RadarrConfig, DEFAULT_ROUTE};
use crate::models::{HorizontallyScrollableText, Route, TabRoute};
use crate::network::radarr_network::RadarrEvent;
use crate::network::NetworkEvent;
#[test]
fn test_app_default() {
let app = App::default();
assert_eq!(app.navigation_stack, vec![DEFAULT_ROUTE]);
assert!(app.network_tx.is_none());
assert_eq!(app.error, HorizontallyScrollableText::default());
assert!(app.response.is_empty());
assert_eq!(app.server_tabs.index, 0);
assert_eq!(
app.server_tabs.tabs,
vec![
TabRoute {
title: "Radarr",
route: ActiveRadarrBlock::Movies.into(),
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ",
contextual_help: None,
},
TabRoute {
title: "Sonarr",
route: Route::Sonarr,
help: "<tab> change servarr | <q> quit ",
contextual_help: None,
},
]
);
assert_str_eq!(app.title, "Managarr");
assert_eq!(app.tick_until_poll, 400);
assert_eq!(app.ticks_until_scroll, 4);
assert_eq!(app.tick_count, 0);
assert!(!app.is_loading);
assert!(!app.is_routing);
assert!(!app.should_refresh);
assert!(!app.should_ignore_quit_key);
}
#[test]
fn test_navigation_stack_methods() {
let mut app = App::default();
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Downloads.into()
);
assert!(app.is_routing);
app.is_routing = false;
app.pop_and_push_navigation_stack(ActiveRadarrBlock::Collections.into());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert!(app.is_routing);
app.is_routing = false;
app.pop_navigation_stack();
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
assert!(app.is_routing);
app.is_routing = false;
app.pop_navigation_stack();
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
assert!(app.is_routing);
}
#[test]
fn test_reset_tick_count() {
let mut app = App {
tick_count: 2,
..App::default()
};
app.reset_tick_count();
assert_eq!(app.tick_count, 0);
}
#[test]
fn test_reset() {
let mut app = App {
tick_count: 2,
error: "Test error".to_owned().into(),
data: Data {
radarr_data: RadarrData {
version: "test".to_owned(),
..RadarrData::default()
},
},
..App::default()
};
app.reset();
assert_eq!(app.tick_count, 0);
assert_eq!(app.error, HorizontallyScrollableText::default());
assert!(app.data.radarr_data.version.is_empty());
}
#[test]
fn test_handle_error() {
let mut app = App::default();
let test_string = "Testing";
app.handle_error(anyhow!(test_string));
assert_eq!(app.error.text, test_string);
app.handle_error(anyhow!("Testing a different error"));
assert_eq!(app.error.text, test_string);
}
#[tokio::test]
async fn test_on_tick_first_render() {
let (sync_network_tx, mut sync_network_rx) = mpsc::channel::<NetworkEvent>(500);
let mut app = App {
tick_until_poll: 2,
network_tx: Some(sync_network_tx),
..App::default()
};
assert_eq!(app.tick_count, 0);
app.on_tick(true).await;
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetQualityProfiles.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetTags.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetRootFolders.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetOverview.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetStatus.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetMovies.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetDownloads.into()
);
assert!(!app.is_routing);
assert!(!app.should_refresh);
assert_eq!(app.tick_count, 1);
}
#[tokio::test]
async fn test_on_tick_routing() {
let mut app = App {
tick_until_poll: 2,
tick_count: 2,
is_routing: true,
..App::default()
};
app.on_tick(false).await;
assert!(!app.is_routing);
}
#[tokio::test]
async fn test_on_tick_should_refresh() {
let mut app = App {
tick_until_poll: 2,
tick_count: 2,
should_refresh: true,
..App::default()
};
app.on_tick(false).await;
assert!(!app.should_refresh);
}
#[test]
fn test_radarr_config_default() {
let radarr_config = RadarrConfig::default();
assert_str_eq!(radarr_config.host, "localhost");
assert_eq!(radarr_config.port, Some(7878));
assert!(radarr_config.api_token.is_empty());
}
}
+5 -215
View File
@@ -9,8 +9,11 @@ use crate::app::radarr::{ActiveRadarrBlock, RadarrData};
use crate::models::{HorizontallyScrollableText, Route, TabRoute, TabState};
use crate::network::NetworkEvent;
pub(crate) mod key_binding;
pub(crate) mod radarr;
#[cfg(test)]
#[path = "app_tests.rs"]
mod app_tests;
pub mod key_binding;
pub mod radarr;
const DEFAULT_ROUTE: Route = Route::Radarr(ActiveRadarrBlock::Movies, None);
@@ -174,216 +177,3 @@ impl Default for RadarrConfig {
}
}
}
#[cfg(test)]
mod tests {
use anyhow::anyhow;
use pretty_assertions::{assert_eq, assert_str_eq};
use tokio::sync::mpsc;
use crate::app::radarr::{ActiveRadarrBlock, RadarrData};
use crate::app::{App, Data, RadarrConfig, DEFAULT_ROUTE};
use crate::models::{HorizontallyScrollableText, Route, TabRoute};
use crate::network::radarr_network::RadarrEvent;
use crate::network::NetworkEvent;
#[test]
fn test_app_default() {
let app = App::default();
assert_eq!(app.navigation_stack, vec![DEFAULT_ROUTE]);
assert!(app.network_tx.is_none());
assert_eq!(app.error, HorizontallyScrollableText::default());
assert!(app.response.is_empty());
assert_eq!(app.server_tabs.index, 0);
assert_eq!(
app.server_tabs.tabs,
vec![
TabRoute {
title: "Radarr",
route: ActiveRadarrBlock::Movies.into(),
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ",
contextual_help: None,
},
TabRoute {
title: "Sonarr",
route: Route::Sonarr,
help: "<tab> change servarr | <q> quit ",
contextual_help: None,
}
]
);
assert_str_eq!(app.title, "Managarr");
assert_eq!(app.tick_until_poll, 400);
assert_eq!(app.ticks_until_scroll, 4);
assert_eq!(app.tick_count, 0);
assert!(!app.is_loading);
assert!(!app.is_routing);
assert!(!app.should_refresh);
assert!(!app.should_ignore_quit_key);
}
#[test]
fn test_navigation_stack_methods() {
let mut app = App::default();
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Downloads.into()
);
assert!(app.is_routing);
app.is_routing = false;
app.pop_and_push_navigation_stack(ActiveRadarrBlock::Collections.into());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert!(app.is_routing);
app.is_routing = false;
app.pop_navigation_stack();
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
assert!(app.is_routing);
app.is_routing = false;
app.pop_navigation_stack();
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
assert!(app.is_routing);
}
#[test]
fn test_reset_tick_count() {
let mut app = App {
tick_count: 2,
..App::default()
};
app.reset_tick_count();
assert_eq!(app.tick_count, 0);
}
#[test]
fn test_reset() {
let mut app = App {
tick_count: 2,
error: "Test error".to_owned().into(),
data: Data {
radarr_data: RadarrData {
version: "test".to_owned(),
..RadarrData::default()
},
},
..App::default()
};
app.reset();
assert_eq!(app.tick_count, 0);
assert_eq!(app.error, HorizontallyScrollableText::default());
assert!(app.data.radarr_data.version.is_empty());
}
#[test]
fn test_handle_error() {
let mut app = App::default();
let test_string = "Testing";
app.handle_error(anyhow!(test_string));
assert_eq!(app.error.text, test_string);
app.handle_error(anyhow!("Testing a different error"));
assert_eq!(app.error.text, test_string);
}
#[tokio::test]
async fn test_on_tick_first_render() {
let (sync_network_tx, mut sync_network_rx) = mpsc::channel::<NetworkEvent>(500);
let mut app = App {
tick_until_poll: 2,
network_tx: Some(sync_network_tx),
..App::default()
};
assert_eq!(app.tick_count, 0);
app.on_tick(true).await;
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetQualityProfiles.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetTags.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetRootFolders.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetOverview.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetStatus.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetMovies.into()
);
assert_eq!(
sync_network_rx.recv().await.unwrap(),
RadarrEvent::GetDownloads.into()
);
assert!(!app.is_routing);
assert!(!app.should_refresh);
assert_eq!(app.tick_count, 1);
}
#[tokio::test]
async fn test_on_tick_routing() {
let mut app = App {
tick_until_poll: 2,
tick_count: 2,
is_routing: true,
..App::default()
};
app.on_tick(false).await;
assert!(!app.is_routing);
}
#[tokio::test]
async fn test_on_tick_should_refresh() {
let mut app = App {
tick_until_poll: 2,
tick_count: 2,
should_refresh: true,
..App::default()
};
app.on_tick(false).await;
assert!(!app.should_refresh);
}
#[test]
fn test_radarr_config_default() {
let radarr_config = RadarrConfig::default();
assert_str_eq!(radarr_config.host, "localhost");
assert_eq!(radarr_config.port, Some(7878));
assert!(radarr_config.api_token.is_empty());
}
}
+23 -1234
View File
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
#[cfg(test)]
pub mod utils {
use crate::app::radarr::RadarrData;
use crate::models::radarr_models::{
AddMovieSearchResult, Collection, CollectionMovie, Credit, Log, MinimumAvailability, Monitor,
Movie, MovieHistoryItem, Release, ReleaseField, RootFolder,
};
use crate::models::ScrollableText;
pub fn create_test_radarr_data<'a>() -> RadarrData<'a> {
let mut radarr_data = RadarrData {
is_searching: true,
is_filtering: true,
delete_movie_files: true,
add_list_exclusion: true,
search: "test search".to_owned().into(),
filter: "test filter".to_owned().into(),
edit_path: "test path".to_owned().into(),
edit_tags: "usenet, test".to_owned().into(),
edit_monitored: Some(true),
edit_search_on_add: Some(true),
file_details: "test file details".to_owned(),
audio_details: "test audio details".to_owned(),
video_details: "test video details".to_owned(),
movie_details: ScrollableText::with_string("test movie details".to_owned()),
..RadarrData::default()
};
radarr_data
.movie_history
.set_items(vec![MovieHistoryItem::default()]);
radarr_data.movie_cast.set_items(vec![Credit::default()]);
radarr_data.movie_crew.set_items(vec![Credit::default()]);
radarr_data
.movie_releases
.set_items(vec![Release::default()]);
radarr_data.movie_info_tabs.index = 1;
radarr_data.monitor_list.set_items(vec![Monitor::default()]);
radarr_data
.minimum_availability_list
.set_items(vec![MinimumAvailability::default()]);
radarr_data
.quality_profile_list
.set_items(vec![String::default()]);
radarr_data
.root_folder_list
.set_items(vec![RootFolder::default()]);
radarr_data
.movie_releases_sort
.set_items(vec![ReleaseField::default()]);
radarr_data.sort_ascending = Some(true);
radarr_data
.filtered_movies
.set_items(vec![Movie::default()]);
radarr_data
.filtered_collections
.set_items(vec![Collection::default()]);
radarr_data
.add_searched_movies
.set_items(vec![AddMovieSearchResult::default()]);
radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
radarr_data.logs.set_items(vec![Log::default()]);
radarr_data
}
#[macro_export]
macro_rules! assert_search_reset {
($radarr_data:expr) => {
assert!(!$radarr_data.is_searching);
assert!($radarr_data.search.text.is_empty());
assert!($radarr_data.filter.text.is_empty());
assert!($radarr_data.filtered_movies.items.is_empty());
assert!($radarr_data.filtered_collections.items.is_empty());
assert!($radarr_data.add_searched_movies.items.is_empty());
};
}
#[macro_export]
macro_rules! assert_edit_media_reset {
($radarr_data:expr) => {
assert!($radarr_data.edit_monitored.is_none());
assert!($radarr_data.edit_search_on_add.is_none());
assert!($radarr_data.edit_path.text.is_empty());
assert!($radarr_data.edit_tags.text.is_empty());
};
}
#[macro_export]
macro_rules! assert_filter_reset {
($radarr_data:expr) => {
assert!(!$radarr_data.is_filtering);
assert!($radarr_data.filter.text.is_empty());
assert!($radarr_data.filtered_movies.items.is_empty());
assert!($radarr_data.filtered_collections.items.is_empty());
};
}
#[macro_export]
macro_rules! assert_movie_info_tabs_reset {
($radarr_data:expr) => {
assert!($radarr_data.file_details.is_empty());
assert!($radarr_data.audio_details.is_empty());
assert!($radarr_data.video_details.is_empty());
assert!($radarr_data.movie_details.get_text().is_empty());
assert!($radarr_data.movie_history.items.is_empty());
assert!($radarr_data.movie_cast.items.is_empty());
assert!($radarr_data.movie_crew.items.is_empty());
assert!($radarr_data.movie_releases.items.is_empty());
assert!($radarr_data.movie_releases_sort.items.is_empty());
assert!($radarr_data.sort_ascending.is_none());
assert_eq!($radarr_data.movie_info_tabs.index, 0);
};
}
#[macro_export]
macro_rules! assert_preferences_selections_reset {
($radarr_data:expr) => {
assert!($radarr_data.monitor_list.items.is_empty());
assert!($radarr_data.minimum_availability_list.items.is_empty());
assert!($radarr_data.quality_profile_list.items.is_empty());
assert!($radarr_data.root_folder_list.items.is_empty());
};
}
}
File diff suppressed because it is too large Load Diff
+4 -84
View File
@@ -3,6 +3,10 @@ use std::fmt::{Display, Formatter};
use crossterm::event::{KeyCode, KeyEvent};
#[cfg(test)]
#[path = "key_tests.rs"]
mod key_tests;
#[derive(Debug, PartialEq, Eq)]
pub enum Key {
Up,
@@ -76,87 +80,3 @@ impl From<KeyEvent> for Key {
}
}
}
#[cfg(test)]
mod tests {
use crossterm::event::{KeyCode, KeyEvent};
use pretty_assertions::{assert_eq, assert_str_eq};
use crate::event::key::Key;
#[test]
fn test_key_formatter() {
assert_str_eq!(format!("{}", Key::Esc), "<Esc>");
}
#[test]
fn test_key_formatter_char() {
assert_str_eq!(format!("{}", Key::Char('q')), "<q>");
}
#[test]
fn test_key_from_up() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Up)), Key::Up);
}
#[test]
fn test_key_from_down() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Down)), Key::Down);
}
#[test]
fn test_key_from_left() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Left)), Key::Left);
}
#[test]
fn test_key_from_right() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Right)), Key::Right);
}
#[test]
fn test_key_from_backspace() {
assert_eq!(
Key::from(KeyEvent::from(KeyCode::Backspace)),
Key::Backspace
);
}
#[test]
fn test_key_from_home() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Home)), Key::Home);
}
#[test]
fn test_key_from_end() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::End)), Key::End);
}
#[test]
fn test_key_from_delete() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Delete)), Key::Delete);
}
#[test]
fn test_key_from_enter() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Enter)), Key::Enter);
}
#[test]
fn test_key_from_esc() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Esc)), Key::Esc);
}
#[test]
fn test_key_from_char() {
assert_eq!(
Key::from(KeyEvent::from(KeyCode::Char('q'))),
Key::Char('q')
)
}
#[test]
fn test_key_from_unknown() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Pause)), Key::Unknown);
}
}
+83
View File
@@ -0,0 +1,83 @@
#[cfg(test)]
mod tests {
use crossterm::event::{KeyCode, KeyEvent};
use pretty_assertions::{assert_eq, assert_str_eq};
use crate::event::key::Key;
#[test]
fn test_key_formatter() {
assert_str_eq!(format!("{}", Key::Esc), "<Esc>");
}
#[test]
fn test_key_formatter_char() {
assert_str_eq!(format!("{}", Key::Char('q')), "<q>");
}
#[test]
fn test_key_from_up() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Up)), Key::Up);
}
#[test]
fn test_key_from_down() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Down)), Key::Down);
}
#[test]
fn test_key_from_left() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Left)), Key::Left);
}
#[test]
fn test_key_from_right() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Right)), Key::Right);
}
#[test]
fn test_key_from_backspace() {
assert_eq!(
Key::from(KeyEvent::from(KeyCode::Backspace)),
Key::Backspace
);
}
#[test]
fn test_key_from_home() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Home)), Key::Home);
}
#[test]
fn test_key_from_end() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::End)), Key::End);
}
#[test]
fn test_key_from_delete() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Delete)), Key::Delete);
}
#[test]
fn test_key_from_enter() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Enter)), Key::Enter);
}
#[test]
fn test_key_from_esc() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Esc)), Key::Esc);
}
#[test]
fn test_key_from_char() {
assert_eq!(
Key::from(KeyEvent::from(KeyCode::Char('q'))),
Key::Char('q')
)
}
#[test]
fn test_key_from_unknown() {
assert_eq!(Key::from(KeyEvent::from(KeyCode::Pause)), Key::Unknown);
}
}
+416
View File
@@ -0,0 +1,416 @@
#[cfg(test)]
#[macro_use]
mod test_utils {
#[macro_export]
macro_rules! simple_stateful_iterable_vec {
($name:ident) => {
vec![
$name {
title: "Test 1".to_owned(),
..$name::default()
},
$name {
title: "Test 2".to_owned(),
..$name::default()
},
]
};
($name:ident, $title_ident:ident) => {
vec![
$name {
title: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
title: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
]
};
($name:ident, $title_ident:ident, $field:ident) => {
vec![
$name {
$field: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
$field: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
]
};
}
#[macro_export]
macro_rules! extended_stateful_iterable_vec {
($name:ident) => {
vec![
$name {
title: "Test 1".to_owned(),
..$name::default()
},
$name {
title: "Test 2".to_owned(),
..$name::default()
},
$name {
title: "Test 3".to_owned(),
..$name::default()
},
]
};
($name:ident, $title_ident:ident) => {
vec![
$name {
title: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
title: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
$name {
title: $title_ident::from("Test 3".to_owned()),
..$name::default()
},
]
};
($name:ident, $title_ident:ident, $field:ident) => {
vec![
$name {
$field: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
$field: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
$name {
$field: $title_ident::from("Test 3".to_owned()),
..$name::default()
},
]
};
}
#[macro_export]
macro_rules! test_iterable_scroll {
($func:ident, $handler:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 2");
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 1");
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(simple_stateful_iterable_vec!($items));
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 2"
);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 2"
);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 2"
);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 1"
);
}
};
}
#[macro_export]
macro_rules! test_enum_scroll {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let reference_vec = Vec::from_iter($name::iter());
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(reference_vec.clone());
if key == Key::Up {
for i in (0..reference_vec.len()).rev() {
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[i]
);
}
} else {
for i in 0..reference_vec.len() {
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[(i + 1) % reference_vec.len()]
);
}
}
}
};
}
#[macro_export]
macro_rules! test_iterable_home_and_end {
($func:ident, $handler:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items(vec![
"Test 1".to_owned(),
"Test 2".to_owned(),
"Test 3".to_owned(),
]);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 3");
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 1");
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(extended_stateful_iterable_vec!($items));
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 1"
);
}
};
}
#[macro_export]
macro_rules! test_enum_home_and_end {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[test]
fn $func() {
let reference_vec = Vec::from_iter($name::iter());
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(reference_vec.clone());
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[reference_vec.len() - 1]
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[0]
);
}
};
}
#[macro_export]
macro_rules! test_text_box_home_end_keys {
($handler:ident, $block:expr, $field:ident) => {
let mut app = App::default();
app.data.radarr_data.$field = "Test".to_owned().into();
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 4);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 0);
};
}
#[macro_export]
macro_rules! test_text_box_left_right_keys {
($handler:ident, $block:expr, $field:ident) => {
let mut app = App::default();
app.data.radarr_data.$field = "Test".to_owned().into();
$handler::with(&DEFAULT_KEYBINDINGS.left.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 1);
$handler::with(&DEFAULT_KEYBINDINGS.right.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 0);
};
}
#[macro_export]
macro_rules! test_handler_delegation {
($base:expr, $active_block:expr) => {
let mut app = App::default();
app.push_navigation_stack($base.clone().into());
app.push_navigation_stack($active_block.clone().into());
RadarrHandler::with(
&DEFAULT_KEYBINDINGS.esc.key,
&mut app,
&$active_block,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &$base.into());
};
}
}
+33
View File
@@ -0,0 +1,33 @@
#[cfg(test)]
mod tests {
use rstest::rstest;
use crate::app::App;
use crate::event::Key;
use crate::handlers::{handle_clear_errors, handle_prompt_toggle};
#[test]
fn test_handle_clear_errors() {
let mut app = App::default();
app.error = "test error".to_owned().into();
handle_clear_errors(&mut app);
assert!(app.error.text.is_empty());
}
#[rstest]
fn test_handle_prompt_toggle_left_right(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
assert!(!app.data.radarr_data.prompt_confirm);
handle_prompt_toggle(&mut app, &key);
assert!(app.data.radarr_data.prompt_confirm);
handle_prompt_toggle(&mut app, &key);
assert!(!app.data.radarr_data.prompt_confirm);
}
}
+8 -451
View File
@@ -7,6 +7,14 @@ use crate::models::{HorizontallyScrollableText, Route};
mod radarr_handlers;
#[cfg(test)]
#[path = "handlers_tests.rs"]
mod handlers_tests;
#[cfg(test)]
#[path = "handler_test_utils.rs"]
pub mod handler_test_utils;
pub trait KeyEventHandler<'a, 'b, T: Into<Route>> {
fn handle_key_event(&mut self) {
let key = self.get_key();
@@ -94,454 +102,3 @@ macro_rules! handle_text_box_keys {
}
};
}
#[cfg(test)]
#[macro_use]
mod test_utils {
#[macro_export]
macro_rules! simple_stateful_iterable_vec {
($name:ident) => {
vec![
$name {
title: "Test 1".to_owned(),
..$name::default()
},
$name {
title: "Test 2".to_owned(),
..$name::default()
},
]
};
($name:ident, $title_ident:ident) => {
vec![
$name {
title: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
title: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
]
};
($name:ident, $title_ident:ident, $field:ident) => {
vec![
$name {
$field: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
$field: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
]
};
}
#[macro_export]
macro_rules! extended_stateful_iterable_vec {
($name:ident) => {
vec![
$name {
title: "Test 1".to_owned(),
..$name::default()
},
$name {
title: "Test 2".to_owned(),
..$name::default()
},
$name {
title: "Test 3".to_owned(),
..$name::default()
},
]
};
($name:ident, $title_ident:ident) => {
vec![
$name {
title: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
title: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
$name {
title: $title_ident::from("Test 3".to_owned()),
..$name::default()
},
]
};
($name:ident, $title_ident:ident, $field:ident) => {
vec![
$name {
$field: $title_ident::from("Test 1".to_owned()),
..$name::default()
},
$name {
$field: $title_ident::from("Test 2".to_owned()),
..$name::default()
},
$name {
$field: $title_ident::from("Test 3".to_owned()),
..$name::default()
},
]
};
}
#[macro_export]
macro_rules! test_iterable_scroll {
($func:ident, $handler:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 2");
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 1");
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(simple_stateful_iterable_vec!($items));
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 2"
);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 2"
);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 2"
);
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 1"
);
}
};
}
#[macro_export]
macro_rules! test_enum_scroll {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let reference_vec = Vec::from_iter($name::iter());
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(reference_vec.clone());
if key == Key::Up {
for i in (0..reference_vec.len()).rev() {
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[i]
);
}
} else {
for i in 0..reference_vec.len() {
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[(i + 1) % reference_vec.len()]
);
}
}
}
};
}
#[macro_export]
macro_rules! test_iterable_home_and_end {
($func:ident, $handler:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items(vec![
"Test 1".to_owned(),
"Test 2".to_owned(),
"Test 3".to_owned(),
]);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 3");
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 1");
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(extended_stateful_iterable_vec!($items));
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 1"
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
.data
.radarr_data
.$data_ref
.current_selection()
.$field
.$conversion_fn(),
"Test 1"
);
}
};
}
#[macro_export]
macro_rules! test_enum_home_and_end {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[test]
fn $func() {
let reference_vec = Vec::from_iter($name::iter());
let mut app = App::default();
app
.data
.radarr_data
.$data_ref
.set_items(reference_vec.clone());
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[reference_vec.len() - 1]
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[0]
);
}
};
}
#[macro_export]
macro_rules! test_text_box_home_end_keys {
($handler:ident, $block:expr, $field:ident) => {
let mut app = App::default();
app.data.radarr_data.$field = "Test".to_owned().into();
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 4);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 0);
};
}
#[macro_export]
macro_rules! test_text_box_left_right_keys {
($handler:ident, $block:expr, $field:ident) => {
let mut app = App::default();
app.data.radarr_data.$field = "Test".to_owned().into();
$handler::with(&DEFAULT_KEYBINDINGS.left.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 1);
$handler::with(&DEFAULT_KEYBINDINGS.right.key, &mut app, &$block, &None).handle();
assert_eq!(*app.data.radarr_data.$field.offset.borrow(), 0);
};
}
#[macro_export]
macro_rules! test_handler_delegation {
($base:expr, $active_block:expr) => {
let mut app = App::default();
app.push_navigation_stack($base.clone().into());
app.push_navigation_stack($active_block.clone().into());
RadarrHandler::with(
&DEFAULT_KEYBINDINGS.esc.key,
&mut app,
&$active_block,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &$base.into());
};
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use crate::app::App;
use crate::event::Key;
use crate::handlers::{handle_clear_errors, handle_prompt_toggle};
#[test]
fn test_handle_clear_errors() {
let mut app = App::default();
app.error = "test error".to_owned().into();
handle_clear_errors(&mut app);
assert!(app.error.text.is_empty());
}
#[rstest]
fn test_handle_prompt_toggle_left_right(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
assert!(!app.data.radarr_data.prompt_confirm);
handle_prompt_toggle(&mut app, &key);
assert!(app.data.radarr_data.prompt_confirm);
handle_prompt_toggle(&mut app, &key);
assert!(!app.data.radarr_data.prompt_confirm);
}
}
@@ -5,6 +5,10 @@ use crate::models::{BlockSelectionState, Scrollable, StatefulTable};
use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
#[cfg(test)]
#[path = "add_movie_handler_tests.rs"]
mod add_movie_handler_tests;
pub(super) struct AddMovieHandler<'a, 'b> {
key: &'a Key,
app: &'a mut App<'b>,
@@ -297,731 +301,3 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
}
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::add_movie_handler::AddMovieHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::{
AddMovieSearchResult, MinimumAvailability, Monitor, RootFolder,
};
use crate::models::HorizontallyScrollableText;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{simple_stateful_iterable_vec, test_enum_scroll, test_iterable_scroll};
use super::*;
test_iterable_scroll!(
test_add_movie_search_results_scroll,
AddMovieHandler,
add_searched_movies,
simple_stateful_iterable_vec!(AddMovieSearchResult, HorizontallyScrollableText),
ActiveRadarrBlock::AddMovieSearchResults,
None,
title,
to_string
);
test_enum_scroll!(
test_add_movie_select_monitor_scroll,
AddMovieHandler,
Monitor,
monitor_list,
ActiveRadarrBlock::AddMovieSelectMonitor,
None
);
test_enum_scroll!(
test_add_movie_select_minimum_availability_scroll,
AddMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_add_movie_select_quality_profile_scroll,
AddMovieHandler,
quality_profile_list,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
None
);
test_iterable_scroll!(
test_add_movie_select_root_folder_scroll,
AddMovieHandler,
root_folder_list,
simple_stateful_iterable_vec!(RootFolder, String, path),
ActiveRadarrBlock::AddMovieSelectRootFolder,
None,
path
);
#[rstest]
fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectRootFolder
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectMinimumAvailability
);
}
}
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::{
extended_stateful_iterable_vec, test_enum_home_and_end, test_iterable_home_and_end,
test_text_box_home_end_keys,
};
use super::*;
test_iterable_home_and_end!(
test_add_movie_search_results_home_end,
AddMovieHandler,
add_searched_movies,
extended_stateful_iterable_vec!(AddMovieSearchResult, HorizontallyScrollableText),
ActiveRadarrBlock::AddMovieSearchResults,
None,
title,
to_string
);
test_enum_home_and_end!(
test_add_movie_select_monitor_home_end,
AddMovieHandler,
Monitor,
monitor_list,
ActiveRadarrBlock::AddMovieSelectMonitor,
None
);
test_enum_home_and_end!(
test_add_movie_select_minimum_availability_home_end,
AddMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_add_movie_select_quality_profile_home_end,
AddMovieHandler,
quality_profile_list,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
None
);
test_iterable_home_and_end!(
test_add_movie_select_root_folder_home_end,
AddMovieHandler,
root_folder_list,
extended_stateful_iterable_vec!(RootFolder, String, path),
ActiveRadarrBlock::AddMovieSelectRootFolder,
None,
path
);
#[test]
fn test_add_movie_search_input_home_end_keys() {
test_text_box_home_end_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieSearchInput,
search
);
}
#[test]
fn test_add_movie_tags_input_home_end_keys() {
test_text_box_home_end_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieTagsInput,
edit_tags
);
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use crate::test_text_box_left_right_keys;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[test]
fn test_add_movie_search_input_left_right_keys() {
test_text_box_left_right_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieSearchInput,
search
);
}
#[test]
fn test_add_movie_tags_input_left_right_keys() {
test_text_box_left_right_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieTagsInput,
edit_tags
);
}
}
mod test_handle_submit {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use rstest::rstest;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::Movie;
use crate::models::BlockSelectionState;
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_add_movie_search_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
}
#[test]
fn test_add_movie_search_results_submit() {
let mut app = App::default();
app
.data
.radarr_data
.add_searched_movies
.set_items(vec![AddMovieSearchResult::default()]);
app.data.radarr_data.quality_profile_map =
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectRootFolder
);
assert!(!app.data.radarr_data.monitor_list.items.is_empty());
assert!(!app
.data
.radarr_data
.minimum_availability_list
.items
.is_empty());
assert!(!app.data.radarr_data.quality_profile_list.items.is_empty());
assert_str_eq!(
app
.data
.radarr_data
.quality_profile_list
.current_selection(),
"A - Test 1"
);
}
#[test]
fn test_add_movie_search_results_submit_does_nothing_on_empty_table() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
}
#[test]
fn test_add_movie_search_results_submit_movie_already_in_library() {
let mut app = App::default();
app
.data
.radarr_data
.add_searched_movies
.set_items(vec![AddMovieSearchResult::default()]);
app
.data
.radarr_data
.movies
.set_items(vec![Movie::default()]);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieAlreadyInLibrary.into()
);
}
#[test]
fn test_add_movie_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_add_movie_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::AddMovie)
);
}
#[rstest]
#[case(ActiveRadarrBlock::AddMovieSelectRootFolder, 0)]
#[case(ActiveRadarrBlock::AddMovieSelectMonitor, 1)]
#[case(ActiveRadarrBlock::AddMovieSelectMinimumAvailability, 2)]
#[case(ActiveRadarrBlock::AddMovieSelectQualityProfile, 3)]
#[case(ActiveRadarrBlock::AddMovieTagsInput, 4)]
fn test_add_movie_prompt_selected_block_submit(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::CollectionDetails)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
if selected_block == ActiveRadarrBlock::AddMovieTagsInput {
assert!(app.should_ignore_quit_key);
}
}
#[rstest]
fn test_add_movie_prompt_selecting_preferences_blocks_submit(
#[values(
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieTagsInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput {
assert!(!app.should_ignore_quit_key);
}
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::{
assert_edit_media_reset, assert_preferences_selections_reset, assert_search_reset,
simple_stateful_iterable_vec,
};
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_add_movie_search_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_search_reset!(app.data.radarr_data);
}
#[test]
fn test_add_movie_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
}
#[rstest]
fn test_add_movie_search_results_esc(
#[values(
ActiveRadarrBlock::AddMovieSearchResults,
ActiveRadarrBlock::AddMovieEmptySearchResults
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
app.push_navigation_stack(active_radarr_block.into());
app
.data
.radarr_data
.add_searched_movies
.set_items(simple_stateful_iterable_vec!(
AddMovieSearchResult,
HorizontallyScrollableText
));
AddMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchInput.into()
);
assert!(app.data.radarr_data.add_searched_movies.items.is_empty());
assert!(app.should_ignore_quit_key);
}
#[test]
fn test_add_movie_already_in_library_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMovieAlreadyInLibrary.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieAlreadyInLibrary,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
}
#[test]
fn test_add_movie_prompt_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
assert_preferences_selections_reset!(app.data.radarr_data);
assert_edit_media_reset!(app.data.radarr_data);
}
#[test]
fn test_add_movie_tags_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
}
#[rstest]
fn test_selecting_preferences_blocks_esc(
#[values(
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieSelectRootFolder
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
app.push_navigation_stack(
(
active_radarr_block,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into()
);
}
}
mod test_handle_key_char {
use super::*;
#[test]
fn test_add_movie_search_input_backspace() {
let mut app = App::default();
app.data.radarr_data.search = "Test".to_owned().into();
AddMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.search.text, "Tes");
}
#[test]
fn test_add_movie_tags_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_tags = "Test".to_owned().into();
AddMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "Tes");
}
#[test]
fn test_add_movie_search_input_char_key() {
let mut app = App::default();
AddMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.search.text, "h");
}
#[test]
fn test_add_movie_tags_input_char_key() {
let mut app = App::default();
AddMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "h");
}
}
}
@@ -0,0 +1,727 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::add_movie_handler::AddMovieHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::{
AddMovieSearchResult, MinimumAvailability, Monitor, RootFolder,
};
use crate::models::HorizontallyScrollableText;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{simple_stateful_iterable_vec, test_enum_scroll, test_iterable_scroll};
use super::*;
test_iterable_scroll!(
test_add_movie_search_results_scroll,
AddMovieHandler,
add_searched_movies,
simple_stateful_iterable_vec!(AddMovieSearchResult, HorizontallyScrollableText),
ActiveRadarrBlock::AddMovieSearchResults,
None,
title,
to_string
);
test_enum_scroll!(
test_add_movie_select_monitor_scroll,
AddMovieHandler,
Monitor,
monitor_list,
ActiveRadarrBlock::AddMovieSelectMonitor,
None
);
test_enum_scroll!(
test_add_movie_select_minimum_availability_scroll,
AddMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_add_movie_select_quality_profile_scroll,
AddMovieHandler,
quality_profile_list,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
None
);
test_iterable_scroll!(
test_add_movie_select_root_folder_scroll,
AddMovieHandler,
root_folder_list,
simple_stateful_iterable_vec!(RootFolder, String, path),
ActiveRadarrBlock::AddMovieSelectRootFolder,
None,
path
);
#[rstest]
fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectRootFolder
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectMinimumAvailability
);
}
}
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::{
extended_stateful_iterable_vec, test_enum_home_and_end, test_iterable_home_and_end,
test_text_box_home_end_keys,
};
use super::*;
test_iterable_home_and_end!(
test_add_movie_search_results_home_end,
AddMovieHandler,
add_searched_movies,
extended_stateful_iterable_vec!(AddMovieSearchResult, HorizontallyScrollableText),
ActiveRadarrBlock::AddMovieSearchResults,
None,
title,
to_string
);
test_enum_home_and_end!(
test_add_movie_select_monitor_home_end,
AddMovieHandler,
Monitor,
monitor_list,
ActiveRadarrBlock::AddMovieSelectMonitor,
None
);
test_enum_home_and_end!(
test_add_movie_select_minimum_availability_home_end,
AddMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_add_movie_select_quality_profile_home_end,
AddMovieHandler,
quality_profile_list,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
None
);
test_iterable_home_and_end!(
test_add_movie_select_root_folder_home_end,
AddMovieHandler,
root_folder_list,
extended_stateful_iterable_vec!(RootFolder, String, path),
ActiveRadarrBlock::AddMovieSelectRootFolder,
None,
path
);
#[test]
fn test_add_movie_search_input_home_end_keys() {
test_text_box_home_end_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieSearchInput,
search
);
}
#[test]
fn test_add_movie_tags_input_home_end_keys() {
test_text_box_home_end_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieTagsInput,
edit_tags
);
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use crate::test_text_box_left_right_keys;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[test]
fn test_add_movie_search_input_left_right_keys() {
test_text_box_left_right_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieSearchInput,
search
);
}
#[test]
fn test_add_movie_tags_input_left_right_keys() {
test_text_box_left_right_keys!(
AddMovieHandler,
ActiveRadarrBlock::AddMovieTagsInput,
edit_tags
);
}
}
mod test_handle_submit {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use rstest::rstest;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::Movie;
use crate::models::BlockSelectionState;
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_add_movie_search_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
}
#[test]
fn test_add_movie_search_results_submit() {
let mut app = App::default();
app
.data
.radarr_data
.add_searched_movies
.set_items(vec![AddMovieSearchResult::default()]);
app.data.radarr_data.quality_profile_map =
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectRootFolder
);
assert!(!app.data.radarr_data.monitor_list.items.is_empty());
assert!(!app
.data
.radarr_data
.minimum_availability_list
.items
.is_empty());
assert!(!app.data.radarr_data.quality_profile_list.items.is_empty());
assert_str_eq!(
app
.data
.radarr_data
.quality_profile_list
.current_selection(),
"A - Test 1"
);
}
#[test]
fn test_add_movie_search_results_submit_does_nothing_on_empty_table() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
}
#[test]
fn test_add_movie_search_results_submit_movie_already_in_library() {
let mut app = App::default();
app
.data
.radarr_data
.add_searched_movies
.set_items(vec![AddMovieSearchResult::default()]);
app
.data
.radarr_data
.movies
.set_items(vec![Movie::default()]);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieAlreadyInLibrary.into()
);
}
#[test]
fn test_add_movie_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_add_movie_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::AddMovie)
);
}
#[rstest]
#[case(ActiveRadarrBlock::AddMovieSelectRootFolder, 0)]
#[case(ActiveRadarrBlock::AddMovieSelectMonitor, 1)]
#[case(ActiveRadarrBlock::AddMovieSelectMinimumAvailability, 2)]
#[case(ActiveRadarrBlock::AddMovieSelectQualityProfile, 3)]
#[case(ActiveRadarrBlock::AddMovieTagsInput, 4)]
fn test_add_movie_prompt_selected_block_submit(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::CollectionDetails)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
if selected_block == ActiveRadarrBlock::AddMovieTagsInput {
assert!(app.should_ignore_quit_key);
}
}
#[rstest]
fn test_add_movie_prompt_selecting_preferences_blocks_submit(
#[values(
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieTagsInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput {
assert!(!app.should_ignore_quit_key);
}
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::utils::create_test_radarr_data;
use crate::{
assert_edit_media_reset, assert_preferences_selections_reset, assert_search_reset,
simple_stateful_iterable_vec,
};
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_add_movie_search_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_search_reset!(app.data.radarr_data);
}
#[test]
fn test_add_movie_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
}
#[rstest]
fn test_add_movie_search_results_esc(
#[values(
ActiveRadarrBlock::AddMovieSearchResults,
ActiveRadarrBlock::AddMovieEmptySearchResults
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
app.push_navigation_stack(active_radarr_block.into());
app
.data
.radarr_data
.add_searched_movies
.set_items(simple_stateful_iterable_vec!(
AddMovieSearchResult,
HorizontallyScrollableText
));
AddMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchInput.into()
);
assert!(app.data.radarr_data.add_searched_movies.items.is_empty());
assert!(app.should_ignore_quit_key);
}
#[test]
fn test_add_movie_already_in_library_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMovieAlreadyInLibrary.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieAlreadyInLibrary,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
}
#[test]
fn test_add_movie_prompt_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMovieSearchResults.into()
);
assert_preferences_selections_reset!(app.data.radarr_data);
assert_edit_media_reset!(app.data.radarr_data);
}
#[test]
fn test_add_movie_tags_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
);
}
#[rstest]
fn test_selecting_preferences_blocks_esc(
#[values(
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieSelectRootFolder
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
app.push_navigation_stack(
(
active_radarr_block,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into()
);
}
}
mod test_handle_key_char {
use super::*;
#[test]
fn test_add_movie_search_input_backspace() {
let mut app = App::default();
app.data.radarr_data.search = "Test".to_owned().into();
AddMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.search.text, "Tes");
}
#[test]
fn test_add_movie_tags_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_tags = "Test".to_owned().into();
AddMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "Tes");
}
#[test]
fn test_add_movie_search_input_char_key() {
let mut app = App::default();
AddMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.search.text, "h");
}
#[test]
fn test_add_movie_tags_input_char_key() {
let mut app = App::default();
AddMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::AddMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "h");
}
}
}
@@ -7,6 +7,10 @@ use crate::event::Key;
use crate::handlers::KeyEventHandler;
use crate::models::{BlockSelectionState, Scrollable};
#[cfg(test)]
#[path = "collection_details_handler_tests.rs"]
mod collection_details_handler_tests;
pub(super) struct CollectionDetailsHandler<'a, 'b> {
key: &'a Key,
app: &'a mut App<'b>,
@@ -132,230 +136,3 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan
}
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::collection_details_handler::CollectionDetailsHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::CollectionMovie;
use crate::models::HorizontallyScrollableText;
mod test_handle_scroll_up_and_down {
use rstest::rstest;
use crate::{simple_stateful_iterable_vec, test_iterable_scroll};
use super::*;
test_iterable_scroll!(
test_collection_details_scroll,
CollectionDetailsHandler,
collection_movies,
simple_stateful_iterable_vec!(CollectionMovie, HorizontallyScrollableText),
ActiveRadarrBlock::CollectionDetails,
None,
title,
to_string
);
}
mod test_handle_home_end {
use crate::{extended_stateful_iterable_vec, test_iterable_home_and_end};
use super::*;
test_iterable_home_and_end!(
test_collection_details_home_end,
CollectionDetailsHandler,
collection_movies,
extended_stateful_iterable_vec!(CollectionMovie, HorizontallyScrollableText),
ActiveRadarrBlock::CollectionDetails,
None,
title,
to_string
);
}
mod test_handle_submit {
use bimap::BiMap;
use pretty_assertions::assert_eq;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::Movie;
use crate::models::BlockSelectionState;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_collection_details_submit() {
let mut app = App::default();
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
app.data.radarr_data.quality_profile_map =
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
CollectionDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails)
)
.into()
);
assert!(!app.data.radarr_data.monitor_list.items.is_empty());
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectRootFolder
);
assert!(!app
.data
.radarr_data
.minimum_availability_list
.items
.is_empty());
assert!(!app.data.radarr_data.quality_profile_list.items.is_empty());
assert_str_eq!(
app
.data
.radarr_data
.quality_profile_list
.current_selection(),
"A - Test 1"
);
}
#[test]
fn test_collection_details_submit_movie_already_in_library() {
let mut app = App::default();
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
app
.data
.radarr_data
.movies
.set_items(vec![Movie::default()]);
CollectionDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ViewMovieOverview.into()
);
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_esc_collection_details() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
CollectionDetailsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert!(app.data.radarr_data.collection_movies.items.is_empty());
}
#[test]
fn test_esc_view_movie_overview() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
app.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into());
CollectionDetailsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::ViewMovieOverview,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::CollectionDetails.into()
);
}
}
mod test_handle_key_char {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use serde_json::Number;
use strum::IntoEnumIterator;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::radarr_models::{Collection, MinimumAvailability};
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable;
use crate::test_edit_collection_key;
use super::*;
#[test]
fn test_edit_key() {
test_edit_collection_key!(
CollectionDetailsHandler,
ActiveRadarrBlock::CollectionDetails,
ActiveRadarrBlock::CollectionDetails
);
}
}
}
@@ -0,0 +1,226 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::collection_details_handler::CollectionDetailsHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::CollectionMovie;
use crate::models::HorizontallyScrollableText;
mod test_handle_scroll_up_and_down {
use rstest::rstest;
use crate::{simple_stateful_iterable_vec, test_iterable_scroll};
use super::*;
test_iterable_scroll!(
test_collection_details_scroll,
CollectionDetailsHandler,
collection_movies,
simple_stateful_iterable_vec!(CollectionMovie, HorizontallyScrollableText),
ActiveRadarrBlock::CollectionDetails,
None,
title,
to_string
);
}
mod test_handle_home_end {
use crate::{extended_stateful_iterable_vec, test_iterable_home_and_end};
use super::*;
test_iterable_home_and_end!(
test_collection_details_home_end,
CollectionDetailsHandler,
collection_movies,
extended_stateful_iterable_vec!(CollectionMovie, HorizontallyScrollableText),
ActiveRadarrBlock::CollectionDetails,
None,
title,
to_string
);
}
mod test_handle_submit {
use bimap::BiMap;
use pretty_assertions::assert_eq;
use crate::app::radarr::ADD_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::Movie;
use crate::models::BlockSelectionState;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_collection_details_submit() {
let mut app = App::default();
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
app.data.radarr_data.quality_profile_map =
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
app.data.radarr_data.selected_block = BlockSelectionState::new(&ADD_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
CollectionDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails)
)
.into()
);
assert!(!app.data.radarr_data.monitor_list.items.is_empty());
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::AddMovieSelectRootFolder
);
assert!(!app
.data
.radarr_data
.minimum_availability_list
.items
.is_empty());
assert!(!app.data.radarr_data.quality_profile_list.items.is_empty());
assert_str_eq!(
app
.data
.radarr_data
.quality_profile_list
.current_selection(),
"A - Test 1"
);
}
#[test]
fn test_collection_details_submit_movie_already_in_library() {
let mut app = App::default();
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
app
.data
.radarr_data
.movies
.set_items(vec![Movie::default()]);
CollectionDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ViewMovieOverview.into()
);
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_esc_collection_details() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
CollectionDetailsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert!(app.data.radarr_data.collection_movies.items.is_empty());
}
#[test]
fn test_esc_view_movie_overview() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
app.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into());
CollectionDetailsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::ViewMovieOverview,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::CollectionDetails.into()
);
}
}
mod test_handle_key_char {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use serde_json::Number;
use strum::IntoEnumIterator;
use crate::app::radarr::radarr_test_utils::utils::create_test_radarr_data;
use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::radarr_models::{Collection, MinimumAvailability};
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable;
use crate::test_edit_collection_key;
use super::*;
#[test]
fn test_edit_key() {
test_edit_collection_key!(
CollectionDetailsHandler,
ActiveRadarrBlock::CollectionDetails,
ActiveRadarrBlock::CollectionDetails
);
}
}
}
@@ -4,6 +4,10 @@ use crate::event::Key;
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
use crate::network::radarr_network::RadarrEvent;
#[cfg(test)]
#[path = "delete_movie_handler_tests.rs"]
mod delete_movie_handler_tests;
pub(super) struct DeleteMovieHandler<'a, 'b> {
key: &'a Key,
app: &'a mut App<'b>,
@@ -90,204 +94,3 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
fn handle_char_key_event(&mut self) {}
}
#[cfg(test)]
mod tests {
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::delete_movie_handler::DeleteMovieHandler;
use crate::handlers::KeyEventHandler;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::DELETE_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use super::*;
#[rstest]
fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::DeleteMovieToggleDeleteFile
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::DeleteMovieConfirmPrompt
);
}
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle();
assert!(app.data.radarr_data.prompt_confirm);
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use crate::app::radarr::DELETE_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_delete_movie_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true;
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
assert!(!app.data.radarr_data.prompt_confirm);
assert!(!app.data.radarr_data.delete_movie_files);
assert!(!app.data.radarr_data.add_list_exclusion);
}
#[test]
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true;
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::DeleteMovie)
);
assert!(app.should_refresh);
assert!(app.data.radarr_data.prompt_confirm);
assert!(app.data.radarr_data.delete_movie_files);
assert!(app.data.radarr_data.add_list_exclusion);
}
#[test]
fn test_delete_movie_toggle_delete_files_submit() {
let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into();
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.delete_movie_files, true);
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.delete_movie_files, false);
}
}
mod test_handle_esc {
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_delete_movie_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true;
DeleteMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert!(!app.data.radarr_data.prompt_confirm);
assert!(!app.data.radarr_data.delete_movie_files);
assert!(!app.data.radarr_data.add_list_exclusion);
}
}
}
@@ -0,0 +1,200 @@
#[cfg(test)]
mod tests {
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::delete_movie_handler::DeleteMovieHandler;
use crate::handlers::KeyEventHandler;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::DELETE_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use super::*;
#[rstest]
fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::DeleteMovieToggleDeleteFile
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::DeleteMovieConfirmPrompt
);
}
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle();
assert!(app.data.radarr_data.prompt_confirm);
DeleteMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::DeleteMoviePrompt, &None)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use crate::app::radarr::DELETE_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_delete_movie_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true;
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
assert!(!app.data.radarr_data.prompt_confirm);
assert!(!app.data.radarr_data.delete_movie_files);
assert!(!app.data.radarr_data.add_list_exclusion);
}
#[test]
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true;
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::DeleteMovie)
);
assert!(app.should_refresh);
assert!(app.data.radarr_data.prompt_confirm);
assert!(app.data.radarr_data.delete_movie_files);
assert!(app.data.radarr_data.add_list_exclusion);
}
#[test]
fn test_delete_movie_toggle_delete_files_submit() {
let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into();
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&DELETE_MOVIE_SELECTION_BLOCKS);
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.delete_movie_files, true);
DeleteMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.delete_movie_files, false);
}
}
mod test_handle_esc {
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_delete_movie_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.delete_movie_files = true;
app.data.radarr_data.add_list_exclusion = true;
DeleteMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::DeleteMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert!(!app.data.radarr_data.prompt_confirm);
assert!(!app.data.radarr_data.delete_movie_files);
assert!(!app.data.radarr_data.add_list_exclusion);
}
}
}
@@ -7,6 +7,10 @@ use crate::models::Scrollable;
use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
#[cfg(test)]
#[path = "edit_collection_handler_tests.rs"]
mod edit_collection_handler_tests;
pub(super) struct EditCollectionHandler<'a, 'b> {
key: &'a Key,
app: &'a mut App<'b>,
@@ -204,507 +208,3 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
}
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::edit_collection_handler::EditCollectionHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::MinimumAvailability;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{test_enum_scroll, test_iterable_scroll};
use super::*;
test_enum_scroll!(
test_edit_collection_select_minimum_availability_scroll,
EditCollectionHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_edit_collection_select_quality_profile_scroll,
EditCollectionHandler,
quality_profile_list,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
None
);
#[rstest]
fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
EditCollectionHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditCollectionToggleMonitored
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditCollectionSelectQualityProfile
);
}
}
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::{test_enum_home_and_end, test_iterable_home_and_end, test_text_box_home_end_keys};
use super::*;
test_enum_home_and_end!(
test_edit_collection_select_minimum_availability_home_end,
EditCollectionHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_edit_collection_select_quality_profile_scroll,
EditCollectionHandler,
quality_profile_list,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
None
);
#[test]
fn test_edit_collection_root_folder_path_input_home_end_keys() {
test_text_box_home_end_keys!(
EditCollectionHandler,
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
edit_path
);
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use crate::test_text_box_left_right_keys;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
EditCollectionHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert!(app.data.radarr_data.prompt_confirm);
EditCollectionHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[test]
fn test_edit_collection_root_folder_path_input_left_right_keys() {
test_text_box_left_right_keys!(
EditCollectionHandler,
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
edit_path
);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::{BlockSelectionState, Route};
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_edit_collection_root_folder_path_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.edit_path = "Test Path".to_owned().into();
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app.data.radarr_data.edit_path.text.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditCollectionPrompt.into()
);
}
#[test]
fn test_edit_collection_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::EditCollection)
);
assert!(app.should_refresh);
}
#[test]
fn test_edit_collection_toggle_monitored_submit() {
let current_route = Route::from((
ActiveRadarrBlock::EditCollectionPrompt,
Some(ActiveRadarrBlock::Collections),
));
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.push_navigation_stack(current_route);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(true));
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(false));
}
#[test]
fn test_edit_collection_toggle_search_on_add_submit() {
let current_route = Route::from((
ActiveRadarrBlock::EditCollectionPrompt,
Some(ActiveRadarrBlock::Collections),
));
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 2);
app.push_navigation_stack(current_route);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_search_on_add, Some(true));
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_search_on_add, Some(false));
}
#[rstest]
#[case(ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, 1)]
#[case(ActiveRadarrBlock::EditCollectionSelectQualityProfile, 2)]
#[case(ActiveRadarrBlock::EditCollectionRootFolderPathInput, 3)]
fn test_edit_collection_prompt_selected_block_submit(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::EditCollectionPrompt,
Some(ActiveRadarrBlock::Collections),
)
.into(),
);
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::Collections)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
assert!(app.should_ignore_quit_key);
}
}
#[rstest]
fn test_edit_collection_prompt_selecting_preferences_blocks_submit(
#[values(
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
ActiveRadarrBlock::EditCollectionRootFolderPathInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.push_navigation_stack(active_radarr_block.into());
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditCollectionPrompt.into()
);
if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
assert!(!app.should_ignore_quit_key);
}
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::{assert_edit_media_reset, assert_preferences_selections_reset};
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_edit_collection_root_folder_path_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
EditCollectionHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditCollectionPrompt.into()
);
}
#[test]
fn test_edit_collection_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data = create_test_radarr_data();
EditCollectionHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
let radarr_data = &app.data.radarr_data;
assert_preferences_selections_reset!(radarr_data);
assert_edit_media_reset!(radarr_data);
assert!(!radarr_data.prompt_confirm);
}
#[rstest]
fn test_edit_collection_esc(
#[values(
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
ActiveRadarrBlock::EditCollectionSelectQualityProfile
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(active_radarr_block.into());
EditCollectionHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
}
}
mod test_handle_key_char {
use super::*;
#[test]
fn test_edit_collection_root_folder_path_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_path = "Test".to_owned().into();
EditCollectionHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "Tes");
}
#[test]
fn test_edit_collection_root_folder_path_input_char_key() {
let mut app = App::default();
EditCollectionHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "h");
}
}
}
@@ -0,0 +1,503 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::edit_collection_handler::EditCollectionHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::MinimumAvailability;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{test_enum_scroll, test_iterable_scroll};
use super::*;
test_enum_scroll!(
test_edit_collection_select_minimum_availability_scroll,
EditCollectionHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_edit_collection_select_quality_profile_scroll,
EditCollectionHandler,
quality_profile_list,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
None
);
#[rstest]
fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
EditCollectionHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditCollectionToggleMonitored
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditCollectionSelectQualityProfile
);
}
}
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::{test_enum_home_and_end, test_iterable_home_and_end, test_text_box_home_end_keys};
use super::*;
test_enum_home_and_end!(
test_edit_collection_select_minimum_availability_home_end,
EditCollectionHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_edit_collection_select_quality_profile_scroll,
EditCollectionHandler,
quality_profile_list,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
None
);
#[test]
fn test_edit_collection_root_folder_path_input_home_end_keys() {
test_text_box_home_end_keys!(
EditCollectionHandler,
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
edit_path
);
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use crate::test_text_box_left_right_keys;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
EditCollectionHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert!(app.data.radarr_data.prompt_confirm);
EditCollectionHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[test]
fn test_edit_collection_root_folder_path_input_left_right_keys() {
test_text_box_left_right_keys!(
EditCollectionHandler,
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
edit_path
);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::EDIT_COLLECTION_SELECTION_BLOCKS;
use crate::models::{BlockSelectionState, Route};
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_edit_collection_root_folder_path_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.edit_path = "Test Path".to_owned().into();
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app.data.radarr_data.edit_path.text.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditCollectionPrompt.into()
);
}
#[test]
fn test_edit_collection_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::EditCollection)
);
assert!(app.should_refresh);
}
#[test]
fn test_edit_collection_toggle_monitored_submit() {
let current_route = Route::from((
ActiveRadarrBlock::EditCollectionPrompt,
Some(ActiveRadarrBlock::Collections),
));
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.push_navigation_stack(current_route);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(true));
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(false));
}
#[test]
fn test_edit_collection_toggle_search_on_add_submit() {
let current_route = Route::from((
ActiveRadarrBlock::EditCollectionPrompt,
Some(ActiveRadarrBlock::Collections),
));
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 2);
app.push_navigation_stack(current_route);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_search_on_add, Some(true));
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_search_on_add, Some(false));
}
#[rstest]
#[case(ActiveRadarrBlock::EditCollectionSelectMinimumAvailability, 1)]
#[case(ActiveRadarrBlock::EditCollectionSelectQualityProfile, 2)]
#[case(ActiveRadarrBlock::EditCollectionRootFolderPathInput, 3)]
fn test_edit_collection_prompt_selected_block_submit(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::EditCollectionPrompt,
Some(ActiveRadarrBlock::Collections),
)
.into(),
);
app.data.radarr_data.selected_block =
BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::Collections)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
assert!(app.should_ignore_quit_key);
}
}
#[rstest]
fn test_edit_collection_prompt_selecting_preferences_blocks_submit(
#[values(
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
ActiveRadarrBlock::EditCollectionRootFolderPathInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.push_navigation_stack(active_radarr_block.into());
EditCollectionHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::Collections),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditCollectionPrompt.into()
);
if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
assert!(!app.should_ignore_quit_key);
}
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::utils::create_test_radarr_data;
use crate::{assert_edit_media_reset, assert_preferences_selections_reset};
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[test]
fn test_edit_collection_root_folder_path_input_esc() {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
EditCollectionHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditCollectionPrompt.into()
);
}
#[test]
fn test_edit_collection_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
app.data.radarr_data = create_test_radarr_data();
EditCollectionHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::EditCollectionPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
let radarr_data = &app.data.radarr_data;
assert_preferences_selections_reset!(radarr_data);
assert_edit_media_reset!(radarr_data);
assert!(!radarr_data.prompt_confirm);
}
#[rstest]
fn test_edit_collection_esc(
#[values(
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
ActiveRadarrBlock::EditCollectionSelectQualityProfile
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
app.push_navigation_stack(active_radarr_block.into());
EditCollectionHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::Collections.into()
);
}
}
mod test_handle_key_char {
use super::*;
#[test]
fn test_edit_collection_root_folder_path_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_path = "Test".to_owned().into();
EditCollectionHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "Tes");
}
#[test]
fn test_edit_collection_root_folder_path_input_char_key() {
let mut app = App::default();
EditCollectionHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::EditCollectionRootFolderPathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "h");
}
}
}
@@ -7,6 +7,10 @@ use crate::models::Scrollable;
use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
#[cfg(test)]
#[path = "edit_movie_handler_tests.rs"]
mod edit_movie_handler_tests;
pub(super) struct EditMovieHandler<'a, 'b> {
key: &'a Key,
app: &'a mut App<'b>,
@@ -197,510 +201,3 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
}
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::MinimumAvailability;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{test_enum_scroll, test_iterable_scroll};
use super::*;
test_enum_scroll!(
test_edit_movie_select_minimum_availability_scroll,
EditMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_edit_movie_select_quality_profile_scroll,
EditMovieHandler,
quality_profile_list,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
None
);
#[rstest]
fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditMovieToggleMonitored
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditMovieSelectQualityProfile
);
}
}
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::{test_enum_home_and_end, test_iterable_home_and_end, test_text_box_home_end_keys};
use super::*;
test_enum_home_and_end!(
test_edit_movie_select_minimum_availability_home_end,
EditMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_edit_movie_select_quality_profile_scroll,
EditMovieHandler,
quality_profile_list,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
None
);
#[test]
fn test_edit_movie_path_input_home_end_keys() {
test_text_box_home_end_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMoviePathInput,
edit_path
);
}
#[test]
fn test_edit_movie_tags_input_home_end_keys() {
test_text_box_home_end_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMovieTagsInput,
edit_tags
);
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use crate::test_text_box_left_right_keys;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[test]
fn test_edit_movie_path_input_left_right_keys() {
test_text_box_left_right_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMoviePathInput,
edit_path
);
}
#[test]
fn test_edit_movie_tags_input_left_right_keys() {
test_text_box_left_right_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMovieTagsInput,
edit_tags
);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::{EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS};
use crate::models::{BlockSelectionState, Route};
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_edit_movie_path_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.edit_path = "Test Path".to_owned().into();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePathInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app.data.radarr_data.edit_path.text.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
}
#[test]
fn test_edit_movie_tags_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.edit_tags = "Test Tags".to_owned().into();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMovieTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app.data.radarr_data.edit_tags.text.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
}
#[test]
fn test_edit_movie_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::EditMovie)
);
assert!(app.should_refresh);
}
#[test]
fn test_edit_movie_toggle_monitored_submit() {
let current_route = Route::from((
ActiveRadarrBlock::EditMoviePrompt,
Some(ActiveRadarrBlock::Movies),
));
let mut app = App::default();
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.push_navigation_stack(current_route);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(true));
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(false));
}
#[rstest]
#[case(ActiveRadarrBlock::EditMovieSelectMinimumAvailability, 1)]
#[case(ActiveRadarrBlock::EditMovieSelectQualityProfile, 2)]
#[case(ActiveRadarrBlock::EditMoviePathInput, 3)]
#[case(ActiveRadarrBlock::EditMovieTagsInput, 4)]
fn test_edit_movie_prompt_selected_block_submit(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::EditMoviePrompt,
Some(ActiveRadarrBlock::Movies),
)
.into(),
);
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::Movies)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
if selected_block == ActiveRadarrBlock::EditMoviePathInput
|| selected_block == ActiveRadarrBlock::EditMovieTagsInput
{
assert!(app.should_ignore_quit_key);
}
}
#[rstest]
fn test_edit_movie_prompt_selecting_preferences_blocks_submit(
#[values(
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
ActiveRadarrBlock::EditMoviePathInput,
ActiveRadarrBlock::EditMovieTagsInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput
|| active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput
{
assert!(!app.should_ignore_quit_key);
}
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::{assert_edit_media_reset, assert_preferences_selections_reset};
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[rstest]
fn test_edit_movie_input_esc(
#[values(
ActiveRadarrBlock::EditMovieTagsInput,
ActiveRadarrBlock::EditMoviePathInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
EditMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
}
#[test]
fn test_edit_movie_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data = create_test_radarr_data();
EditMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
let radarr_data = &app.data.radarr_data;
assert_preferences_selections_reset!(radarr_data);
assert_edit_media_reset!(radarr_data);
assert!(!radarr_data.prompt_confirm);
}
#[rstest]
fn test_edit_movie_esc(
#[values(
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
ActiveRadarrBlock::EditMovieSelectQualityProfile
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(active_radarr_block.into());
EditMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
}
}
mod test_handle_key_char {
use super::*;
#[test]
fn test_edit_movie_path_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_path = "Test".to_owned().into();
EditMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::EditMoviePathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "Tes");
}
#[test]
fn test_edit_movie_tags_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_tags = "Test".to_owned().into();
EditMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::EditMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "Tes");
}
#[test]
fn test_edit_movie_path_input_char_key() {
let mut app = App::default();
EditMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::EditMoviePathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "h");
}
#[test]
fn test_edit_movie_tags_input_char_key() {
let mut app = App::default();
EditMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::EditMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "h");
}
}
}
@@ -0,0 +1,506 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::MinimumAvailability;
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use crate::{test_enum_scroll, test_iterable_scroll};
use super::*;
test_enum_scroll!(
test_edit_movie_select_minimum_availability_scroll,
EditMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_edit_movie_select_quality_profile_scroll,
EditMovieHandler,
quality_profile_list,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
None
);
#[rstest]
fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
if key == Key::Up {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditMovieToggleMonitored
);
} else {
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditMovieSelectQualityProfile
);
}
}
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::{test_enum_home_and_end, test_iterable_home_and_end, test_text_box_home_end_keys};
use super::*;
test_enum_home_and_end!(
test_edit_movie_select_minimum_availability_home_end,
EditMovieHandler,
MinimumAvailability,
minimum_availability_list,
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_edit_movie_select_quality_profile_scroll,
EditMovieHandler,
quality_profile_list,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
None
);
#[test]
fn test_edit_movie_path_input_home_end_keys() {
test_text_box_home_end_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMoviePathInput,
edit_path
);
}
#[test]
fn test_edit_movie_tags_input_home_end_keys() {
test_text_box_home_end_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMovieTagsInput,
edit_tags
);
}
}
mod test_handle_left_right_action {
use rstest::rstest;
use crate::test_text_box_left_right_keys;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
EditMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::EditMoviePrompt, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[test]
fn test_edit_movie_path_input_left_right_keys() {
test_text_box_left_right_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMoviePathInput,
edit_path
);
}
#[test]
fn test_edit_movie_tags_input_left_right_keys() {
test_text_box_left_right_keys!(
EditMovieHandler,
ActiveRadarrBlock::EditMovieTagsInput,
edit_tags
);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::{EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS};
use crate::models::{BlockSelectionState, Route};
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_edit_movie_path_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.edit_path = "Test Path".to_owned().into();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePathInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app.data.radarr_data.edit_path.text.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
}
#[test]
fn test_edit_movie_tags_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.edit_tags = "Test Tags".to_owned().into();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMovieTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app.data.radarr_data.edit_tags.text.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
}
#[test]
fn test_edit_movie_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::EditMovie)
);
assert!(app.should_refresh);
}
#[test]
fn test_edit_movie_toggle_monitored_submit() {
let current_route = Route::from((
ActiveRadarrBlock::EditMoviePrompt,
Some(ActiveRadarrBlock::Movies),
));
let mut app = App::default();
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.push_navigation_stack(current_route);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(true));
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(app.get_current_route(), &current_route);
assert_eq!(app.data.radarr_data.edit_monitored, Some(false));
}
#[rstest]
#[case(ActiveRadarrBlock::EditMovieSelectMinimumAvailability, 1)]
#[case(ActiveRadarrBlock::EditMovieSelectQualityProfile, 2)]
#[case(ActiveRadarrBlock::EditMoviePathInput, 3)]
#[case(ActiveRadarrBlock::EditMovieTagsInput, 4)]
fn test_edit_movie_prompt_selected_block_submit(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(
(
ActiveRadarrBlock::EditMoviePrompt,
Some(ActiveRadarrBlock::Movies),
)
.into(),
);
app.data.radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::Movies)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
if selected_block == ActiveRadarrBlock::EditMoviePathInput
|| selected_block == ActiveRadarrBlock::EditMovieTagsInput
{
assert!(app.should_ignore_quit_key);
}
}
#[rstest]
fn test_edit_movie_prompt_selecting_preferences_blocks_submit(
#[values(
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
ActiveRadarrBlock::EditMovieSelectQualityProfile,
ActiveRadarrBlock::EditMoviePathInput,
ActiveRadarrBlock::EditMovieTagsInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
EditMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::Movies),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput
|| active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput
{
assert!(!app.should_ignore_quit_key);
}
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::utils::create_test_radarr_data;
use crate::{assert_edit_media_reset, assert_preferences_selections_reset};
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[rstest]
fn test_edit_movie_input_esc(
#[values(
ActiveRadarrBlock::EditMovieTagsInput,
ActiveRadarrBlock::EditMoviePathInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
EditMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::EditMoviePrompt.into()
);
}
#[test]
fn test_edit_movie_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data = create_test_radarr_data();
EditMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::EditMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
let radarr_data = &app.data.radarr_data;
assert_preferences_selections_reset!(radarr_data);
assert_edit_media_reset!(radarr_data);
assert!(!radarr_data.prompt_confirm);
}
#[rstest]
fn test_edit_movie_esc(
#[values(
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
ActiveRadarrBlock::EditMovieSelectQualityProfile
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(active_radarr_block.into());
EditMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
}
}
mod test_handle_key_char {
use super::*;
#[test]
fn test_edit_movie_path_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_path = "Test".to_owned().into();
EditMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::EditMoviePathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "Tes");
}
#[test]
fn test_edit_movie_tags_input_backspace() {
let mut app = App::default();
app.data.radarr_data.edit_tags = "Test".to_owned().into();
EditMovieHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::EditMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "Tes");
}
#[test]
fn test_edit_movie_path_input_char_key() {
let mut app = App::default();
EditMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::EditMoviePathInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_path.text, "h");
}
#[test]
fn test_edit_movie_tags_input_char_key() {
let mut app = App::default();
EditMovieHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::EditMovieTagsInput,
&None,
)
.handle();
assert_str_eq!(app.data.radarr_data.edit_tags.text, "h");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -12,6 +12,10 @@ use crate::models::radarr_models::{Language, Release, ReleaseField};
use crate::models::{BlockSelectionState, Scrollable};
use crate::network::radarr_network::RadarrEvent;
#[cfg(test)]
#[path = "movie_details_handler_tests.rs"]
mod movie_details_handler_tests;
pub(super) struct MovieDetailsHandler<'a, 'b> {
key: &'a Key,
app: &'a mut App<'b>,
@@ -330,684 +334,3 @@ fn sort_releases_by_selected_field(
releases
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use rstest::rstest;
use serde_json::Number;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::movie_details_handler::{
sort_releases_by_selected_field, MovieDetailsHandler,
};
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::{
Credit, Language, MovieHistoryItem, Quality, QualityWrapper, Release, ReleaseField,
};
use crate::models::{HorizontallyScrollableText, ScrollableText};
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::models::radarr_models::ReleaseField;
use crate::{simple_stateful_iterable_vec, test_enum_scroll, test_iterable_scroll};
use super::*;
#[test]
fn test_movie_details_scroll() {
let mut app = App::default();
app.data.radarr_data.movie_details = ScrollableText::with_string("Test 1\nTest 2".to_owned());
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.up.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 0);
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.down.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 1);
}
test_iterable_scroll!(
test_movie_history_scroll,
MovieDetailsHandler,
movie_history,
simple_stateful_iterable_vec!(MovieHistoryItem, HorizontallyScrollableText, source_title),
ActiveRadarrBlock::MovieHistory,
None,
source_title,
to_string
);
test_iterable_scroll!(
test_cast_scroll,
MovieDetailsHandler,
movie_cast,
simple_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Cast,
None,
person_name,
to_owned
);
test_iterable_scroll!(
test_crew_scroll,
MovieDetailsHandler,
movie_crew,
simple_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Crew,
None,
person_name,
to_owned
);
test_iterable_scroll!(
test_manual_search_scroll,
MovieDetailsHandler,
movie_releases,
simple_stateful_iterable_vec!(Release, HorizontallyScrollableText),
ActiveRadarrBlock::ManualSearch,
None,
title,
to_string
);
test_enum_scroll!(
test_manual_search_sort_scroll,
MovieDetailsHandler,
ReleaseField,
movie_releases_sort,
ActiveRadarrBlock::ManualSearchSortPrompt,
None
);
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::models::radarr_models::ReleaseField;
use crate::{
extended_stateful_iterable_vec, test_enum_home_and_end, test_iterable_home_and_end,
};
use super::*;
#[test]
fn test_movie_details_home_end() {
let mut app = App::default();
app.data.radarr_data.movie_details = ScrollableText::with_string("Test 1\nTest 2".to_owned());
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.end.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 1);
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.home.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 0);
}
test_iterable_home_and_end!(
test_movie_history_home_end,
MovieDetailsHandler,
movie_history,
extended_stateful_iterable_vec!(MovieHistoryItem, HorizontallyScrollableText, source_title),
ActiveRadarrBlock::MovieHistory,
None,
source_title,
to_string
);
test_iterable_home_and_end!(
test_cast_home_end,
MovieDetailsHandler,
movie_cast,
extended_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Cast,
None,
person_name,
to_owned
);
test_iterable_home_and_end!(
test_crew_home_end,
MovieDetailsHandler,
movie_crew,
extended_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Crew,
None,
person_name,
to_owned
);
test_iterable_home_and_end!(
test_manual_search_home_end,
MovieDetailsHandler,
movie_releases,
extended_stateful_iterable_vec!(Release, HorizontallyScrollableText),
ActiveRadarrBlock::ManualSearch,
None,
title,
to_string
);
test_enum_home_and_end!(
test_manual_search_sort_home_end,
MovieDetailsHandler,
ReleaseField,
movie_releases_sort,
ActiveRadarrBlock::ManualSearchSortPrompt,
None
);
}
mod test_handle_left_right_action {
use pretty_assertions::assert_eq;
use rstest::rstest;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(
#[values(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
ActiveRadarrBlock::UpdateAndScanPrompt,
ActiveRadarrBlock::ManualSearchConfirmPrompt
)]
active_radarr_block: ActiveRadarrBlock,
#[values(Key::Left, Key::Right)] key: Key,
) {
let mut app = App::default();
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[rstest]
#[case(ActiveRadarrBlock::MovieDetails, ActiveRadarrBlock::MovieHistory)]
#[case(ActiveRadarrBlock::MovieHistory, ActiveRadarrBlock::FileInfo)]
#[case(ActiveRadarrBlock::FileInfo, ActiveRadarrBlock::Cast)]
#[case(ActiveRadarrBlock::Cast, ActiveRadarrBlock::Crew)]
#[case(ActiveRadarrBlock::Crew, ActiveRadarrBlock::ManualSearch)]
#[case(ActiveRadarrBlock::ManualSearch, ActiveRadarrBlock::MovieDetails)]
fn test_movie_info_tabs_left_right_action(
#[case] left_block: ActiveRadarrBlock,
#[case] right_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(right_block.into());
app.data.radarr_data.movie_info_tabs.index = app
.data
.radarr_data
.movie_info_tabs
.tabs
.iter()
.position(|tab_route| tab_route.route == right_block.into())
.unwrap_or_default();
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.left.key, &mut app, &right_block, &None)
.handle();
assert_eq!(
app.get_current_route(),
app.data.radarr_data.movie_info_tabs.get_active_route()
);
assert_eq!(app.get_current_route(), &left_block.into());
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.right.key, &mut app, &left_block, &None)
.handle();
assert_eq!(
app.get_current_route(),
app.data.radarr_data.movie_info_tabs.get_active_route()
);
assert_eq!(app.get_current_route(), &right_block.into());
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::models::radarr_models::ReleaseField;
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_manual_search_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
MovieDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::ManualSearch,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ManualSearchConfirmPrompt.into()
);
}
#[rstest]
#[case(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
RadarrEvent::TriggerAutomaticSearch
)]
#[case(ActiveRadarrBlock::UpdateAndScanPrompt, RadarrEvent::UpdateAndScan)]
#[case(
ActiveRadarrBlock::ManualSearchConfirmPrompt,
RadarrEvent::DownloadRelease
)]
fn test_movie_info_prompt_confirm_submit(
#[case] prompt_block: ActiveRadarrBlock,
#[case] expected_action: RadarrEvent,
) {
let mut app = App::default();
app.data.radarr_data.prompt_confirm = true;
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::MovieDetails.into()
);
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(expected_action)
);
}
#[rstest]
fn test_movie_info_prompt_decline_submit(
#[values(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
ActiveRadarrBlock::UpdateAndScanPrompt,
ActiveRadarrBlock::ManualSearchConfirmPrompt
)]
prompt_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::MovieDetails.into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_manual_search_sort_prompt_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
app.push_navigation_stack(ActiveRadarrBlock::ManualSearchSortPrompt.into());
app.data.radarr_data.sort_ascending = Some(true);
app
.data
.radarr_data
.movie_releases_sort
.set_items(vec![ReleaseField::default()]);
app.data.radarr_data.movie_releases.set_items(release_vec());
let mut expected_vec = release_vec();
expected_vec.reverse();
MovieDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::ManualSearchSortPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ManualSearch.into()
);
assert_eq!(app.data.radarr_data.movie_releases.items, expected_vec);
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::assert_movie_info_tabs_reset;
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[rstest]
fn test_movie_info_tabs_esc(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(active_radarr_block.into());
MovieDetailsHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_movie_info_tabs_reset!(app.data.radarr_data);
}
#[rstest]
fn test_movie_info_prompts_esc(
#[values(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
ActiveRadarrBlock::UpdateAndScanPrompt,
ActiveRadarrBlock::ManualSearchConfirmPrompt,
ActiveRadarrBlock::ManualSearchSortPrompt
)]
prompt_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data.prompt_confirm = true;
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&ESC_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
}
}
mod test_handle_key_char {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::{MinimumAvailability, Movie};
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable;
use crate::test_edit_movie_key;
use super::*;
#[rstest]
fn test_search_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.search.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into()
);
}
#[test]
fn test_sort_key() {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.sort.key,
&mut app,
&ActiveRadarrBlock::ManualSearch,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ManualSearchSortPrompt.into()
);
assert!(!app.data.radarr_data.movie_releases_sort.items.is_empty());
assert!(app.data.radarr_data.sort_ascending.is_some());
assert_eq!(app.data.radarr_data.sort_ascending, Some(false));
}
#[rstest]
fn test_edit_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
test_edit_movie_key!(
MovieDetailsHandler,
active_radarr_block,
active_radarr_block
);
}
#[rstest]
fn test_update_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.update.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::UpdateAndScanPrompt.into()
);
}
#[rstest]
fn test_refresh_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.refresh.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &active_radarr_block.into());
assert!(app.is_routing);
}
}
#[rstest]
fn test_sort_releases_by_selected_field(
#[values(
ReleaseField::Source,
ReleaseField::Age,
ReleaseField::Title,
ReleaseField::Indexer,
ReleaseField::Size,
ReleaseField::Peers,
ReleaseField::Language,
ReleaseField::Quality
)]
field: ReleaseField,
) {
let mut expected_vec = release_vec();
let sorted_releases = sort_releases_by_selected_field(release_vec(), field, true);
assert_eq!(sorted_releases, expected_vec);
let sorted_releases = sort_releases_by_selected_field(release_vec(), field, false);
expected_vec.reverse();
assert_eq!(sorted_releases, expected_vec);
}
#[test]
fn test_sort_releases_by_selected_field_rejected() {
let mut expected_vec = Vec::from(&release_vec()[1..]);
expected_vec.push(release_vec()[0].clone());
let sorted_releases =
sort_releases_by_selected_field(release_vec(), ReleaseField::Rejected, true);
assert_eq!(sorted_releases, expected_vec);
let sorted_releases =
sort_releases_by_selected_field(release_vec(), ReleaseField::Rejected, false);
assert_eq!(sorted_releases, release_vec());
}
fn release_vec() -> Vec<Release> {
let release_a = Release {
protocol: "Protocol A".to_owned(),
age: Number::from(1),
title: HorizontallyScrollableText::from("Title A".to_owned()),
indexer: "Indexer A".to_owned(),
size: Number::from(1),
rejected: true,
seeders: Some(Number::from(1)),
languages: Some(vec![Language {
name: "Language A".to_owned(),
}]),
quality: QualityWrapper {
quality: Quality {
name: "Quality A".to_owned(),
},
},
..Release::default()
};
let release_b = Release {
protocol: "Protocol B".to_owned(),
age: Number::from(2),
title: HorizontallyScrollableText::from("Title B".to_owned()),
indexer: "Indexer B".to_owned(),
size: Number::from(2),
rejected: false,
seeders: Some(Number::from(2)),
languages: Some(vec![Language {
name: "Language B".to_owned(),
}]),
quality: QualityWrapper {
quality: Quality {
name: "Quality B".to_owned(),
},
},
..Release::default()
};
let release_c = Release {
protocol: "Protocol C".to_owned(),
age: Number::from(3),
title: HorizontallyScrollableText::from("Title C".to_owned()),
indexer: "Indexer C".to_owned(),
size: Number::from(3),
rejected: false,
seeders: None,
languages: None,
quality: QualityWrapper {
quality: Quality {
name: "Quality C".to_owned(),
},
},
..Release::default()
};
vec![release_a, release_b, release_c]
}
}
@@ -0,0 +1,680 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use rstest::rstest;
use serde_json::Number;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::event::Key;
use crate::handlers::radarr_handlers::movie_details_handler::{
sort_releases_by_selected_field, MovieDetailsHandler,
};
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::{
Credit, Language, MovieHistoryItem, Quality, QualityWrapper, Release, ReleaseField,
};
use crate::models::{HorizontallyScrollableText, ScrollableText};
mod test_handle_scroll_up_and_down {
use pretty_assertions::assert_eq;
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::models::radarr_models::ReleaseField;
use crate::{simple_stateful_iterable_vec, test_enum_scroll, test_iterable_scroll};
use super::*;
#[test]
fn test_movie_details_scroll() {
let mut app = App::default();
app.data.radarr_data.movie_details = ScrollableText::with_string("Test 1\nTest 2".to_owned());
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.up.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 0);
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.down.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 1);
}
test_iterable_scroll!(
test_movie_history_scroll,
MovieDetailsHandler,
movie_history,
simple_stateful_iterable_vec!(MovieHistoryItem, HorizontallyScrollableText, source_title),
ActiveRadarrBlock::MovieHistory,
None,
source_title,
to_string
);
test_iterable_scroll!(
test_cast_scroll,
MovieDetailsHandler,
movie_cast,
simple_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Cast,
None,
person_name,
to_owned
);
test_iterable_scroll!(
test_crew_scroll,
MovieDetailsHandler,
movie_crew,
simple_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Crew,
None,
person_name,
to_owned
);
test_iterable_scroll!(
test_manual_search_scroll,
MovieDetailsHandler,
movie_releases,
simple_stateful_iterable_vec!(Release, HorizontallyScrollableText),
ActiveRadarrBlock::ManualSearch,
None,
title,
to_string
);
test_enum_scroll!(
test_manual_search_sort_scroll,
MovieDetailsHandler,
ReleaseField,
movie_releases_sort,
ActiveRadarrBlock::ManualSearchSortPrompt,
None
);
}
mod test_handle_home_end {
use strum::IntoEnumIterator;
use crate::models::radarr_models::ReleaseField;
use crate::{
extended_stateful_iterable_vec, test_enum_home_and_end, test_iterable_home_and_end,
};
use super::*;
#[test]
fn test_movie_details_home_end() {
let mut app = App::default();
app.data.radarr_data.movie_details = ScrollableText::with_string("Test 1\nTest 2".to_owned());
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.end.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 1);
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.home.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.movie_details.offset, 0);
}
test_iterable_home_and_end!(
test_movie_history_home_end,
MovieDetailsHandler,
movie_history,
extended_stateful_iterable_vec!(MovieHistoryItem, HorizontallyScrollableText, source_title),
ActiveRadarrBlock::MovieHistory,
None,
source_title,
to_string
);
test_iterable_home_and_end!(
test_cast_home_end,
MovieDetailsHandler,
movie_cast,
extended_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Cast,
None,
person_name,
to_owned
);
test_iterable_home_and_end!(
test_crew_home_end,
MovieDetailsHandler,
movie_crew,
extended_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Crew,
None,
person_name,
to_owned
);
test_iterable_home_and_end!(
test_manual_search_home_end,
MovieDetailsHandler,
movie_releases,
extended_stateful_iterable_vec!(Release, HorizontallyScrollableText),
ActiveRadarrBlock::ManualSearch,
None,
title,
to_string
);
test_enum_home_and_end!(
test_manual_search_sort_home_end,
MovieDetailsHandler,
ReleaseField,
movie_releases_sort,
ActiveRadarrBlock::ManualSearchSortPrompt,
None
);
}
mod test_handle_left_right_action {
use pretty_assertions::assert_eq;
use rstest::rstest;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(
#[values(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
ActiveRadarrBlock::UpdateAndScanPrompt,
ActiveRadarrBlock::ManualSearchConfirmPrompt
)]
active_radarr_block: ActiveRadarrBlock,
#[values(Key::Left, Key::Right)] key: Key,
) {
let mut app = App::default();
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[rstest]
#[case(ActiveRadarrBlock::MovieDetails, ActiveRadarrBlock::MovieHistory)]
#[case(ActiveRadarrBlock::MovieHistory, ActiveRadarrBlock::FileInfo)]
#[case(ActiveRadarrBlock::FileInfo, ActiveRadarrBlock::Cast)]
#[case(ActiveRadarrBlock::Cast, ActiveRadarrBlock::Crew)]
#[case(ActiveRadarrBlock::Crew, ActiveRadarrBlock::ManualSearch)]
#[case(ActiveRadarrBlock::ManualSearch, ActiveRadarrBlock::MovieDetails)]
fn test_movie_info_tabs_left_right_action(
#[case] left_block: ActiveRadarrBlock,
#[case] right_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(right_block.into());
app.data.radarr_data.movie_info_tabs.index = app
.data
.radarr_data
.movie_info_tabs
.tabs
.iter()
.position(|tab_route| tab_route.route == right_block.into())
.unwrap_or_default();
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.left.key, &mut app, &right_block, &None)
.handle();
assert_eq!(
app.get_current_route(),
app.data.radarr_data.movie_info_tabs.get_active_route()
);
assert_eq!(app.get_current_route(), &left_block.into());
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.right.key, &mut app, &left_block, &None)
.handle();
assert_eq!(
app.get_current_route(),
app.data.radarr_data.movie_info_tabs.get_active_route()
);
assert_eq!(app.get_current_route(), &right_block.into());
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::models::radarr_models::ReleaseField;
use crate::network::radarr_network::RadarrEvent;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_manual_search_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
MovieDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::ManualSearch,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ManualSearchConfirmPrompt.into()
);
}
#[rstest]
#[case(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
RadarrEvent::TriggerAutomaticSearch
)]
#[case(ActiveRadarrBlock::UpdateAndScanPrompt, RadarrEvent::UpdateAndScan)]
#[case(
ActiveRadarrBlock::ManualSearchConfirmPrompt,
RadarrEvent::DownloadRelease
)]
fn test_movie_info_prompt_confirm_submit(
#[case] prompt_block: ActiveRadarrBlock,
#[case] expected_action: RadarrEvent,
) {
let mut app = App::default();
app.data.radarr_data.prompt_confirm = true;
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::MovieDetails.into()
);
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(expected_action)
);
}
#[rstest]
fn test_movie_info_prompt_decline_submit(
#[values(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
ActiveRadarrBlock::UpdateAndScanPrompt,
ActiveRadarrBlock::ManualSearchConfirmPrompt
)]
prompt_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::MovieDetails.into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
#[test]
fn test_manual_search_sort_prompt_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
app.push_navigation_stack(ActiveRadarrBlock::ManualSearchSortPrompt.into());
app.data.radarr_data.sort_ascending = Some(true);
app
.data
.radarr_data
.movie_releases_sort
.set_items(vec![ReleaseField::default()]);
app.data.radarr_data.movie_releases.set_items(release_vec());
let mut expected_vec = release_vec();
expected_vec.reverse();
MovieDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::ManualSearchSortPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ManualSearch.into()
);
assert_eq!(app.data.radarr_data.movie_releases.items, expected_vec);
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::app::radarr::radarr_test_utils::utils::create_test_radarr_data;
use crate::assert_movie_info_tabs_reset;
use super::*;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[rstest]
fn test_movie_info_tabs_esc(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(active_radarr_block.into());
MovieDetailsHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_movie_info_tabs_reset!(app.data.radarr_data);
}
#[rstest]
fn test_movie_info_prompts_esc(
#[values(
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
ActiveRadarrBlock::UpdateAndScanPrompt,
ActiveRadarrBlock::ManualSearchConfirmPrompt,
ActiveRadarrBlock::ManualSearchSortPrompt
)]
prompt_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data.prompt_confirm = true;
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&ESC_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
}
}
mod test_handle_key_char {
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::radarr::radarr_test_utils::utils::create_test_radarr_data;
use crate::app::radarr::RadarrData;
use crate::app::radarr::EDIT_MOVIE_SELECTION_BLOCKS;
use crate::models::radarr_models::{MinimumAvailability, Movie};
use crate::models::BlockSelectionState;
use crate::models::HorizontallyScrollableText;
use crate::models::StatefulTable;
use crate::test_edit_movie_key;
use super::*;
#[rstest]
fn test_search_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.search.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into()
);
}
#[test]
fn test_sort_key() {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.sort.key,
&mut app,
&ActiveRadarrBlock::ManualSearch,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::ManualSearchSortPrompt.into()
);
assert!(!app.data.radarr_data.movie_releases_sort.items.is_empty());
assert!(app.data.radarr_data.sort_ascending.is_some());
assert_eq!(app.data.radarr_data.sort_ascending, Some(false));
}
#[rstest]
fn test_edit_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
test_edit_movie_key!(
MovieDetailsHandler,
active_radarr_block,
active_radarr_block
);
}
#[rstest]
fn test_update_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.update.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::UpdateAndScanPrompt.into()
);
}
#[rstest]
fn test_refresh_key(
#[values(
ActiveRadarrBlock::MovieDetails,
ActiveRadarrBlock::MovieHistory,
ActiveRadarrBlock::FileInfo,
ActiveRadarrBlock::Cast,
ActiveRadarrBlock::Crew,
ActiveRadarrBlock::ManualSearch
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
MovieDetailsHandler::with(
&DEFAULT_KEYBINDINGS.refresh.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &active_radarr_block.into());
assert!(app.is_routing);
}
}
#[rstest]
fn test_sort_releases_by_selected_field(
#[values(
ReleaseField::Source,
ReleaseField::Age,
ReleaseField::Title,
ReleaseField::Indexer,
ReleaseField::Size,
ReleaseField::Peers,
ReleaseField::Language,
ReleaseField::Quality
)]
field: ReleaseField,
) {
let mut expected_vec = release_vec();
let sorted_releases = sort_releases_by_selected_field(release_vec(), field, true);
assert_eq!(sorted_releases, expected_vec);
let sorted_releases = sort_releases_by_selected_field(release_vec(), field, false);
expected_vec.reverse();
assert_eq!(sorted_releases, expected_vec);
}
#[test]
fn test_sort_releases_by_selected_field_rejected() {
let mut expected_vec = Vec::from(&release_vec()[1..]);
expected_vec.push(release_vec()[0].clone());
let sorted_releases =
sort_releases_by_selected_field(release_vec(), ReleaseField::Rejected, true);
assert_eq!(sorted_releases, expected_vec);
let sorted_releases =
sort_releases_by_selected_field(release_vec(), ReleaseField::Rejected, false);
assert_eq!(sorted_releases, release_vec());
}
fn release_vec() -> Vec<Release> {
let release_a = Release {
protocol: "Protocol A".to_owned(),
age: Number::from(1),
title: HorizontallyScrollableText::from("Title A".to_owned()),
indexer: "Indexer A".to_owned(),
size: Number::from(1),
rejected: true,
seeders: Some(Number::from(1)),
languages: Some(vec![Language {
name: "Language A".to_owned(),
}]),
quality: QualityWrapper {
quality: Quality {
name: "Quality A".to_owned(),
},
},
..Release::default()
};
let release_b = Release {
protocol: "Protocol B".to_owned(),
age: Number::from(2),
title: HorizontallyScrollableText::from("Title B".to_owned()),
indexer: "Indexer B".to_owned(),
size: Number::from(2),
rejected: false,
seeders: Some(Number::from(2)),
languages: Some(vec![Language {
name: "Language B".to_owned(),
}]),
quality: QualityWrapper {
quality: Quality {
name: "Quality B".to_owned(),
},
},
..Release::default()
};
let release_c = Release {
protocol: "Protocol C".to_owned(),
age: Number::from(3),
title: HorizontallyScrollableText::from("Title C".to_owned()),
indexer: "Indexer C".to_owned(),
size: Number::from(3),
rejected: false,
seeders: None,
languages: None,
quality: QualityWrapper {
quality: Quality {
name: "Quality C".to_owned(),
},
},
..Release::default()
};
vec![release_a, release_b, release_c]
}
}
@@ -0,0 +1,138 @@
#[cfg(test)]
#[macro_use]
mod utils {
#[macro_export]
macro_rules! test_edit_movie_key {
($handler:ident, $block:expr, $context:expr) => {
let mut app = App::default();
let mut radarr_data = RadarrData {
edit_path: HorizontallyScrollableText::default(),
edit_tags: HorizontallyScrollableText::default(),
edit_monitored: None,
edit_search_on_add: None,
quality_profile_map: BiMap::from_iter([
(2222, "HD - 1080p".to_owned()),
(1111, "Any".to_owned()),
]),
tags_map: BiMap::from_iter([(1, "test".to_owned())]),
filtered_movies: StatefulTable::default(),
..create_test_radarr_data()
};
radarr_data.movies.set_items(vec![Movie {
path: "/nfs/movies/Test".to_owned().into(),
monitored: true,
quality_profile_id: Number::from(2222),
minimum_availability: MinimumAvailability::Released,
tags: vec![Number::from(1)],
..Movie::default()
}]);
radarr_data.selected_block = BlockSelectionState::new(&EDIT_MOVIE_SELECTION_BLOCKS);
app.data.radarr_data = radarr_data;
$handler::with(&DEFAULT_KEYBINDINGS.edit.key, &mut app, &$block, &None).handle();
assert_eq!(
app.get_current_route(),
&(ActiveRadarrBlock::EditMoviePrompt, Some($context)).into()
);
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditMovieToggleMonitored
);
assert_eq!(
app.data.radarr_data.minimum_availability_list.items,
Vec::from_iter(MinimumAvailability::iter())
);
assert_eq!(
app
.data
.radarr_data
.minimum_availability_list
.current_selection(),
&MinimumAvailability::Released
);
assert_eq!(
app.data.radarr_data.quality_profile_list.items,
vec!["Any".to_owned(), "HD - 1080p".to_owned()]
);
assert_str_eq!(
app
.data
.radarr_data
.quality_profile_list
.current_selection(),
"HD - 1080p"
);
assert_str_eq!(app.data.radarr_data.edit_path.text, "/nfs/movies/Test");
assert_str_eq!(app.data.radarr_data.edit_tags.text, "test");
assert_eq!(app.data.radarr_data.edit_monitored, Some(true));
};
}
#[macro_export]
macro_rules! test_edit_collection_key {
($handler:ident, $block:expr, $context:expr) => {
let mut app = App::default();
let mut radarr_data = RadarrData {
edit_path: HorizontallyScrollableText::default(),
edit_tags: HorizontallyScrollableText::default(),
edit_monitored: None,
edit_search_on_add: None,
quality_profile_map: BiMap::from_iter([
(2222, "HD - 1080p".to_owned()),
(1111, "Any".to_owned()),
]),
filtered_collections: StatefulTable::default(),
..create_test_radarr_data()
};
radarr_data.collections.set_items(vec![Collection {
root_folder_path: "/nfs/movies/Test".to_owned().into(),
monitored: true,
search_on_add: true,
quality_profile_id: Number::from(2222),
minimum_availability: MinimumAvailability::Released,
..Collection::default()
}]);
radarr_data.selected_block = BlockSelectionState::new(&EDIT_COLLECTION_SELECTION_BLOCKS);
app.data.radarr_data = radarr_data;
$handler::with(&DEFAULT_KEYBINDINGS.edit.key, &mut app, &$block, &None).handle();
assert_eq!(
app.get_current_route(),
&(ActiveRadarrBlock::EditCollectionPrompt, Some($context)).into()
);
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&ActiveRadarrBlock::EditCollectionToggleMonitored
);
assert_eq!(
app.data.radarr_data.minimum_availability_list.items,
Vec::from_iter(MinimumAvailability::iter())
);
assert_eq!(
app
.data
.radarr_data
.minimum_availability_list
.current_selection(),
&MinimumAvailability::Released
);
assert_eq!(
app.data.radarr_data.quality_profile_list.items,
vec!["Any".to_owned(), "HD - 1080p".to_owned()]
);
assert_str_eq!(
app
.data
.radarr_data
.quality_profile_list
.current_selection(),
"HD - 1080p"
);
assert_str_eq!(app.data.radarr_data.edit_path.text, "/nfs/movies/Test");
assert_eq!(app.data.radarr_data.edit_monitored, Some(true));
assert_eq!(app.data.radarr_data.edit_search_on_add, Some(true));
};
}
}
File diff suppressed because it is too large Load Diff
+4 -529
View File
@@ -8,6 +8,10 @@ use crate::app::radarr::ActiveRadarrBlock;
pub mod radarr_models;
#[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)]
@@ -343,532 +347,3 @@ where
self.index = index;
}
}
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use pretty_assertions::{assert_eq, assert_str_eq};
use crate::app::radarr::ActiveRadarrBlock;
use crate::models::{
BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulTable,
TabRoute, TabState,
};
const BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieTagsInput,
ActiveRadarrBlock::AddMovieConfirmPrompt,
];
#[test]
fn test_stateful_table_scroll() {
let mut stateful_table = create_test_stateful_table();
assert_eq!(stateful_table.state.selected(), Some(0));
stateful_table.scroll_down();
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.scroll_down();
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));
stateful_table.scroll_to_bottom();
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.scroll_to_top();
assert_eq!(stateful_table.state.selected(), Some(0));
}
#[test]
fn test_stateful_table_set_items() {
let items_vec = vec!["Test 1", "Test 2", "Test 3"];
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
stateful_table.set_items(items_vec.clone());
assert_eq!(stateful_table.state.selected(), Some(0));
stateful_table.state.select(Some(1));
stateful_table.set_items(items_vec.clone());
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.state.select(Some(3));
stateful_table.set_items(items_vec);
assert_eq!(stateful_table.state.selected(), Some(2));
}
#[test]
fn test_stateful_table_current_selection() {
let mut stateful_table = create_test_stateful_table();
assert_str_eq!(stateful_table.current_selection(), &stateful_table.items[0]);
stateful_table.state.select(Some(1));
assert_str_eq!(stateful_table.current_selection(), &stateful_table.items[1]);
}
#[test]
fn test_stateful_table_select_index() {
let mut stateful_table = create_test_stateful_table();
assert_eq!(stateful_table.state.selected(), Some(0));
stateful_table.select_index(Some(1));
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.select_index(None);
assert_eq!(stateful_table.state.selected(), None);
}
#[test]
fn test_stateful_table_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());
assert_eq!(scrollable_text.items.len(), 3);
assert_eq!(scrollable_text.items, vec!["Test ", " String ", ""]);
assert_eq!(scrollable_text.offset, 0);
}
#[test]
fn test_scrollable_text_get_text() {
let test_text = "Test \nString";
let scrollable_text = ScrollableText::with_string(test_text.to_owned());
assert_str_eq!(scrollable_text.get_text(), test_text);
}
#[test]
fn test_scrollable_text_scroll() {
let mut scrollable_text = ScrollableText::with_string("Test \nString".to_owned());
scrollable_text.scroll_down();
assert_eq!(scrollable_text.offset, 1);
scrollable_text.scroll_down();
assert_eq!(scrollable_text.offset, 1);
scrollable_text.scroll_up();
assert_eq!(scrollable_text.offset, 0);
scrollable_text.scroll_up();
assert_eq!(scrollable_text.offset, 0);
scrollable_text.scroll_to_bottom();
assert_eq!(scrollable_text.offset, 1);
scrollable_text.scroll_to_top();
assert_eq!(scrollable_text.offset, 0);
}
#[test]
fn test_horizontally_scrollable_text_from() {
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
assert_str_eq!(horizontally_scrollable_text.text, test_text);
}
#[test]
fn test_horizontally_scrollable_text_to_string() {
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
assert_str_eq!(horizontally_scrollable_text.to_string(), test_text);
let horizontally_scrollable_text = HorizontallyScrollableText {
text: test_text.to_owned(),
offset: RefCell::new(test_text.len() - 1),
};
assert_str_eq!(horizontally_scrollable_text.to_string(), "g");
let horizontally_scrollable_text = HorizontallyScrollableText {
text: test_text.to_owned(),
offset: RefCell::new(test_text.len()),
};
assert!(horizontally_scrollable_text.to_string().is_empty());
}
#[test]
fn test_horizontally_scrollable_text_new() {
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::new(test_text.to_owned());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
assert_str_eq!(horizontally_scrollable_text.text, test_text);
}
#[test]
fn test_horizontally_scrollable_text_scroll_text_left() {
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string".to_owned());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
for i in 1..horizontally_scrollable_text.text.len() - 1 {
horizontally_scrollable_text.scroll_left();
assert_eq!(*horizontally_scrollable_text.offset.borrow(), i);
}
horizontally_scrollable_text.scroll_left();
assert_eq!(
*horizontally_scrollable_text.offset.borrow(),
horizontally_scrollable_text.text.len() - 1
);
}
#[test]
fn test_horizontally_scrollable_text_scroll_text_right() {
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string".to_owned());
*horizontally_scrollable_text.offset.borrow_mut() = horizontally_scrollable_text.text.len();
for i in 1..horizontally_scrollable_text.text.len() {
horizontally_scrollable_text.scroll_right();
assert_eq!(
*horizontally_scrollable_text.offset.borrow(),
horizontally_scrollable_text.text.len() - i
);
}
horizontally_scrollable_text.scroll_right();
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_scroll_home() {
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string".to_owned());
horizontally_scrollable_text.scroll_home();
assert_eq!(
*horizontally_scrollable_text.offset.borrow(),
horizontally_scrollable_text.text.len()
);
}
#[test]
fn test_horizontally_scrollable_text_reset_offset() {
let horizontally_scrollable_text = HorizontallyScrollableText {
text: "Test string".to_owned(),
offset: RefCell::new(1),
};
horizontally_scrollable_text.reset_offset();
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_scroll_or_reset() {
let width = 3;
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_left_or_reset(width, false, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left_or_reset(width, true, false);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_left_or_reset(test_text.len(), false, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_test_scroll_or_reset_resets_when_text_unselected() {
let horizontally_scrollable_test = HorizontallyScrollableText::from("Test string".to_owned());
horizontally_scrollable_test.scroll_left();
assert_eq!(*horizontally_scrollable_test.offset.borrow(), 1);
horizontally_scrollable_test.scroll_left_or_reset(3, false, false);
assert_eq!(*horizontally_scrollable_test.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_drain() {
let test_text = "Test string";
let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
assert_str_eq!(horizontally_scrollable_text.drain(), test_text);
assert!(horizontally_scrollable_text.text.is_empty());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_pop() {
let test_text = "Test string";
let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test strin");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left();
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test strn");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test str");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_home();
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test str");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 8);
}
#[test]
fn test_horizontally_scrollable_text_push() {
let test_text = "Test string";
let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
horizontally_scrollable_text.push('h');
assert_str_eq!(horizontally_scrollable_text.text, "Test stringh");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left();
horizontally_scrollable_text.push('l');
assert_str_eq!(horizontally_scrollable_text.text, "Test stringlh");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.push('0');
assert_str_eq!(horizontally_scrollable_text.text, "Test stringlh0");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_tab_state_new() {
let tab_state = TabState::new(create_test_tab_routes());
assert_eq!(tab_state.index, 0);
}
#[test]
fn test_tab_state_set_index() {
let mut tab_state = TabState::new(create_test_tab_routes());
let result = tab_state.set_index(1);
assert_eq!(result, &create_test_tab_routes()[1]);
assert_eq!(tab_state.index, 1);
}
#[test]
fn test_tab_state_get_active_route() {
let tabs = create_test_tab_routes();
let second_tab = tabs[1].route;
let tab_state = TabState { tabs, index: 1 };
let active_route = tab_state.get_active_route();
assert_eq!(active_route, &second_tab);
}
#[test]
fn test_tab_state_get_active_tab_help() {
let tabs = create_test_tab_routes();
let second_tab_help = tabs[1].help;
let tab_state = TabState { tabs, index: 1 };
let tab_help = tab_state.get_active_tab_help();
assert_str_eq!(tab_help, second_tab_help);
}
#[test]
fn test_tab_state_get_active_tab_contextual_help() {
let tabs = create_test_tab_routes();
let second_tab_contextual_help = tabs[1].contextual_help.unwrap();
let tab_state = TabState { tabs, index: 1 };
let tab_contextual_help = tab_state.get_active_tab_contextual_help();
assert!(tab_contextual_help.is_some());
assert_str_eq!(tab_contextual_help.unwrap(), second_tab_contextual_help);
}
#[test]
fn test_tab_state_next() {
let tab_routes = create_test_tab_routes();
let mut tab_state = TabState::new(create_test_tab_routes());
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
tab_state.next();
assert_eq!(tab_state.get_active_route(), &tab_routes[1].route);
tab_state.next();
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
}
#[test]
fn test_tab_state_previous() {
let tab_routes = create_test_tab_routes();
let mut tab_state = TabState::new(create_test_tab_routes());
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
tab_state.previous();
assert_eq!(tab_state.get_active_route(), &tab_routes[1].route);
tab_state.previous();
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
}
#[test]
fn test_block_selection_state_new() {
let block_selection_state = BlockSelectionState::new(&BLOCKS);
assert_eq!(block_selection_state.index, 0);
}
#[test]
fn test_block_selection_state_get_active_block() {
let second_block = BLOCKS[1];
let block_selection_state = BlockSelectionState {
blocks: &BLOCKS,
index: 1,
};
let active_block = block_selection_state.get_active_block();
assert_eq!(active_block, &second_block);
}
#[test]
fn test_block_selection_state_next() {
let blocks = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
];
let mut block_selection_state = BlockSelectionState::new(&blocks);
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
block_selection_state.next();
assert_eq!(block_selection_state.get_active_block(), &blocks[1]);
block_selection_state.next();
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
}
#[test]
fn test_block_selection_state_previous() {
let blocks = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
];
let mut block_selection_state = BlockSelectionState::new(&blocks);
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
block_selection_state.previous();
assert_eq!(block_selection_state.get_active_block(), &blocks[1]);
block_selection_state.previous();
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
}
fn create_test_tab_routes() -> Vec<TabRoute> {
vec![
TabRoute {
title: "Test 1",
route: ActiveRadarrBlock::Movies.into(),
help: "Help for Test 1",
contextual_help: Some("Contextual Help for Test 1"),
},
TabRoute {
title: "Test 2",
route: ActiveRadarrBlock::Collections.into(),
help: "Help for Test 2",
contextual_help: Some("Contextual Help for Test 2"),
},
]
}
fn create_test_stateful_table() -> StatefulTable<&'static str> {
let mut stateful_table = StatefulTable::default();
stateful_table.set_items(vec!["Test 1", "Test 2"]);
stateful_table
}
}
+528
View File
@@ -0,0 +1,528 @@
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use pretty_assertions::{assert_eq, assert_str_eq};
use crate::app::radarr::ActiveRadarrBlock;
use crate::models::{
BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, StatefulTable,
TabRoute, TabState,
};
const BLOCKS: [ActiveRadarrBlock; 6] = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
ActiveRadarrBlock::AddMovieSelectQualityProfile,
ActiveRadarrBlock::AddMovieTagsInput,
ActiveRadarrBlock::AddMovieConfirmPrompt,
];
#[test]
fn test_stateful_table_scroll() {
let mut stateful_table = create_test_stateful_table();
assert_eq!(stateful_table.state.selected(), Some(0));
stateful_table.scroll_down();
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.scroll_down();
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));
stateful_table.scroll_to_bottom();
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.scroll_to_top();
assert_eq!(stateful_table.state.selected(), Some(0));
}
#[test]
fn test_stateful_table_set_items() {
let items_vec = vec!["Test 1", "Test 2", "Test 3"];
let mut stateful_table: StatefulTable<&str> = StatefulTable::default();
stateful_table.set_items(items_vec.clone());
assert_eq!(stateful_table.state.selected(), Some(0));
stateful_table.state.select(Some(1));
stateful_table.set_items(items_vec.clone());
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.state.select(Some(3));
stateful_table.set_items(items_vec);
assert_eq!(stateful_table.state.selected(), Some(2));
}
#[test]
fn test_stateful_table_current_selection() {
let mut stateful_table = create_test_stateful_table();
assert_str_eq!(stateful_table.current_selection(), &stateful_table.items[0]);
stateful_table.state.select(Some(1));
assert_str_eq!(stateful_table.current_selection(), &stateful_table.items[1]);
}
#[test]
fn test_stateful_table_select_index() {
let mut stateful_table = create_test_stateful_table();
assert_eq!(stateful_table.state.selected(), Some(0));
stateful_table.select_index(Some(1));
assert_eq!(stateful_table.state.selected(), Some(1));
stateful_table.select_index(None);
assert_eq!(stateful_table.state.selected(), None);
}
#[test]
fn test_stateful_table_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());
assert_eq!(scrollable_text.items.len(), 3);
assert_eq!(scrollable_text.items, vec!["Test ", " String ", ""]);
assert_eq!(scrollable_text.offset, 0);
}
#[test]
fn test_scrollable_text_get_text() {
let test_text = "Test \nString";
let scrollable_text = ScrollableText::with_string(test_text.to_owned());
assert_str_eq!(scrollable_text.get_text(), test_text);
}
#[test]
fn test_scrollable_text_scroll() {
let mut scrollable_text = ScrollableText::with_string("Test \nString".to_owned());
scrollable_text.scroll_down();
assert_eq!(scrollable_text.offset, 1);
scrollable_text.scroll_down();
assert_eq!(scrollable_text.offset, 1);
scrollable_text.scroll_up();
assert_eq!(scrollable_text.offset, 0);
scrollable_text.scroll_up();
assert_eq!(scrollable_text.offset, 0);
scrollable_text.scroll_to_bottom();
assert_eq!(scrollable_text.offset, 1);
scrollable_text.scroll_to_top();
assert_eq!(scrollable_text.offset, 0);
}
#[test]
fn test_horizontally_scrollable_text_from() {
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
assert_str_eq!(horizontally_scrollable_text.text, test_text);
}
#[test]
fn test_horizontally_scrollable_text_to_string() {
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
assert_str_eq!(horizontally_scrollable_text.to_string(), test_text);
let horizontally_scrollable_text = HorizontallyScrollableText {
text: test_text.to_owned(),
offset: RefCell::new(test_text.len() - 1),
};
assert_str_eq!(horizontally_scrollable_text.to_string(), "g");
let horizontally_scrollable_text = HorizontallyScrollableText {
text: test_text.to_owned(),
offset: RefCell::new(test_text.len()),
};
assert!(horizontally_scrollable_text.to_string().is_empty());
}
#[test]
fn test_horizontally_scrollable_text_new() {
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::new(test_text.to_owned());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
assert_str_eq!(horizontally_scrollable_text.text, test_text);
}
#[test]
fn test_horizontally_scrollable_text_scroll_text_left() {
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string".to_owned());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
for i in 1..horizontally_scrollable_text.text.len() - 1 {
horizontally_scrollable_text.scroll_left();
assert_eq!(*horizontally_scrollable_text.offset.borrow(), i);
}
horizontally_scrollable_text.scroll_left();
assert_eq!(
*horizontally_scrollable_text.offset.borrow(),
horizontally_scrollable_text.text.len() - 1
);
}
#[test]
fn test_horizontally_scrollable_text_scroll_text_right() {
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string".to_owned());
*horizontally_scrollable_text.offset.borrow_mut() = horizontally_scrollable_text.text.len();
for i in 1..horizontally_scrollable_text.text.len() {
horizontally_scrollable_text.scroll_right();
assert_eq!(
*horizontally_scrollable_text.offset.borrow(),
horizontally_scrollable_text.text.len() - i
);
}
horizontally_scrollable_text.scroll_right();
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_scroll_home() {
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string".to_owned());
horizontally_scrollable_text.scroll_home();
assert_eq!(
*horizontally_scrollable_text.offset.borrow(),
horizontally_scrollable_text.text.len()
);
}
#[test]
fn test_horizontally_scrollable_text_reset_offset() {
let horizontally_scrollable_text = HorizontallyScrollableText {
text: "Test string".to_owned(),
offset: RefCell::new(1),
};
horizontally_scrollable_text.reset_offset();
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_scroll_or_reset() {
let width = 3;
let test_text = "Test string";
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_left_or_reset(width, false, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left_or_reset(width, true, false);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_left_or_reset(test_text.len(), false, true);
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_test_scroll_or_reset_resets_when_text_unselected() {
let horizontally_scrollable_test = HorizontallyScrollableText::from("Test string".to_owned());
horizontally_scrollable_test.scroll_left();
assert_eq!(*horizontally_scrollable_test.offset.borrow(), 1);
horizontally_scrollable_test.scroll_left_or_reset(3, false, false);
assert_eq!(*horizontally_scrollable_test.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_drain() {
let test_text = "Test string";
let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
assert_str_eq!(horizontally_scrollable_text.drain(), test_text);
assert!(horizontally_scrollable_text.text.is_empty());
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_horizontally_scrollable_text_pop() {
let test_text = "Test string";
let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test strin");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left();
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test strn");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test str");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_home();
horizontally_scrollable_text.pop();
assert_str_eq!(horizontally_scrollable_text.text, "Test str");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 8);
}
#[test]
fn test_horizontally_scrollable_text_push() {
let test_text = "Test string";
let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
horizontally_scrollable_text.push('h');
assert_str_eq!(horizontally_scrollable_text.text, "Test stringh");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
horizontally_scrollable_text.scroll_left();
horizontally_scrollable_text.push('l');
assert_str_eq!(horizontally_scrollable_text.text, "Test stringlh");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.scroll_right();
horizontally_scrollable_text.push('0');
assert_str_eq!(horizontally_scrollable_text.text, "Test stringlh0");
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
}
#[test]
fn test_tab_state_new() {
let tab_state = TabState::new(create_test_tab_routes());
assert_eq!(tab_state.index, 0);
}
#[test]
fn test_tab_state_set_index() {
let mut tab_state = TabState::new(create_test_tab_routes());
let result = tab_state.set_index(1);
assert_eq!(result, &create_test_tab_routes()[1]);
assert_eq!(tab_state.index, 1);
}
#[test]
fn test_tab_state_get_active_route() {
let tabs = create_test_tab_routes();
let second_tab = tabs[1].route;
let tab_state = TabState { tabs, index: 1 };
let active_route = tab_state.get_active_route();
assert_eq!(active_route, &second_tab);
}
#[test]
fn test_tab_state_get_active_tab_help() {
let tabs = create_test_tab_routes();
let second_tab_help = tabs[1].help;
let tab_state = TabState { tabs, index: 1 };
let tab_help = tab_state.get_active_tab_help();
assert_str_eq!(tab_help, second_tab_help);
}
#[test]
fn test_tab_state_get_active_tab_contextual_help() {
let tabs = create_test_tab_routes();
let second_tab_contextual_help = tabs[1].contextual_help.unwrap();
let tab_state = TabState { tabs, index: 1 };
let tab_contextual_help = tab_state.get_active_tab_contextual_help();
assert!(tab_contextual_help.is_some());
assert_str_eq!(tab_contextual_help.unwrap(), second_tab_contextual_help);
}
#[test]
fn test_tab_state_next() {
let tab_routes = create_test_tab_routes();
let mut tab_state = TabState::new(create_test_tab_routes());
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
tab_state.next();
assert_eq!(tab_state.get_active_route(), &tab_routes[1].route);
tab_state.next();
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
}
#[test]
fn test_tab_state_previous() {
let tab_routes = create_test_tab_routes();
let mut tab_state = TabState::new(create_test_tab_routes());
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
tab_state.previous();
assert_eq!(tab_state.get_active_route(), &tab_routes[1].route);
tab_state.previous();
assert_eq!(tab_state.get_active_route(), &tab_routes[0].route);
}
#[test]
fn test_block_selection_state_new() {
let block_selection_state = BlockSelectionState::new(&BLOCKS);
assert_eq!(block_selection_state.index, 0);
}
#[test]
fn test_block_selection_state_get_active_block() {
let second_block = BLOCKS[1];
let block_selection_state = BlockSelectionState {
blocks: &BLOCKS,
index: 1,
};
let active_block = block_selection_state.get_active_block();
assert_eq!(active_block, &second_block);
}
#[test]
fn test_block_selection_state_next() {
let blocks = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
];
let mut block_selection_state = BlockSelectionState::new(&blocks);
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
block_selection_state.next();
assert_eq!(block_selection_state.get_active_block(), &blocks[1]);
block_selection_state.next();
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
}
#[test]
fn test_block_selection_state_previous() {
let blocks = [
ActiveRadarrBlock::AddMovieSelectRootFolder,
ActiveRadarrBlock::AddMovieSelectMonitor,
];
let mut block_selection_state = BlockSelectionState::new(&blocks);
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
block_selection_state.previous();
assert_eq!(block_selection_state.get_active_block(), &blocks[1]);
block_selection_state.previous();
assert_eq!(block_selection_state.get_active_block(), &blocks[0]);
}
fn create_test_tab_routes() -> Vec<TabRoute> {
vec![
TabRoute {
title: "Test 1",
route: ActiveRadarrBlock::Movies.into(),
help: "Help for Test 1",
contextual_help: Some("Contextual Help for Test 1"),
},
TabRoute {
title: "Test 2",
route: ActiveRadarrBlock::Collections.into(),
help: "Help for Test 2",
contextual_help: Some("Contextual Help for Test 2"),
},
]
}
fn create_test_stateful_table() -> StatefulTable<&'static str> {
let mut stateful_table = StatefulTable::default();
stateful_table.set_items(vec!["Test 1", "Test 2"]);
stateful_table
}
}
+32 -44
View File
@@ -8,6 +8,10 @@ use strum_macros::{Display, EnumIter};
use crate::models::HorizontallyScrollableText;
#[cfg(test)]
#[path = "radarr_models_tests.rs"]
mod radarr_models_tests;
#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct DiskSpace {
@@ -404,48 +408,32 @@ impl Monitor {
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::models::radarr_models::{MinimumAvailability, Monitor};
#[test]
fn test_minimum_availability_display() {
assert_str_eq!(MinimumAvailability::Tba.to_string(), "tba");
assert_str_eq!(MinimumAvailability::Announced.to_string(), "announced");
assert_str_eq!(MinimumAvailability::InCinemas.to_string(), "inCinemas");
assert_str_eq!(MinimumAvailability::Released.to_string(), "released");
}
#[test]
fn test_minimum_availability_to_display_str() {
assert_str_eq!(MinimumAvailability::Tba.to_display_str(), "TBA");
assert_str_eq!(MinimumAvailability::Announced.to_display_str(), "Announced");
assert_str_eq!(
MinimumAvailability::InCinemas.to_display_str(),
"In Cinemas"
);
assert_str_eq!(MinimumAvailability::Released.to_display_str(), "Released");
}
#[test]
fn test_monitor_display() {
assert_str_eq!(Monitor::MovieOnly.to_string(), "movieOnly");
assert_str_eq!(
Monitor::MovieAndCollection.to_string(),
"movieAndCollection"
);
assert_str_eq!(Monitor::None.to_string(), "none");
}
#[test]
fn test_monitor_to_display_str() {
assert_str_eq!(Monitor::MovieOnly.to_display_str(), "Movie only");
assert_str_eq!(
Monitor::MovieAndCollection.to_display_str(),
"Movie and Collection"
);
assert_str_eq!(Monitor::None.to_display_str(), "None");
}
#[derive(Default, Deserialize, Clone, Debug, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Log {
pub time: DateTime<Utc>,
pub exception: Option<String>,
pub exception_type: Option<String>,
pub level: Option<String>,
pub logger: Option<String>,
pub message: Option<String>,
pub method: Option<String>,
}
#[derive(Default, Deserialize, Debug, Eq, PartialEq)]
pub struct LogResponse {
pub records: Vec<Log>,
}
#[derive(Derivative, Deserialize, Debug, Clone, PartialEq, Eq)]
#[derivative(Default)]
#[serde(rename_all = "camelCase")]
pub struct Task {
pub name: String,
pub task_name: String,
#[derivative(Default(value = "Number::from(0)"))]
pub interval: Number,
pub last_execution: DateTime<Utc>,
pub last_duration: String,
pub next_execution: DateTime<Utc>,
}
+45
View File
@@ -0,0 +1,45 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::models::radarr_models::{MinimumAvailability, Monitor};
#[test]
fn test_minimum_availability_display() {
assert_str_eq!(MinimumAvailability::Tba.to_string(), "tba");
assert_str_eq!(MinimumAvailability::Announced.to_string(), "announced");
assert_str_eq!(MinimumAvailability::InCinemas.to_string(), "inCinemas");
assert_str_eq!(MinimumAvailability::Released.to_string(), "released");
}
#[test]
fn test_minimum_availability_to_display_str() {
assert_str_eq!(MinimumAvailability::Tba.to_display_str(), "TBA");
assert_str_eq!(MinimumAvailability::Announced.to_display_str(), "Announced");
assert_str_eq!(
MinimumAvailability::InCinemas.to_display_str(),
"In Cinemas"
);
assert_str_eq!(MinimumAvailability::Released.to_display_str(), "Released");
}
#[test]
fn test_monitor_display() {
assert_str_eq!(Monitor::MovieOnly.to_string(), "movieOnly");
assert_str_eq!(
Monitor::MovieAndCollection.to_string(),
"movieAndCollection"
);
assert_str_eq!(Monitor::None.to_string(), "none");
}
#[test]
fn test_monitor_to_display_str() {
assert_str_eq!(Monitor::MovieOnly.to_display_str(), "Movie only");
assert_str_eq!(
Monitor::MovieAndCollection.to_display_str(),
"Movie and Collection"
);
assert_str_eq!(Monitor::None.to_display_str(), "None");
}
}
+5 -303
View File
@@ -13,9 +13,13 @@ use tokio::sync::{Mutex, MutexGuard};
use crate::app::App;
use crate::network::radarr_network::RadarrEvent;
pub(crate) mod radarr_network;
pub mod radarr_network;
mod utils;
#[cfg(test)]
#[path = "network_tests.rs"]
mod network_tests;
#[derive(PartialEq, Eq, Debug)]
pub enum NetworkEvent {
Radarr(RadarrEvent),
@@ -150,305 +154,3 @@ pub struct RequestProps<T: Serialize + Debug> {
pub body: Option<T>,
pub api_token: String,
}
#[cfg(test)]
mod tests {
use std::fmt::Debug;
use std::string::ToString;
use std::sync::Arc;
use mockito::{Mock, Server, ServerGuard};
use pretty_assertions::assert_str_eq;
use rstest::rstest;
use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use crate::app::{App, RadarrConfig};
use crate::models::HorizontallyScrollableText;
use crate::network::radarr_network::RadarrEvent;
use crate::network::{Network, RequestMethod, RequestProps};
#[tokio::test]
async fn test_handle_network_event_radarr_event() {
let mut server = Server::new_async().await;
let radarr_server = server
.mock("GET", "/api/v3/health")
.with_status(200)
.create_async()
.await;
let host = server.host_with_port().split(':').collect::<Vec<&str>>()[0].to_owned();
let port = Some(
server.host_with_port().split(':').collect::<Vec<&str>>()[1]
.parse()
.unwrap(),
);
let mut app = App::default();
app.is_loading = true;
let radarr_config = RadarrConfig {
host,
api_token: String::default(),
port,
};
app.config.radarr = radarr_config;
let app_arc = Arc::new(Mutex::new(app));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_network_event(RadarrEvent::HealthCheck.into())
.await;
radarr_server.assert_async().await;
assert!(!app_arc.lock().await.is_loading);
}
#[rstest]
#[tokio::test]
async fn test_handle_request_no_response_body(
#[values(RequestMethod::Post, RequestMethod::Put, RequestMethod::Delete)]
request_method: RequestMethod,
) {
let mut server = Server::new_async().await;
let async_server = server
.mock(&request_method.to_string().to_uppercase(), "/test")
.match_header("X-Api-Key", "test1234")
.with_status(200)
.create_async()
.await;
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<Test, ()>(
RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body: Some(Test {
value: "Test".to_owned(),
}),
api_token: "test1234".to_owned(),
},
|_, _| (),
)
.await;
async_server.assert_async().await;
}
#[rstest]
#[tokio::test]
async fn test_handle_request_with_response_body(
#[values(RequestMethod::Get, RequestMethod::Post)] request_method: RequestMethod,
) {
let (async_server, app_arc, server) = mock_api(request_method, 200, true).await;
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert_str_eq!(app_arc.lock().await.error.text, "Test");
}
#[tokio::test]
async fn test_handle_request_get_invalid_body() {
let mut server = Server::new_async().await;
let async_server = server
.mock("GET", "/test")
.match_header("X-Api-Key", "test1234")
.with_status(200)
.with_body(r#"{ "invalid": "INVALID" }"#)
.create_async()
.await;
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: RequestMethod::Get,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert!(app_arc
.lock()
.await
.error
.text
.starts_with("Failed to parse response!"));
}
#[tokio::test]
async fn test_handle_request_failure_to_send_request() {
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: String::default(),
method: RequestMethod::Get,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
assert!(app_arc
.lock()
.await
.error
.text
.starts_with("Failed to send request."));
}
#[rstest]
#[tokio::test]
async fn test_handle_request_non_success_code(
#[values(
RequestMethod::Get,
RequestMethod::Post,
RequestMethod::Put,
RequestMethod::Delete
)]
request_method: RequestMethod,
) {
let (async_server, app_arc, server) = mock_api(request_method, 404, true).await;
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert_str_eq!(
app_arc.lock().await.error.text,
r#"Request failed. Received 404 Not Found response code with body: { "value": "Test" }"#
);
}
#[tokio::test]
async fn test_handle_request_non_success_code_empty_response_body() {
let (async_server, app_arc, server) = mock_api(RequestMethod::Post, 404, false).await;
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: RequestMethod::Post,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert_str_eq!(
app_arc.lock().await.error.text,
r#"Request failed. Received 404 Not Found response code with body: "#
);
}
#[rstest]
#[tokio::test]
async fn test_call_api(
#[values(
RequestMethod::Get,
RequestMethod::Post,
RequestMethod::Put,
RequestMethod::Delete
)]
request_method: RequestMethod,
) {
let mut server = Server::new_async().await;
let mut async_server = server
.mock(&request_method.to_string().to_uppercase(), "/test")
.match_header("X-Api-Key", "test1234")
.with_status(200);
let mut body = None::<Test>;
if request_method == RequestMethod::Post {
async_server = async_server.with_body(
r#"{
"value": "Test"
}"#,
);
body = Some(Test {
value: "Test".to_owned(),
});
}
async_server = async_server.create_async().await;
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.call_api(RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body,
api_token: "test1234".to_owned(),
})
.await
.send()
.await
.unwrap();
async_server.assert_async().await;
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct Test {
pub value: String,
}
async fn mock_api<'a>(
method: RequestMethod,
response_status: usize,
has_response_body: bool,
) -> (Mock, Arc<Mutex<App<'a>>>, ServerGuard) {
let mut server = Server::new_async().await;
let mut async_server = server
.mock(&method.to_string().to_uppercase(), "/test")
.match_header("X-Api-Key", "test1234")
.with_status(response_status);
if has_response_body {
async_server = async_server.with_body(
r#"{
"value": "Test"
}"#,
);
}
async_server = async_server.create_async().await;
let app_arc = Arc::new(Mutex::new(App::default()));
(async_server, app_arc, server)
}
}
+301
View File
@@ -0,0 +1,301 @@
#[cfg(test)]
mod tests {
use std::fmt::Debug;
use std::string::ToString;
use std::sync::Arc;
use mockito::{Mock, Server, ServerGuard};
use pretty_assertions::assert_str_eq;
use rstest::rstest;
use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;
use crate::app::{App, RadarrConfig};
use crate::models::HorizontallyScrollableText;
use crate::network::radarr_network::RadarrEvent;
use crate::network::{Network, RequestMethod, RequestProps};
#[tokio::test]
async fn test_handle_network_event_radarr_event() {
let mut server = Server::new_async().await;
let radarr_server = server
.mock("GET", "/api/v3/health")
.with_status(200)
.create_async()
.await;
let host = server.host_with_port().split(':').collect::<Vec<&str>>()[0].to_owned();
let port = Some(
server.host_with_port().split(':').collect::<Vec<&str>>()[1]
.parse()
.unwrap(),
);
let mut app = App::default();
app.is_loading = true;
let radarr_config = RadarrConfig {
host,
api_token: String::default(),
port,
};
app.config.radarr = radarr_config;
let app_arc = Arc::new(Mutex::new(app));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_network_event(RadarrEvent::HealthCheck.into())
.await;
radarr_server.assert_async().await;
assert!(!app_arc.lock().await.is_loading);
}
#[rstest]
#[tokio::test]
async fn test_handle_request_no_response_body(
#[values(RequestMethod::Post, RequestMethod::Put, RequestMethod::Delete)]
request_method: RequestMethod,
) {
let mut server = Server::new_async().await;
let async_server = server
.mock(&request_method.to_string().to_uppercase(), "/test")
.match_header("X-Api-Key", "test1234")
.with_status(200)
.create_async()
.await;
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<Test, ()>(
RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body: Some(Test {
value: "Test".to_owned(),
}),
api_token: "test1234".to_owned(),
},
|_, _| (),
)
.await;
async_server.assert_async().await;
}
#[rstest]
#[tokio::test]
async fn test_handle_request_with_response_body(
#[values(RequestMethod::Get, RequestMethod::Post)] request_method: RequestMethod,
) {
let (async_server, app_arc, server) = mock_api(request_method, 200, true).await;
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert_str_eq!(app_arc.lock().await.error.text, "Test");
}
#[tokio::test]
async fn test_handle_request_get_invalid_body() {
let mut server = Server::new_async().await;
let async_server = server
.mock("GET", "/test")
.match_header("X-Api-Key", "test1234")
.with_status(200)
.with_body(r#"{ "invalid": "INVALID" }"#)
.create_async()
.await;
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: RequestMethod::Get,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert!(app_arc
.lock()
.await
.error
.text
.starts_with("Failed to parse response!"));
}
#[tokio::test]
async fn test_handle_request_failure_to_send_request() {
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: String::default(),
method: RequestMethod::Get,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
assert!(app_arc
.lock()
.await
.error
.text
.starts_with("Failed to send request."));
}
#[rstest]
#[tokio::test]
async fn test_handle_request_non_success_code(
#[values(
RequestMethod::Get,
RequestMethod::Post,
RequestMethod::Put,
RequestMethod::Delete
)]
request_method: RequestMethod,
) {
let (async_server, app_arc, server) = mock_api(request_method, 404, true).await;
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert_str_eq!(
app_arc.lock().await.error.text,
r#"Request failed. Received 404 Not Found response code with body: { "value": "Test" }"#
);
}
#[tokio::test]
async fn test_handle_request_non_success_code_empty_response_body() {
let (async_server, app_arc, server) = mock_api(RequestMethod::Post, 404, false).await;
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.handle_request::<(), Test>(
RequestProps {
uri: format!("{}/test", server.url()),
method: RequestMethod::Post,
body: None,
api_token: "test1234".to_owned(),
},
|response, mut app| app.error = HorizontallyScrollableText::from(response.value),
)
.await;
async_server.assert_async().await;
assert_str_eq!(
app_arc.lock().await.error.text,
r#"Request failed. Received 404 Not Found response code with body: "#
);
}
#[rstest]
#[tokio::test]
async fn test_call_api(
#[values(
RequestMethod::Get,
RequestMethod::Post,
RequestMethod::Put,
RequestMethod::Delete
)]
request_method: RequestMethod,
) {
let mut server = Server::new_async().await;
let mut async_server = server
.mock(&request_method.to_string().to_uppercase(), "/test")
.match_header("X-Api-Key", "test1234")
.with_status(200);
let mut body = None::<Test>;
if request_method == RequestMethod::Post {
async_server = async_server.with_body(
r#"{
"value": "Test"
}"#,
);
body = Some(Test {
value: "Test".to_owned(),
});
}
async_server = async_server.create_async().await;
let app_arc = Arc::new(Mutex::new(App::default()));
let network = Network::new(reqwest::Client::new(), &app_arc);
network
.call_api(RequestProps {
uri: format!("{}/test", server.url()),
method: request_method,
body,
api_token: "test1234".to_owned(),
})
.await
.send()
.await
.unwrap();
async_server.assert_async().await;
}
#[derive(Serialize, Deserialize, Debug, Default)]
struct Test {
pub value: String,
}
async fn mock_api<'a>(
method: RequestMethod,
response_status: usize,
has_response_body: bool,
) -> (Mock, Arc<Mutex<App<'a>>>, ServerGuard) {
let mut server = Server::new_async().await;
let mut async_server = server
.mock(&method.to_string().to_uppercase(), "/test")
.match_header("X-Api-Key", "test1234")
.with_status(response_status);
if has_response_body {
async_server = async_server.with_body(
r#"{
"value": "Test"
}"#,
);
}
async_server = async_server.create_async().await;
let app_arc = Arc::new(Mutex::new(App::default()));
(async_server, app_arc, server)
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+21 -1
View File
@@ -566,7 +566,7 @@ pub fn draw_drop_down_menu_button<B: Backend>(
draw_button_with_icon(f, horizontal_chunks[1], selection, "", is_selected);
}
pub fn draw_drop_down_list<'a, B: Backend, T>(
pub fn draw_selectable_list<'a, B: Backend, T>(
f: &mut Frame<'_, B>,
area: Rect,
content: &'a mut StatefulList<T>,
@@ -580,6 +580,26 @@ pub fn draw_drop_down_list<'a, B: Backend, T>(
f.render_stateful_widget(list, area, &mut content.state);
}
pub fn draw_list_box<'a, B: Backend, T>(
f: &mut Frame<'_, B>,
area: Rect,
content: &'a mut StatefulList<T>,
title: &str,
item_mapper: impl Fn(&T) -> ListItem<'a>,
is_loading: bool,
) {
let block = title_block(title);
if !content.items.is_empty() {
let items: Vec<ListItem<'_>> = content.items.iter().map(item_mapper).collect();
let list = List::new(items).block(title_block(title));
f.render_stateful_widget(list, area, &mut content.state);
} else {
loading(f, block, area, is_loading);
}
}
pub fn draw_text_box<B: Backend>(
f: &mut Frame<'_, B>,
text_box_area: Rect,
+3 -3
View File
@@ -20,8 +20,8 @@ use crate::ui::utils::{
vertical_chunks_with_margin,
};
use crate::ui::{
draw_button, draw_drop_down_list, draw_drop_down_menu_button, draw_drop_down_popup,
draw_error_popup, draw_error_popup_over, draw_large_popup_over, draw_medium_popup_over,
draw_button, draw_drop_down_menu_button, draw_drop_down_popup, draw_error_popup,
draw_error_popup_over, draw_large_popup_over, draw_medium_popup_over, draw_selectable_list,
draw_table, draw_text_box, draw_text_box_with_label, DrawUi, TableProps,
};
use crate::utils::convert_runtime;
@@ -311,7 +311,7 @@ fn draw_select_monitor_popup<B: Backend>(
app: &mut App<'_>,
popup_area: Rect,
) {
draw_drop_down_list(
draw_selectable_list(
f,
popup_area,
&mut app.data.radarr_data.monitor_list,
+7 -4
View File
@@ -18,9 +18,10 @@ use crate::app::App;
use crate::logos::RADARR_LOGO;
use crate::models::radarr_models::{DiskSpace, DownloadRecord, Movie, RootFolder};
use crate::models::Route;
use crate::ui::draw_drop_down_list;
use crate::ui::draw_selectable_list;
use crate::ui::draw_tabs;
use crate::ui::loading;
use crate::ui::radarr_ui::system_ui::SystemUi;
use crate::ui::radarr_ui::{
add_movie_ui::AddMoviesUi, collection_details_ui::CollectionDetailsUi,
collections_ui::CollectionsUi, delete_movie_ui::DeleteMovieUi, downloads_ui::DownloadsUi,
@@ -45,6 +46,7 @@ mod edit_movie_ui;
mod library_ui;
mod movie_details_ui;
mod root_folders_ui;
mod system_ui;
pub(super) struct RadarrUi {}
@@ -70,6 +72,7 @@ impl DrawUi for RadarrUi {
ActiveRadarrBlock::RootFolders
| ActiveRadarrBlock::AddRootFolderPrompt
| ActiveRadarrBlock::DeleteRootFolderPrompt => RootFoldersUi::draw(f, app, content_rect),
ActiveRadarrBlock::System => SystemUi::draw(f, app, content_rect),
_ if MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block) => {
MovieDetailsUi::draw(f, app, content_rect)
}
@@ -265,7 +268,7 @@ fn draw_select_minimum_availability_popup<B: Backend>(
app: &mut App<'_>,
popup_area: Rect,
) {
draw_drop_down_list(
draw_selectable_list(
f,
popup_area,
&mut app.data.radarr_data.minimum_availability_list,
@@ -278,7 +281,7 @@ fn draw_select_quality_profile_popup<B: Backend>(
app: &mut App<'_>,
popup_area: Rect,
) {
draw_drop_down_list(
draw_selectable_list(
f,
popup_area,
&mut app.data.radarr_data.quality_profile_list,
@@ -291,7 +294,7 @@ fn draw_select_root_folder_popup<B: Backend>(
app: &mut App<'_>,
popup_area: Rect,
) {
draw_drop_down_list(
draw_selectable_list(
f,
popup_area,
&mut app.data.radarr_data.root_folder_list,
+4 -4
View File
@@ -18,9 +18,9 @@ use crate::ui::utils::{
style_primary, style_success, style_warning, vertical_chunks,
};
use crate::ui::{
draw_drop_down_list, draw_drop_down_popup, draw_large_popup_over, draw_prompt_box,
draw_prompt_box_with_content, draw_prompt_popup_over, draw_small_popup_over, draw_table,
draw_tabs, loading, DrawUi, TableProps,
draw_drop_down_popup, draw_large_popup_over, draw_prompt_box, draw_prompt_box_with_content,
draw_prompt_popup_over, draw_selectable_list, draw_small_popup_over, draw_table, draw_tabs,
loading, DrawUi, TableProps,
};
use crate::utils::convert_to_gb;
@@ -58,7 +58,7 @@ impl DrawUi for MovieDetailsUi {
content_area,
draw_movie_info,
|f, app, content_area| {
draw_drop_down_list(
draw_selectable_list(
f,
content_area,
&mut app.data.radarr_data.movie_releases_sort,
+147
View File
@@ -0,0 +1,147 @@
use crate::ui::utils::{style_primary, style_secondary};
use crate::ui::{draw_table, TableProps};
use crate::{
app::{radarr::ActiveRadarrBlock, App},
models::Route,
ui::{
draw_list_box,
utils::{horizontal_chunks, style_default, style_failure, title_block, vertical_chunks},
DrawUi,
},
};
use chrono::DateTime;
use std::ops::Sub;
use tui::style::Modifier;
use tui::text::{Span, Text};
use tui::widgets::{Cell, Row};
use tui::{
backend::Backend,
layout::{Constraint, Rect},
style::{Color, Style},
widgets::ListItem,
Frame,
};
pub(super) struct SystemUi {}
impl DrawUi for SystemUi {
fn draw<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, content_rect: Rect) {
if matches!(
*app.get_current_route(),
Route::Radarr(ActiveRadarrBlock::System, _)
) {
draw_system_ui_layout(f, app, content_rect)
}
}
}
fn draw_system_ui_layout<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let vertical_chunks =
vertical_chunks(vec![Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)], area);
let horizontal_chunks = horizontal_chunks(
vec![Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)],
vertical_chunks[0],
);
draw_tasks(f, app, horizontal_chunks[0]);
f.render_widget(title_block("Queue"), horizontal_chunks[1]);
draw_logs(f, app, vertical_chunks[1]);
}
fn draw_tasks<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
let block = title_block("Tasks");
draw_table(
f,
area,
block,
TableProps {
content: &mut app.data.radarr_data.tasks,
table_headers: vec![
"Name",
"Interval",
"Last Execution",
"Last Duration",
"Next Duration",
],
constraints: vec![
Constraint::Percentage(30),
Constraint::Percentage(12),
Constraint::Percentage(16),
Constraint::Percentage(16),
Constraint::Percentage(16),
],
help: None,
},
|task| {
let interval = format!("{} hours", task.interval.as_u64().as_ref().unwrap() / 60);
let last_duration = &task.last_duration[..8];
let next_execution = task.next_execution.sub(DateTime::default()).num_minutes();
let next_execution_string = if next_execution > 60 {
format!("{} hours", next_execution / 60)
} else {
format!("{} minutes", next_execution)
};
let last_execution = task.last_execution.sub(DateTime::default()).num_minutes();
let last_execution_string = if last_execution > 60 {
format!("{} hours", last_execution / 60)
} else {
format!("{} minutes", last_execution)
};
Row::new(vec![
Cell::from(task.name.clone()),
Cell::from(interval),
Cell::from(last_execution_string),
Cell::from(last_duration.to_owned()),
Cell::from(next_execution_string),
])
.style(style_primary())
},
app.is_loading,
);
}
fn draw_logs<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) {
draw_list_box(
f,
area,
&mut app.data.radarr_data.logs,
"Logs",
|log| {
let log_line = if log.exception.is_some() {
Text::from(Span::raw(format!(
"{}|{}|{}|{}|{}",
log.time,
log.level.as_ref().unwrap().to_uppercase(),
log.logger.as_ref().unwrap(),
log.exception_type.as_ref().unwrap(),
log.exception.as_ref().unwrap()
)))
} else {
Text::from(Span::raw(format!(
"{}|{}|{}|{}",
log.time,
log.level.as_ref().unwrap().to_uppercase(),
log.logger.as_ref().unwrap(),
log.message.as_ref().unwrap()
)))
};
ListItem::new(log_line).style(determine_log_style_by_level(log.level.as_ref().unwrap()))
},
app.is_loading,
);
}
fn determine_log_style_by_level(level: &str) -> Style {
match level.to_lowercase().as_str() {
"trace" => Style::default().fg(Color::Gray),
"debug" => Style::default().fg(Color::Blue),
"info" => style_default(),
"warn" => style_secondary(),
"error" => style_failure(),
"fatal" => style_failure().add_modifier(Modifier::BOLD),
_ => style_default(),
}
}
+4 -410
View File
@@ -16,6 +16,10 @@ pub const COLOR_ORANGE: Color = Color::Rgb(255, 170, 66);
pub const COLOR_WHITE: Color = Color::White;
pub const COLOR_MAGENTA: Color = Color::Magenta;
#[cfg(test)]
#[path = "utils_tests.rs"]
mod utils_tests;
pub fn horizontal_chunks(constraints: Vec<Constraint>, area: Rect) -> Rc<[Rect]> {
layout_with_constraints(constraints)
.direction(Direction::Horizontal)
@@ -271,413 +275,3 @@ pub fn show_cursor<B: Backend>(f: &mut Frame<'_, B>, area: Rect, offset: usize,
pub fn get_width_from_percentage(area: Rect, percentage: u16) -> usize {
(area.width as f64 * (percentage as f64 / 100.0)) as usize
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use tui::style::{Color, Modifier, Style};
use tui::text::{Span, Spans};
use tui::widgets::{Block, BorderType, Borders};
use crate::ui::utils::{
borderless_block, centered_rect, get_width_from_percentage, horizontal_chunks,
horizontal_chunks_with_margin, layout_block, layout_block_bottom_border,
layout_block_top_border, layout_block_top_border_with_title, layout_block_with_title,
layout_with_constraints, logo_block, spans_info_default, spans_info_primary,
spans_info_with_style, style_block_highlight, style_bold, style_default, style_default_bold,
style_failure, style_help, style_highlight, style_primary, style_secondary, style_success,
style_system_function, style_unmonitored, style_warning, title_block, title_block_centered,
title_style, vertical_chunks, vertical_chunks_with_margin,
};
#[test]
fn test_horizontal_chunks() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Horizontal)
.split(area);
assert_eq!(horizontal_chunks(constraints.into(), area), expected_layout);
}
#[test]
fn test_horizontal_chunks_with_margin() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Horizontal)
.margin(1)
.split(area);
assert_eq!(
horizontal_chunks_with_margin(constraints.into(), area, 1),
expected_layout
);
}
#[test]
fn test_vertical_chunks() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Vertical)
.split(area);
assert_eq!(vertical_chunks(constraints.into(), area), expected_layout);
}
#[test]
fn test_vertical_chunks_with_margin() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Vertical)
.margin(1)
.split(area);
assert_eq!(
vertical_chunks_with_margin(constraints.into(), area, 1),
expected_layout
);
}
#[test]
fn test_layout_with_constraints() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let expected_layout = Layout::default().constraints(constraints);
assert_eq!(layout_with_constraints(constraints.into()), expected_layout);
}
#[test]
fn test_layout_block() {
assert_eq!(
layout_block(),
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
);
}
#[test]
fn test_layout_block_with_title() {
let title_span = Span::styled(
"title",
Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::BOLD),
);
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(title_span.clone());
assert_eq!(layout_block_with_title(title_span), expected_block);
}
#[test]
fn test_layout_block_top_border_with_title() {
let title_span = Span::styled(
"title",
Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::BOLD),
);
let expected_block = Block::default()
.borders(Borders::TOP)
.title(title_span.clone());
assert_eq!(
layout_block_top_border_with_title(title_span),
expected_block
);
}
#[test]
fn test_layout_block_top_border() {
assert_eq!(
layout_block_top_border(),
Block::default().borders(Borders::TOP)
);
}
#[test]
fn test_layout_block_bottom_border() {
assert_eq!(
layout_block_bottom_border(),
Block::default().borders(Borders::BOTTOM)
);
}
#[test]
fn test_borderless_block() {
assert_eq!(borderless_block(), Block::default());
}
#[test]
fn test_spans_info_with_style() {
let first_style = Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::BOLD);
let second_style = Style::default()
.fg(Color::LightYellow)
.add_modifier(Modifier::ITALIC);
let expected_spans = Spans::from(vec![
Span::styled("title".to_owned(), first_style),
Span::styled("content".to_owned(), second_style),
]);
assert_eq!(
spans_info_with_style(
"title".to_owned(),
"content".to_owned(),
first_style,
second_style
),
expected_spans
);
}
#[test]
fn test_spans_info_default() {
let expected_spans = Spans::from(vec![
Span::styled(
"title".to_owned(),
Style::default().add_modifier(Modifier::BOLD),
),
Span::styled("content".to_owned(), Style::default().fg(Color::White)),
]);
assert_eq!(
spans_info_default("title".to_owned(), "content".to_owned()),
expected_spans
);
}
#[test]
fn test_spans_info_primary() {
let expected_spans = Spans::from(vec![
Span::styled(
"title".to_owned(),
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
),
Span::styled("content".to_owned(), Style::default().fg(Color::White)),
]);
assert_eq!(
spans_info_primary("title".to_owned(), "content".to_owned()),
expected_spans
);
}
#[test]
fn test_style_bold() {
assert_eq!(style_bold(), Style::default().add_modifier(Modifier::BOLD));
}
#[test]
fn test_style_highlight() {
assert_eq!(
style_highlight(),
Style::default().add_modifier(Modifier::REVERSED)
);
}
#[test]
fn test_style_unmonitored() {
assert_eq!(style_unmonitored(), Style::default().fg(Color::White));
}
#[test]
fn test_style_default() {
assert_eq!(style_default(), Style::default().fg(Color::White));
}
#[test]
fn test_style_default_bold() {
assert_eq!(
style_default_bold(),
Style::default()
.fg(Color::White)
.add_modifier(Modifier::BOLD)
);
}
#[test]
fn test_style_primary() {
assert_eq!(style_primary(), Style::default().fg(Color::Cyan));
}
#[test]
fn test_style_secondary() {
assert_eq!(style_secondary(), Style::default().fg(Color::Yellow));
}
#[test]
fn test_style_system_function() {
assert_eq!(style_system_function(), Style::default().fg(Color::Yellow));
}
#[test]
fn test_style_success() {
assert_eq!(style_success(), Style::default().fg(Color::Green));
}
#[test]
fn test_style_warning() {
assert_eq!(style_warning(), Style::default().fg(Color::Magenta));
}
#[test]
fn test_style_failure() {
assert_eq!(style_failure(), Style::default().fg(Color::Red));
}
#[test]
fn test_style_help() {
assert_eq!(style_help(), Style::default().fg(Color::LightBlue));
}
#[test]
fn test_style_button_highlight_selected() {
let expected_style = Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD);
assert_eq!(style_block_highlight(true), expected_style);
}
#[test]
fn test_style_button_highlight_unselected() {
let expected_style = Style::default()
.fg(Color::White)
.add_modifier(Modifier::BOLD);
assert_eq!(style_block_highlight(false), expected_style);
}
#[test]
fn test_title_style() {
let expected_span = Span::styled(" test ", Style::default().add_modifier(Modifier::BOLD));
assert_eq!(title_style("test"), expected_span);
}
#[test]
fn test_title_block() {
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Span::styled(
" test ",
Style::default().add_modifier(Modifier::BOLD),
));
assert_eq!(title_block("test"), expected_block);
}
#[test]
fn test_title_block_centered() {
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Span::styled(
" test ",
Style::default().add_modifier(Modifier::BOLD),
))
.title_alignment(Alignment::Center);
assert_eq!(title_block_centered("test"), expected_block);
}
#[test]
fn test_logo_block() {
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Span::styled(
" Managarr - A Servarr management TUI ",
Style::default()
.fg(Color::Magenta)
.add_modifier(Modifier::BOLD)
.add_modifier(Modifier::ITALIC),
));
assert_eq!(logo_block(), expected_block);
}
#[test]
fn test_centered_rect() {
let expected_rect = Rect {
x: 30,
y: 45,
width: 60,
height: 90,
};
assert_eq!(centered_rect(50, 50, rect()), expected_rect);
}
#[test]
fn test_get_width_from_percentage() {
assert_eq!(
get_width_from_percentage(
Rect {
x: 0,
y: 0,
width: 100,
height: 10
},
30
),
30
);
}
fn rect() -> Rect {
Rect {
x: 0,
y: 0,
width: 120,
height: 180,
}
}
}
+409
View File
@@ -0,0 +1,409 @@
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use tui::style::{Color, Modifier, Style};
use tui::text::{Span, Spans};
use tui::widgets::{Block, BorderType, Borders};
use crate::ui::utils::{
borderless_block, centered_rect, get_width_from_percentage, horizontal_chunks,
horizontal_chunks_with_margin, layout_block, layout_block_bottom_border,
layout_block_top_border, layout_block_top_border_with_title, layout_block_with_title,
layout_with_constraints, logo_block, spans_info_default, spans_info_primary,
spans_info_with_style, style_block_highlight, style_bold, style_default, style_default_bold,
style_failure, style_help, style_highlight, style_primary, style_secondary, style_success,
style_system_function, style_unmonitored, style_warning, title_block, title_block_centered,
title_style, vertical_chunks, vertical_chunks_with_margin,
};
#[test]
fn test_horizontal_chunks() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Horizontal)
.split(area);
assert_eq!(horizontal_chunks(constraints.into(), area), expected_layout);
}
#[test]
fn test_horizontal_chunks_with_margin() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Horizontal)
.margin(1)
.split(area);
assert_eq!(
horizontal_chunks_with_margin(constraints.into(), area, 1),
expected_layout
);
}
#[test]
fn test_vertical_chunks() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Vertical)
.split(area);
assert_eq!(vertical_chunks(constraints.into(), area), expected_layout);
}
#[test]
fn test_vertical_chunks_with_margin() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let area = rect();
let expected_layout = Layout::default()
.constraints(constraints)
.direction(Direction::Vertical)
.margin(1)
.split(area);
assert_eq!(
vertical_chunks_with_margin(constraints.into(), area, 1),
expected_layout
);
}
#[test]
fn test_layout_with_constraints() {
let constraints = [
Constraint::Percentage(10),
Constraint::Max(20),
Constraint::Min(10),
Constraint::Length(30),
Constraint::Ratio(3, 4),
];
let expected_layout = Layout::default().constraints(constraints);
assert_eq!(layout_with_constraints(constraints.into()), expected_layout);
}
#[test]
fn test_layout_block() {
assert_eq!(
layout_block(),
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
);
}
#[test]
fn test_layout_block_with_title() {
let title_span = Span::styled(
"title",
Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::BOLD),
);
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(title_span.clone());
assert_eq!(layout_block_with_title(title_span), expected_block);
}
#[test]
fn test_layout_block_top_border_with_title() {
let title_span = Span::styled(
"title",
Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::BOLD),
);
let expected_block = Block::default()
.borders(Borders::TOP)
.title(title_span.clone());
assert_eq!(
layout_block_top_border_with_title(title_span),
expected_block
);
}
#[test]
fn test_layout_block_top_border() {
assert_eq!(
layout_block_top_border(),
Block::default().borders(Borders::TOP)
);
}
#[test]
fn test_layout_block_bottom_border() {
assert_eq!(
layout_block_bottom_border(),
Block::default().borders(Borders::BOTTOM)
);
}
#[test]
fn test_borderless_block() {
assert_eq!(borderless_block(), Block::default());
}
#[test]
fn test_spans_info_with_style() {
let first_style = Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::BOLD);
let second_style = Style::default()
.fg(Color::LightYellow)
.add_modifier(Modifier::ITALIC);
let expected_spans = Spans::from(vec![
Span::styled("title".to_owned(), first_style),
Span::styled("content".to_owned(), second_style),
]);
assert_eq!(
spans_info_with_style(
"title".to_owned(),
"content".to_owned(),
first_style,
second_style
),
expected_spans
);
}
#[test]
fn test_spans_info_default() {
let expected_spans = Spans::from(vec![
Span::styled(
"title".to_owned(),
Style::default().add_modifier(Modifier::BOLD),
),
Span::styled("content".to_owned(), Style::default().fg(Color::White)),
]);
assert_eq!(
spans_info_default("title".to_owned(), "content".to_owned()),
expected_spans
);
}
#[test]
fn test_spans_info_primary() {
let expected_spans = Spans::from(vec![
Span::styled(
"title".to_owned(),
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
),
Span::styled("content".to_owned(), Style::default().fg(Color::White)),
]);
assert_eq!(
spans_info_primary("title".to_owned(), "content".to_owned()),
expected_spans
);
}
#[test]
fn test_style_bold() {
assert_eq!(style_bold(), Style::default().add_modifier(Modifier::BOLD));
}
#[test]
fn test_style_highlight() {
assert_eq!(
style_highlight(),
Style::default().add_modifier(Modifier::REVERSED)
);
}
#[test]
fn test_style_unmonitored() {
assert_eq!(style_unmonitored(), Style::default().fg(Color::White));
}
#[test]
fn test_style_default() {
assert_eq!(style_default(), Style::default().fg(Color::White));
}
#[test]
fn test_style_default_bold() {
assert_eq!(
style_default_bold(),
Style::default()
.fg(Color::White)
.add_modifier(Modifier::BOLD)
);
}
#[test]
fn test_style_primary() {
assert_eq!(style_primary(), Style::default().fg(Color::Cyan));
}
#[test]
fn test_style_secondary() {
assert_eq!(style_secondary(), Style::default().fg(Color::Yellow));
}
#[test]
fn test_style_system_function() {
assert_eq!(style_system_function(), Style::default().fg(Color::Yellow));
}
#[test]
fn test_style_success() {
assert_eq!(style_success(), Style::default().fg(Color::Green));
}
#[test]
fn test_style_warning() {
assert_eq!(style_warning(), Style::default().fg(Color::Magenta));
}
#[test]
fn test_style_failure() {
assert_eq!(style_failure(), Style::default().fg(Color::Red));
}
#[test]
fn test_style_help() {
assert_eq!(style_help(), Style::default().fg(Color::LightBlue));
}
#[test]
fn test_style_button_highlight_selected() {
let expected_style = Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD);
assert_eq!(style_block_highlight(true), expected_style);
}
#[test]
fn test_style_button_highlight_unselected() {
let expected_style = Style::default()
.fg(Color::White)
.add_modifier(Modifier::BOLD);
assert_eq!(style_block_highlight(false), expected_style);
}
#[test]
fn test_title_style() {
let expected_span = Span::styled(" test ", Style::default().add_modifier(Modifier::BOLD));
assert_eq!(title_style("test"), expected_span);
}
#[test]
fn test_title_block() {
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Span::styled(
" test ",
Style::default().add_modifier(Modifier::BOLD),
));
assert_eq!(title_block("test"), expected_block);
}
#[test]
fn test_title_block_centered() {
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Span::styled(
" test ",
Style::default().add_modifier(Modifier::BOLD),
))
.title_alignment(Alignment::Center);
assert_eq!(title_block_centered("test"), expected_block);
}
#[test]
fn test_logo_block() {
let expected_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Span::styled(
" Managarr - A Servarr management TUI ",
Style::default()
.fg(Color::Magenta)
.add_modifier(Modifier::BOLD)
.add_modifier(Modifier::ITALIC),
));
assert_eq!(logo_block(), expected_block);
}
#[test]
fn test_centered_rect() {
let expected_rect = Rect {
x: 30,
y: 45,
width: 60,
height: 90,
};
assert_eq!(centered_rect(50, 50, rect()), expected_rect);
}
#[test]
fn test_get_width_from_percentage() {
assert_eq!(
get_width_from_percentage(
Rect {
x: 0,
y: 0,
width: 100,
height: 10
},
30
),
30
);
}
fn rect() -> Rect {
Rect {
x: 0,
y: 0,
width: 120,
height: 180,
}
}
}
+4 -29
View File
@@ -4,6 +4,10 @@ use log4rs::config::{Appender, Root};
use log4rs::encode::pattern::PatternEncoder;
use regex::Regex;
#[cfg(test)]
#[path = "utils_tests.rs"]
mod utils_tests;
pub fn init_logging_config() -> log4rs::Config {
let file_path = "/tmp/managarr.log";
let logfile = FileAppender::builder()
@@ -40,32 +44,3 @@ pub fn strip_non_search_characters(input: &str) -> String {
.replace_all(&input.to_lowercase(), "")
.to_string()
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use crate::utils::{convert_runtime, convert_to_gb, strip_non_search_characters};
#[test]
fn test_convert_to_gb() {
assert_eq!(convert_to_gb(2147483648), 2f64);
assert_eq!(convert_to_gb(2662879723), 2.4799999995157123);
}
#[test]
fn test_convert_runtime() {
let (hours, minutes) = convert_runtime(154);
assert_eq!(hours, 2);
assert_eq!(minutes, 34);
}
#[test]
fn test_strip_non_alphanumeric_characters() {
assert_eq!(
strip_non_search_characters("Te$t S7r!ng::'~-@_`,(.)/*}^&%#+="),
"tet s7rng::'-,./".to_owned()
)
}
}
+28
View File
@@ -0,0 +1,28 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use crate::utils::{convert_runtime, convert_to_gb, strip_non_search_characters};
#[test]
fn test_convert_to_gb() {
assert_eq!(convert_to_gb(2147483648), 2f64);
assert_eq!(convert_to_gb(2662879723), 2.4799999995157123);
}
#[test]
fn test_convert_runtime() {
let (hours, minutes) = convert_runtime(154);
assert_eq!(hours, 2);
assert_eq!(minutes, 34);
}
#[test]
fn test_strip_non_alphanumeric_characters() {
assert_eq!(
strip_non_search_characters("Te$t S7r!ng::'~-@_`,(.)/*}^&%#+="),
"tet s7rng::'-,./".to_owned()
)
}
}