Partial implementation of Tasks and Logs and test refactor
This commit is contained in:
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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(), ¤t_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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
+54
-1858
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+21
-1
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user