diff --git a/src/handlers/lidarr_handlers/library/delete_artist_handler.rs b/src/handlers/lidarr_handlers/library/delete_artist_handler.rs index 31affd7..89fc39d 100644 --- a/src/handlers/lidarr_handlers/library/delete_artist_handler.rs +++ b/src/handlers/lidarr_handlers/library/delete_artist_handler.rs @@ -1,3 +1,4 @@ +use crate::models::Route; use crate::models::lidarr_models::DeleteArtistParams; use crate::network::lidarr_network::LidarrEvent; use crate::{ @@ -7,7 +8,6 @@ use crate::{ matches_key, models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, DELETE_ARTIST_BLOCKS}, }; -use crate::models::Route; #[cfg(test)] #[path = "delete_artist_handler_tests.rs"] diff --git a/src/handlers/lidarr_handlers/library/edit_artist_handler.rs b/src/handlers/lidarr_handlers/library/edit_artist_handler.rs index 3b62fae..194a5e0 100644 --- a/src/handlers/lidarr_handlers/library/edit_artist_handler.rs +++ b/src/handlers/lidarr_handlers/library/edit_artist_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; -use crate::models::{Route, Scrollable}; use crate::models::lidarr_models::EditArtistParams; use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, EDIT_ARTIST_BLOCKS}; use crate::models::servarr_data::lidarr::modals::EditArtistModal; +use crate::models::{Route, Scrollable}; use crate::network::lidarr_network::LidarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; diff --git a/src/handlers/lidarr_handlers/library/edit_artist_handler_tests.rs b/src/handlers/lidarr_handlers/library/edit_artist_handler_tests.rs index 1f1ed9b..fee625c 100644 --- a/src/handlers/lidarr_handlers/library/edit_artist_handler_tests.rs +++ b/src/handlers/lidarr_handlers/library/edit_artist_handler_tests.rs @@ -1,28 +1,214 @@ #[cfg(test)] mod tests { - use pretty_assertions::assert_eq; + use bimap::BiMap; + use pretty_assertions::{assert_eq, assert_str_eq}; + use rstest::rstest; use strum::IntoEnumIterator; use crate::app::App; use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; use crate::handlers::KeyEventHandler; use crate::handlers::lidarr_handlers::library::edit_artist_handler::EditArtistHandler; + use crate::models::lidarr_models::{Artist, EditArtistParams, NewItemMonitorType}; use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, EDIT_ARTIST_BLOCKS}; use crate::models::servarr_data::lidarr::modals::EditArtistModal; + use crate::network::lidarr_network::LidarrEvent; mod test_handle_scroll_up_and_down { use pretty_assertions::assert_eq; use rstest::rstest; + use strum::IntoEnumIterator; use crate::models::BlockSelectionState; use crate::models::servarr_data::lidarr::lidarr_data::EDIT_ARTIST_SELECTION_BLOCKS; use super::*; + #[rstest] + fn test_edit_artist_select_monitor_new_items_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let monitor_type_vec = Vec::from_iter(NewItemMonitorType::iter()); + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .monitor_list + .set_items(monitor_type_vec.clone()); + + if key == Key::Up { + for i in (0..monitor_type_vec.len()).rev() { + EditArtistHandler::new( + key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_type_vec[i] + ); + } + } else { + for i in 0..monitor_type_vec.len() { + EditArtistHandler::new( + key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_type_vec[(i + 1) % monitor_type_vec.len()] + ); + } + } + } + + #[rstest] + fn test_edit_artist_select_quality_profile_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]); + + EditArtistHandler::new( + key, + &mut app, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 2" + ); + + EditArtistHandler::new( + key, + &mut app, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } + + #[rstest] + fn test_edit_artist_select_metadata_profile_scroll( + #[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key, + ) { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .metadata_profile_list + .set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]); + + EditArtistHandler::new( + key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .metadata_profile_list + .current_selection(), + "Test 2" + ); + + EditArtistHandler::new( + key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .metadata_profile_list + .current_selection(), + "Test 1" + ); + } + #[rstest] fn test_edit_artist_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) { let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); app.data.lidarr_data.selected_block.down(); @@ -45,6 +231,7 @@ mod tests { #[rstest] fn test_edit_artist_prompt_scroll_no_op_when_not_ready(#[values(Key::Up, Key::Down)] key: Key) { let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); app.is_loading = true; app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); @@ -59,7 +246,300 @@ mod tests { } } + mod test_handle_home_end { + use pretty_assertions::assert_eq; + use std::sync::atomic::Ordering; + + use strum::IntoEnumIterator; + + use crate::models::servarr_data::lidarr::modals::EditArtistModal; + + use super::*; + + #[test] + fn test_edit_artist_select_monitor_new_items_home_end() { + let monitor_type_vec = Vec::from_iter(NewItemMonitorType::iter()); + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .monitor_list + .set_items(monitor_type_vec.clone()); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_type_vec[monitor_type_vec.len() - 1] + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .monitor_list + .current_selection(), + &monitor_type_vec[0] + ); + } + + #[test] + fn test_edit_artist_select_quality_profile_home_end() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .quality_profile_list + .set_items(vec![ + "Test 1".to_owned(), + "Test 2".to_owned(), + "Test 3".to_owned(), + ]); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 3" + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .quality_profile_list + .current_selection(), + "Test 1" + ); + } + + #[test] + fn test_edit_artist_select_metadata_profile_home_end() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .metadata_profile_list + .set_items(vec![ + "Test 1".to_owned(), + "Test 2".to_owned(), + "Test 3".to_owned(), + ]); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .metadata_profile_list + .current_selection(), + "Test 3" + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .metadata_profile_list + .current_selection(), + "Test 1" + ); + } + + #[test] + fn test_edit_artist_path_input_home_end_keys() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + path: "Test".into(), + ..EditArtistModal::default() + }); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .offset + .load(Ordering::SeqCst), + 4 + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .offset + .load(Ordering::SeqCst), + 0 + ); + } + + #[test] + fn test_edit_artist_tags_input_home_end_keys() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + tags: "Test".into(), + ..EditArtistModal::default() + }); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .tags + .offset + .load(Ordering::SeqCst), + 4 + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .tags + .offset + .load(Ordering::SeqCst), + 0 + ); + } + } + mod test_handle_left_right_action { + use pretty_assertions::assert_eq; + use std::sync::atomic::Ordering; + + use crate::models::servarr_data::lidarr::modals::EditArtistModal; use rstest::rstest; use super::*; @@ -67,8 +547,8 @@ mod tests { #[rstest] fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) { let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); - app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); EditArtistHandler::new(key, &mut app, ActiveLidarrBlock::EditArtistPrompt, None).handle(); @@ -78,17 +558,193 @@ mod tests { assert!(!app.data.lidarr_data.prompt_confirm); } + + #[test] + fn test_edit_artist_path_input_left_right_keys() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + path: "Test".into(), + ..EditArtistModal::default() + }); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.left.key, + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .offset + .load(Ordering::SeqCst), + 1 + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.right.key, + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .offset + .load(Ordering::SeqCst), + 0 + ); + } + + #[test] + fn test_edit_artist_tags_input_left_right_keys() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + tags: "Test".into(), + ..EditArtistModal::default() + }); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.left.key, + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .tags + .offset + .load(Ordering::SeqCst), + 1 + ); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.right.key, + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .tags + .offset + .load(Ordering::SeqCst), + 0 + ); + } } mod test_handle_submit { - use crate::models::BlockSelectionState; + use crate::assert_navigation_popped; use crate::models::servarr_data::lidarr::lidarr_data::EDIT_ARTIST_SELECTION_BLOCKS; + use crate::models::{BlockSelectionState, Route}; + use pretty_assertions::assert_eq; + use rstest::rstest; use super::*; - use crate::assert_navigation_popped; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; + #[test] + fn test_edit_artist_path_input_submit() { + let mut app = App::test_default(); + app.ignore_special_keys_for_textbox_input = true; + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + path: "Test Path".into(), + ..EditArtistModal::default() + }); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPathInput.into()); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert!(!app.ignore_special_keys_for_textbox_input); + assert!( + !app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .text + .is_empty() + ); + assert_navigation_popped!(app, ActiveLidarrBlock::EditArtistPrompt.into()); + } + + #[test] + fn test_edit_artist_tags_input_submit() { + let mut app = App::test_default(); + app.ignore_special_keys_for_textbox_input = true; + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + tags: "Test Tags".into(), + ..EditArtistModal::default() + }); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistTagsInput.into()); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert!(!app.ignore_special_keys_for_textbox_input); + assert!( + !app + .data + .lidarr_data + .edit_artist_modal + .as_mut() + .unwrap() + .tags + .text + .is_empty() + ); + assert_navigation_popped!(app, ActiveLidarrBlock::EditArtistPrompt.into()); + } + #[test] fn test_edit_artist_prompt_prompt_decline_submit() { let mut app = App::test_default(); @@ -96,10 +752,11 @@ mod tests { app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); - // Navigate to the confirm prompt (last selection block) - for _ in 0..EDIT_ARTIST_SELECTION_BLOCKS.len() - 1 { - app.data.lidarr_data.selected_block.down(); - } + app + .data + .lidarr_data + .selected_block + .set_index(0, EDIT_ARTIST_SELECTION_BLOCKS.len() - 1); EditArtistHandler::new( SUBMIT_KEY, @@ -109,72 +766,620 @@ mod tests { ) .handle(); - assert!(app.data.lidarr_data.prompt_confirm_action.is_none()); - assert_navigation_popped!(&app, ActiveLidarrBlock::Artists.into()); + assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into()); + assert_none!(app.data.lidarr_data.prompt_confirm_action); } - } - - mod test_handle_esc { - use super::*; - use crate::assert_navigation_popped; - - const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; #[test] - fn test_edit_artist_prompt_esc() { + fn test_edit_artist_confirm_prompt_prompt_confirmation_submit() { let mut app = App::test_default(); + let mut edit_artist = EditArtistModal { + tags: "usenet, testing".to_owned().into(), + path: "/nfs/Test Path".to_owned().into(), + monitored: Some(false), + ..EditArtistModal::default() + }; + edit_artist + .quality_profile_list + .set_items(vec!["Lossless".to_owned(), "HD - 1080p".to_owned()]); + edit_artist + .metadata_profile_list + .set_items(vec!["Standard".to_owned(), "Full".to_owned()]); + edit_artist + .monitor_list + .set_items(Vec::from_iter(NewItemMonitorType::iter())); + app.data.lidarr_data.edit_artist_modal = Some(edit_artist); + app.data.lidarr_data.artists.set_items(vec![Artist { + monitored: false, + ..Artist::default() + }]); + app.data.lidarr_data.quality_profile_map = BiMap::from_iter([ + (1111, "Lossless".to_owned()), + (2222, "HD - 1080p".to_owned()), + ]); + app.data.lidarr_data.metadata_profile_map = + BiMap::from_iter([(1111, "Standard".to_owned()), (2222, "Full".to_owned())]); + let expected_edit_artist_params = EditArtistParams { + artist_id: 0, + monitored: Some(false), + monitor_new_items: Some(NewItemMonitorType::All), + quality_profile_id: Some(1111), + metadata_profile_id: Some(1111), + root_folder_path: Some("/nfs/Test Path".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + ..EditArtistParams::default() + }; + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.data.lidarr_data.prompt_confirm = true; + app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); + app + .data + .lidarr_data + .selected_block + .set_index(0, EDIT_ARTIST_SELECTION_BLOCKS.len() - 1); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + None, + ) + .handle(); + + assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into()); + assert_eq!( + app.data.lidarr_data.prompt_confirm_action, + Some(LidarrEvent::EditArtist(expected_edit_artist_params)) + ); + assert_modal_absent!(app.data.lidarr_data.edit_artist_modal); + assert!(app.should_refresh); + } + + #[test] + fn test_edit_artist_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() { + let mut app = App::test_default(); + app.is_loading = true; app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); app.data.lidarr_data.prompt_confirm = true; - EditArtistHandler::new(ESC_KEY, &mut app, ActiveLidarrBlock::EditArtistPrompt, None).handle(); - - assert_navigation_popped!(&app, ActiveLidarrBlock::Artists.into()); - assert!(app.data.lidarr_data.edit_artist_modal.is_none()); - assert!(!app.data.lidarr_data.prompt_confirm); - } - - #[test] - fn test_edit_artist_select_blocks_esc() { - let mut app = App::test_default(); - app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); - app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); - app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); - app.push_navigation_stack(ActiveLidarrBlock::EditArtistSelectQualityProfile.into()); - EditArtistHandler::new( - ESC_KEY, + SUBMIT_KEY, &mut app, - ActiveLidarrBlock::EditArtistSelectQualityProfile, + ActiveLidarrBlock::EditArtistPrompt, None, ) .handle(); - assert_navigation_popped!(&app, ActiveLidarrBlock::EditArtistPrompt.into()); + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::EditArtistPrompt.into() + ); + assert_none!(app.data.lidarr_data.prompt_confirm_action); + assert!(!app.should_refresh); + } + + #[test] + fn test_edit_artist_toggle_monitored_submit() { + let current_route = Route::from(( + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + )); + let mut app = App::test_default(); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(current_route); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .handle(); + + assert_eq!(app.get_current_route(), current_route); + assert_some_eq_x!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .monitored, + true + ); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .handle(); + + assert_eq!(app.get_current_route(), current_route); + assert_some_eq_x!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .monitored, + false + ); + } + + #[rstest] + #[case(ActiveLidarrBlock::EditArtistSelectQualityProfile, 2)] + #[case(ActiveLidarrBlock::EditArtistSelectMetadataProfile, 3)] + #[case(ActiveLidarrBlock::EditArtistPathInput, 4)] + #[case(ActiveLidarrBlock::EditArtistTagsInput, 5)] + fn test_edit_artist_prompt_selected_block_submit( + #[case] selected_block: ActiveLidarrBlock, + #[case] y_index: usize, + ) { + let mut app = App::test_default(); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack( + ( + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .into(), + ); + app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); + app.data.lidarr_data.selected_block.set_index(0, y_index); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .handle(); + + assert_navigation_pushed!( + app, + (selected_block, Some(ActiveLidarrBlock::Artists)).into() + ); + assert_none!(app.data.lidarr_data.prompt_confirm_action); + + if selected_block == ActiveLidarrBlock::EditArtistPathInput + || selected_block == ActiveLidarrBlock::EditArtistTagsInput + { + assert!(app.ignore_special_keys_for_textbox_input); + } + } + + #[rstest] + fn test_edit_artist_prompt_selected_block_submit_no_op_when_not_ready( + #[values(1, 2, 3, 4)] y_index: usize, + ) { + let mut app = App::test_default(); + app.is_loading = true; + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack( + ( + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .into(), + ); + app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); + app.data.lidarr_data.selected_block.set_index(0, y_index); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .handle(); + + assert_eq!( + app.get_current_route(), + ( + ActiveLidarrBlock::EditArtistPrompt, + Some(ActiveLidarrBlock::Artists), + ) + .into() + ); + assert_none!(app.data.lidarr_data.prompt_confirm_action); + assert!(!app.ignore_special_keys_for_textbox_input); + } + + #[rstest] + fn test_edit_artist_prompt_selecting_preferences_blocks_submit( + #[values( + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + ActiveLidarrBlock::EditArtistPathInput, + ActiveLidarrBlock::EditArtistTagsInput + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default(); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.push_navigation_stack(active_lidarr_block.into()); + + EditArtistHandler::new( + SUBMIT_KEY, + &mut app, + active_lidarr_block, + Some(ActiveLidarrBlock::Artists), + ) + .handle(); + + assert_navigation_popped!(app, ActiveLidarrBlock::EditArtistPrompt.into()); + + if active_lidarr_block == ActiveLidarrBlock::EditArtistPathInput + || active_lidarr_block == ActiveLidarrBlock::EditArtistTagsInput + { + assert!(!app.ignore_special_keys_for_textbox_input); + } + } + } + + mod test_handle_esc { + use crate::assert_navigation_popped; + use crate::models::servarr_data::lidarr::modals::EditArtistModal; + use rstest::rstest; + + use super::*; + + const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; + + #[rstest] + fn test_edit_artist_input_esc( + #[values( + ActiveLidarrBlock::EditArtistTagsInput, + ActiveLidarrBlock::EditArtistPathInput + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default(); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.ignore_special_keys_for_textbox_input = true; + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.push_navigation_stack(active_lidarr_block.into()); + + EditArtistHandler::new(ESC_KEY, &mut app, active_lidarr_block, None).handle(); + + assert!(!app.ignore_special_keys_for_textbox_input); + assert_navigation_popped!(app, ActiveLidarrBlock::EditArtistPrompt.into()); + } + + #[test] + fn test_edit_artist_prompt_esc() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + + EditArtistHandler::new(ESC_KEY, &mut app, ActiveLidarrBlock::EditArtistPrompt, None).handle(); + + assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into()); + + assert_modal_absent!(app.data.lidarr_data.edit_artist_modal); + assert!(!app.data.lidarr_data.prompt_confirm); + } + + #[rstest] + fn test_edit_artist_esc( + #[values( + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + ActiveLidarrBlock::EditArtistSelectMetadataProfile + )] + active_lidarr_block: ActiveLidarrBlock, + #[values(true, false)] is_ready: bool, + ) { + let mut app = App::test_default(); + app.is_loading = is_ready; + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(active_lidarr_block.into()); + + EditArtistHandler::new(ESC_KEY, &mut app, active_lidarr_block, None).handle(); + + assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into()); + } + } + + mod test_handle_key_char { + use super::*; + use crate::{ + assert_navigation_popped, + models::{ + BlockSelectionState, + servarr_data::lidarr::{ + lidarr_data::EDIT_ARTIST_SELECTION_BLOCKS, modals::EditArtistModal, + }, + }, + }; + use pretty_assertions::assert_eq; + + #[test] + fn test_edit_artist_path_input_backspace() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + path: "Test".into(), + ..EditArtistModal::default() + }); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.backspace.key, + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .text, + "Tes" + ); + } + + #[test] + fn test_edit_artist_tags_input_backspace() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + tags: "Test".into(), + ..EditArtistModal::default() + }); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.backspace.key, + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .tags + .text, + "Tes" + ); + } + + #[test] + fn test_edit_artist_path_input_char_key() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + + EditArtistHandler::new( + Key::Char('a'), + &mut app, + ActiveLidarrBlock::EditArtistPathInput, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .path + .text, + "a" + ); + } + + #[test] + fn test_edit_artist_tags_input_char_key() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + + EditArtistHandler::new( + Key::Char('a'), + &mut app, + ActiveLidarrBlock::EditArtistTagsInput, + None, + ) + .handle(); + + assert_str_eq!( + app + .data + .lidarr_data + .edit_artist_modal + .as_ref() + .unwrap() + .tags + .text, + "a" + ); + } + + #[test] + fn test_edit_artist_confirm_prompt_prompt_confirm() { + let mut app = App::test_default(); + let mut edit_artist = EditArtistModal { + tags: "usenet, testing".to_owned().into(), + path: "/nfs/Test Path".to_owned().into(), + monitored: Some(false), + ..EditArtistModal::default() + }; + edit_artist + .quality_profile_list + .set_items(vec!["Lossless".to_owned(), "HD - 1080p".to_owned()]); + edit_artist + .metadata_profile_list + .set_items(vec!["Standard".to_owned(), "Full".to_owned()]); + edit_artist + .monitor_list + .set_items(Vec::from_iter(NewItemMonitorType::iter())); + app.data.lidarr_data.edit_artist_modal = Some(edit_artist); + app.data.lidarr_data.artists.set_items(vec![Artist { + monitored: false, + ..Artist::default() + }]); + app.data.lidarr_data.quality_profile_map = BiMap::from_iter([ + (1111, "Lossless".to_owned()), + (2222, "HD - 1080p".to_owned()), + ]); + app.data.lidarr_data.metadata_profile_map = + BiMap::from_iter([(1111, "Standard".to_owned()), (2222, "Full".to_owned())]); + let expected_edit_artist_params = EditArtistParams { + artist_id: 0, + monitored: Some(false), + monitor_new_items: Some(NewItemMonitorType::All), + quality_profile_id: Some(1111), + metadata_profile_id: Some(1111), + root_folder_path: Some("/nfs/Test Path".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + ..EditArtistParams::default() + }; + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); + app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); + app + .data + .lidarr_data + .selected_block + .set_index(0, EDIT_ARTIST_SELECTION_BLOCKS.len() - 1); + + EditArtistHandler::new( + DEFAULT_KEYBINDINGS.confirm.key, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + None, + ) + .handle(); + + assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into()); + assert_eq!( + app.data.lidarr_data.prompt_confirm_action, + Some(LidarrEvent::EditArtist(expected_edit_artist_params)) + ); + assert_modal_absent!(app.data.lidarr_data.edit_artist_modal); + assert!(app.should_refresh); } } #[test] fn test_edit_artist_handler_accepts() { - let mut edit_artist_handler_blocks = Vec::new(); - for block in ActiveLidarrBlock::iter() { - if EditArtistHandler::accepts(block) { - edit_artist_handler_blocks.push(block); + ActiveLidarrBlock::iter().for_each(|active_lidarr_block| { + if EDIT_ARTIST_BLOCKS.contains(&active_lidarr_block) { + assert!(EditArtistHandler::accepts(active_lidarr_block)); + } else { + assert!(!EditArtistHandler::accepts(active_lidarr_block)); } - } + }); + } - assert_eq!(edit_artist_handler_blocks, EDIT_ARTIST_BLOCKS.to_vec()); + #[rstest] + fn test_edit_artist_handler_ignore_special_keys( + #[values(true, false)] ignore_special_keys_for_textbox_input: bool, + ) { + let mut app = App::test_default(); + app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input; + let handler = EditArtistHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::default(), + None, + ); + + assert_eq!( + handler.ignore_special_keys(), + ignore_special_keys_for_textbox_input + ); + } + + #[test] + fn test_build_edit_artist_params() { + let mut app = App::test_default(); + let mut edit_artist = EditArtistModal { + tags: "usenet, testing".to_owned().into(), + path: "/nfs/Test Path".to_owned().into(), + monitored: Some(false), + ..EditArtistModal::default() + }; + edit_artist + .quality_profile_list + .set_items(vec!["Lossless".to_owned(), "HD - 1080p".to_owned()]); + edit_artist + .metadata_profile_list + .set_items(vec!["Standard".to_owned(), "Full".to_owned()]); + edit_artist + .monitor_list + .set_items(Vec::from_iter(NewItemMonitorType::iter())); + app.data.lidarr_data.edit_artist_modal = Some(edit_artist); + app.data.lidarr_data.artists.set_items(vec![Artist { + monitored: false, + ..Artist::default() + }]); + app.data.lidarr_data.quality_profile_map = BiMap::from_iter([ + (1111, "Lossless".to_owned()), + (2222, "HD - 1080p".to_owned()), + ]); + app.data.lidarr_data.metadata_profile_map = + BiMap::from_iter([(1111, "Standard".to_owned()), (2222, "Full".to_owned())]); + let expected_edit_artist_params = EditArtistParams { + artist_id: 0, + monitored: Some(false), + monitor_new_items: Some(NewItemMonitorType::All), + quality_profile_id: Some(1111), + metadata_profile_id: Some(1111), + root_folder_path: Some("/nfs/Test Path".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + ..EditArtistParams::default() + }; + + let edit_artist_params = EditArtistHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::EditArtistPrompt, + None, + ) + .build_edit_artist_params(); + + assert_eq!(edit_artist_params, expected_edit_artist_params); + assert_modal_absent!(app.data.lidarr_data.edit_artist_modal); } #[test] fn test_edit_artist_handler_is_not_ready_when_loading() { let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); app.is_loading = true; - app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); let handler = EditArtistHandler::new( - Key::Esc, + DEFAULT_KEYBINDINGS.esc.key, &mut app, ActiveLidarrBlock::EditArtistPrompt, None, @@ -186,10 +1391,11 @@ mod tests { #[test] fn test_edit_artist_handler_is_not_ready_when_edit_artist_modal_is_none() { let mut app = App::test_default(); - app.data.lidarr_data.edit_artist_modal = None; + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.is_loading = false; let handler = EditArtistHandler::new( - Key::Esc, + DEFAULT_KEYBINDINGS.esc.key, &mut app, ActiveLidarrBlock::EditArtistPrompt, None, @@ -199,12 +1405,14 @@ mod tests { } #[test] - fn test_edit_artist_handler_is_ready_when_not_loading_and_modal_is_some() { + fn test_edit_artist_handler_is_ready_when_edit_artist_modal_is_some() { let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.is_loading = false; app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); let handler = EditArtistHandler::new( - Key::Esc, + DEFAULT_KEYBINDINGS.esc.key, &mut app, ActiveLidarrBlock::EditArtistPrompt, None, diff --git a/src/handlers/lidarr_handlers/library/library_handler_tests.rs b/src/handlers/lidarr_handlers/library/library_handler_tests.rs index 4a7d94e..9801a8d 100644 --- a/src/handlers/lidarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/lidarr_handlers/library/library_handler_tests.rs @@ -3,6 +3,7 @@ mod tests { use std::cmp::Ordering; use pretty_assertions::{assert_eq, assert_str_eq}; + use rstest::rstest; use serde_json::Number; use strum::IntoEnumIterator; @@ -11,9 +12,15 @@ mod tests { use crate::handlers::KeyEventHandler; use crate::handlers::lidarr_handlers::library::{LibraryHandler, artists_sorting_options}; use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus}; - use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS}; + use crate::models::servarr_data::lidarr::lidarr_data::{ + ActiveLidarrBlock, DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, + LIBRARY_BLOCKS, + }; + use crate::models::servarr_data::lidarr::modals::EditArtistModal; use crate::network::lidarr_network::LidarrEvent; - use crate::{assert_modal_absent, assert_navigation_popped, assert_navigation_pushed}; + use crate::{ + assert_modal_absent, assert_modal_present, assert_navigation_popped, assert_navigation_pushed, + }; #[test] fn test_library_handler_accepts() { @@ -22,7 +29,7 @@ mod tests { library_handler_blocks.extend(DELETE_ARTIST_BLOCKS); library_handler_blocks.extend(EDIT_ARTIST_BLOCKS); - ActiveLidarrBlock::iter().for_each(|lidarr_block| { + ActiveLidarrBlock::iter().for_each(|lidarr_block| { if library_handler_blocks.contains(&lidarr_block) { assert!(LibraryHandler::accepts(lidarr_block)); } else { @@ -494,4 +501,134 @@ mod tests { }, ] } + + #[test] + fn test_delegates_delete_artist_blocks_to_delete_artist_handler() { + let mut app = App::test_default(); + app + .data + .lidarr_data + .artists + .set_items(vec![Artist::default()]); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(ActiveLidarrBlock::DeleteArtistPrompt.into()); + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::DeleteArtistPrompt, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into()); + } + + #[rstest] + fn test_delegates_edit_artist_blocks_to_edit_artist_handler( + #[values( + ActiveLidarrBlock::EditArtistPrompt, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + ActiveLidarrBlock::EditArtistTagsInput, + ActiveLidarrBlock::EditArtistPathInput, + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default(); + app + .data + .lidarr_data + .artists + .set_items(vec![Artist::default()]); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(active_lidarr_block.into()); + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + active_lidarr_block, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into()); + } + + #[test] + fn test_edit_key() { + let mut app = App::test_default(); + app + .data + .lidarr_data + .artists + .set_items(vec![Artist::default()]); + app.data.lidarr_data.quality_profile_map = + bimap::BiMap::from_iter([(0i64, "Default Quality".to_owned())]); + app.data.lidarr_data.metadata_profile_map = + bimap::BiMap::from_iter([(0i64, "Default Metadata".to_owned())]); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.edit.key, + &mut app, + ActiveLidarrBlock::Artists, + None, + ) + .handle(); + + assert_navigation_pushed!(app, ActiveLidarrBlock::EditArtistPrompt.into()); + assert_modal_present!(app.data.lidarr_data.edit_artist_modal); + assert_eq!( + app.data.lidarr_data.selected_block.blocks, + EDIT_ARTIST_SELECTION_BLOCKS + ); + } + + #[test] + fn test_edit_key_no_op_when_not_ready() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app + .data + .lidarr_data + .artists + .set_items(vec![Artist::default()]); + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.edit.key, + &mut app, + ActiveLidarrBlock::Artists, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into()); + assert_modal_absent!(app.data.lidarr_data.edit_artist_modal); + } + + #[test] + fn test_refresh_key() { + let mut app = App::test_default(); + app + .data + .lidarr_data + .artists + .set_items(vec![Artist::default()]); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + + LibraryHandler::new( + DEFAULT_KEYBINDINGS.refresh.key, + &mut app, + ActiveLidarrBlock::Artists, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into()); + assert!(app.should_refresh); + } } diff --git a/src/handlers/lidarr_handlers/library/mod.rs b/src/handlers/lidarr_handlers/library/mod.rs index 114442d..fdbf9c2 100644 --- a/src/handlers/lidarr_handlers/library/mod.rs +++ b/src/handlers/lidarr_handlers/library/mod.rs @@ -10,7 +10,6 @@ use crate::{ ActiveLidarrBlock, DELETE_ARTIST_SELECTION_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, LIBRARY_BLOCKS, }, - servarr_data::lidarr::modals::EditArtistModal, stateful_table::SortOption, }, network::lidarr_network::LidarrEvent, @@ -22,9 +21,9 @@ use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; mod delete_artist_handler; mod edit_artist_handler; +use crate::models::Route; pub(in crate::handlers::lidarr_handlers) use delete_artist_handler::DeleteArtistHandler; pub(in crate::handlers::lidarr_handlers) use edit_artist_handler::EditArtistHandler; -use crate::models::Route; #[cfg(test)] #[path = "library_handler_tests.rs"] @@ -66,7 +65,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for LibraryHandler<'a, ' .handle(); } _ if EditArtistHandler::accepts(self.active_lidarr_block) => { - EditArtistHandler::new(self.key, self.app, self.active_lidarr_block, self.context).handle(); + EditArtistHandler::new(self.key, self.app, self.active_lidarr_block, self.context) + .handle(); } _ => self.handle_key_event(), } @@ -168,8 +168,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for LibraryHandler<'a, ' .pop_and_push_navigation_stack(self.active_lidarr_block.into()); } _ if matches_key!(edit, key) => { - self.app.data.lidarr_data.edit_artist_modal = - Some((&self.app.data.lidarr_data).into()); + self.app.data.lidarr_data.edit_artist_modal = Some((&self.app.data.lidarr_data).into()); self .app .push_navigation_stack(ActiveLidarrBlock::EditArtistPrompt.into()); diff --git a/src/handlers/lidarr_handlers/lidarr_handler_tests.rs b/src/handlers/lidarr_handlers/lidarr_handler_tests.rs index c180d35..484d367 100644 --- a/src/handlers/lidarr_handlers/lidarr_handler_tests.rs +++ b/src/handlers/lidarr_handlers/lidarr_handler_tests.rs @@ -1,12 +1,15 @@ #[cfg(test)] mod tests { - use rstest::rstest; - use strum::IntoEnumIterator; use crate::app::App; use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::handlers::KeyEventHandler; use crate::handlers::lidarr_handlers::LidarrHandler; + use crate::models::lidarr_models::Artist; use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock; + use crate::models::servarr_data::lidarr::modals::EditArtistModal; + use pretty_assertions::assert_eq; + use rstest::rstest; + use strum::IntoEnumIterator; #[rstest] fn test_lidarr_handler_ignore_special_keys( @@ -48,4 +51,45 @@ mod tests { assert!(LidarrHandler::accepts(lidarr_block)); } } + + #[rstest] + fn test_delegates_library_blocks_to_library_handler( + #[values( + ActiveLidarrBlock::Artists, + ActiveLidarrBlock::ArtistsSortPrompt, + ActiveLidarrBlock::FilterArtists, + ActiveLidarrBlock::FilterArtistsError, + ActiveLidarrBlock::SearchArtists, + ActiveLidarrBlock::SearchArtistsError, + ActiveLidarrBlock::UpdateAllArtistsPrompt, + ActiveLidarrBlock::DeleteArtistPrompt, + ActiveLidarrBlock::EditArtistPrompt, + ActiveLidarrBlock::EditArtistPathInput, + ActiveLidarrBlock::EditArtistSelectMetadataProfile, + ActiveLidarrBlock::EditArtistSelectMonitorNewItems, + ActiveLidarrBlock::EditArtistSelectQualityProfile, + ActiveLidarrBlock::EditArtistTagsInput + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default(); + app + .data + .lidarr_data + .artists + .set_items(vec![Artist::default()]); + app.data.lidarr_data.edit_artist_modal = Some(EditArtistModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::Artists.into()); + app.push_navigation_stack(active_lidarr_block.into()); + + LidarrHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + active_lidarr_block, + None, + ) + .handle(); + + assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into()); + } } diff --git a/src/handlers/lidarr_handlers/mod.rs b/src/handlers/lidarr_handlers/mod.rs index 16ff15b..04c7499 100644 --- a/src/handlers/lidarr_handlers/mod.rs +++ b/src/handlers/lidarr_handlers/mod.rs @@ -1,10 +1,10 @@ use library::LibraryHandler; +use super::KeyEventHandler; +use crate::models::Route; use crate::{ app::App, event::Key, matches_key, models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock, }; -use crate::models::Route; -use super::KeyEventHandler; mod library; diff --git a/src/handlers/radarr_handlers/blocklist/mod.rs b/src/handlers/radarr_handlers/blocklist/mod.rs index 44dcbbb..3199c38 100644 --- a/src/handlers/radarr_handlers/blocklist/mod.rs +++ b/src/handlers/radarr_handlers/blocklist/mod.rs @@ -4,8 +4,8 @@ use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; use crate::matches_key; -use crate::models::radarr_models::BlocklistItem; use crate::models::Route; +use crate::models::radarr_models::BlocklistItem; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS}; use crate::models::stateful_table::SortOption; use crate::network::radarr_network::RadarrEvent; diff --git a/src/handlers/radarr_handlers/collections/collection_details_handler.rs b/src/handlers/radarr_handlers/collections/collection_details_handler.rs index 5fb64a2..92ca215 100644 --- a/src/handlers/radarr_handlers/collections/collection_details_handler.rs +++ b/src/handlers/radarr_handlers/collections/collection_details_handler.rs @@ -3,12 +3,12 @@ use crate::event::Key; use crate::handlers::KeyEventHandler; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::matches_key; -use crate::models::{BlockSelectionState, Route}; use crate::models::servarr_data::radarr::radarr_data::{ ADD_MOVIE_SELECTION_BLOCKS, ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; use crate::models::stateful_table::StatefulTable; +use crate::models::{BlockSelectionState, Route}; #[cfg(test)] #[path = "collection_details_handler_tests.rs"] diff --git a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs index 1f38ce5..fe34986 100644 --- a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs +++ b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; -use crate::models::{Route, Scrollable}; use crate::models::radarr_models::EditCollectionParams; use crate::models::servarr_data::radarr::modals::EditCollectionModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS}; +use crate::models::{Route, Scrollable}; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; diff --git a/src/handlers/radarr_handlers/collections/mod.rs b/src/handlers/radarr_handlers/collections/mod.rs index bcc2370..4e2e32a 100644 --- a/src/handlers/radarr_handlers/collections/mod.rs +++ b/src/handlers/radarr_handlers/collections/mod.rs @@ -6,12 +6,12 @@ use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; use crate::matches_key; -use crate::models::{BlockSelectionState, Route}; use crate::models::radarr_models::Collection; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTIONS_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; use crate::models::stateful_table::SortOption; +use crate::models::{BlockSelectionState, Route}; use crate::network::radarr_network::RadarrEvent; mod collection_details_handler; diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs index 1c224c3..c22dad1 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs @@ -1,6 +1,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Route; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::servarr_models::EditIndexerParams; @@ -8,7 +9,6 @@ use crate::network::radarr_network::RadarrEvent; use crate::{ handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, }; -use crate::models::Route; #[cfg(test)] #[path = "edit_indexer_handler_tests.rs"] diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs index f237f97..9145529 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -1,6 +1,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Route; use crate::models::radarr_models::IndexerSettings; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, @@ -9,7 +10,6 @@ use crate::network::radarr_network::RadarrEvent; use crate::{ handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, }; -use crate::models::Route; #[cfg(test)] #[path = "edit_indexer_settings_handler_tests.rs"] diff --git a/src/handlers/radarr_handlers/indexers/mod.rs b/src/handlers/radarr_handlers/indexers/mod.rs index c37d9f6..72b99e8 100644 --- a/src/handlers/radarr_handlers/indexers/mod.rs +++ b/src/handlers/radarr_handlers/indexers/mod.rs @@ -7,11 +7,11 @@ use crate::handlers::radarr_handlers::indexers::test_all_indexers_handler::TestA use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; use crate::matches_key; -use crate::models::{BlockSelectionState, Route}; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, }; +use crate::models::{BlockSelectionState, Route}; use crate::network::radarr_network::RadarrEvent; mod edit_indexer_handler; diff --git a/src/handlers/radarr_handlers/library/delete_movie_handler.rs b/src/handlers/radarr_handlers/library/delete_movie_handler.rs index ab25e4c..c3817c2 100644 --- a/src/handlers/radarr_handlers/library/delete_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/delete_movie_handler.rs @@ -2,8 +2,8 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; -use crate::models::radarr_models::DeleteMovieParams; use crate::models::Route; +use crate::models::radarr_models::DeleteMovieParams; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; use crate::network::radarr_network::RadarrEvent; diff --git a/src/handlers/radarr_handlers/library/edit_movie_handler.rs b/src/handlers/radarr_handlers/library/edit_movie_handler.rs index db5e4b7..593f08d 100644 --- a/src/handlers/radarr_handlers/library/edit_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/edit_movie_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; -use crate::models::{Route, Scrollable}; use crate::models::radarr_models::EditMovieParams; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; +use crate::models::{Route, Scrollable}; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; diff --git a/src/handlers/radarr_handlers/mod.rs b/src/handlers/radarr_handlers/mod.rs index a785c41..282ce3b 100644 --- a/src/handlers/radarr_handlers/mod.rs +++ b/src/handlers/radarr_handlers/mod.rs @@ -6,9 +6,9 @@ use crate::handlers::radarr_handlers::indexers::IndexersHandler; use crate::handlers::radarr_handlers::library::LibraryHandler; use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler; use crate::handlers::radarr_handlers::system::SystemHandler; +use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::{App, Key, matches_key}; -use crate::models::Route; mod blocklist; mod collections; diff --git a/src/handlers/radarr_handlers/root_folders/mod.rs b/src/handlers/radarr_handlers/root_folders/mod.rs index 27a3bd4..eadd21d 100644 --- a/src/handlers/radarr_handlers/root_folders/mod.rs +++ b/src/handlers/radarr_handlers/root_folders/mod.rs @@ -3,9 +3,9 @@ use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; -use crate::models::{HorizontallyScrollableText, Route}; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::servarr_models::AddRootFolderBody; +use crate::models::{HorizontallyScrollableText, Route}; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; diff --git a/src/handlers/radarr_handlers/system/mod.rs b/src/handlers/radarr_handlers/system/mod.rs index bf3cc56..8bc1778 100644 --- a/src/handlers/radarr_handlers/system/mod.rs +++ b/src/handlers/radarr_handlers/system/mod.rs @@ -4,8 +4,8 @@ use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::handlers::{KeyEventHandler, handle_clear_errors}; use crate::matches_key; -use crate::models::{Route, Scrollable}; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; +use crate::models::{Route, Scrollable}; mod system_details_handler; diff --git a/src/handlers/radarr_handlers/system/system_details_handler.rs b/src/handlers/radarr_handlers/system/system_details_handler.rs index 60db4c7..77b553c 100644 --- a/src/handlers/radarr_handlers/system/system_details_handler.rs +++ b/src/handlers/radarr_handlers/system/system_details_handler.rs @@ -2,10 +2,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; -use crate::models::{Route, Scrollable}; use crate::models::radarr_models::RadarrTaskName; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; use crate::models::stateful_list::StatefulList; +use crate::models::{Route, Scrollable}; use crate::network::radarr_network::RadarrEvent; #[cfg(test)] diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs index c6613aa..4e2d3c9 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs @@ -1,6 +1,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Route; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::servarr_models::EditIndexerParams; @@ -8,7 +9,6 @@ use crate::network::sonarr_network::SonarrEvent; use crate::{ handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, }; -use crate::models::Route; #[cfg(test)] #[path = "edit_indexer_handler_tests.rs"] diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs index 22d0ea8..e2185ff 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -1,13 +1,13 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS, }; use crate::models::sonarr_models::IndexerSettings; use crate::network::sonarr_network::SonarrEvent; use crate::{handle_prompt_left_right_keys, matches_key}; -use crate::models::Route; #[cfg(test)] #[path = "edit_indexer_settings_handler_tests.rs"] diff --git a/src/handlers/sonarr_handlers/indexers/mod.rs b/src/handlers/sonarr_handlers/indexers/mod.rs index 3d3cd46..cc8e852 100644 --- a/src/handlers/sonarr_handlers/indexers/mod.rs +++ b/src/handlers/sonarr_handlers/indexers/mod.rs @@ -7,11 +7,11 @@ use crate::handlers::sonarr_handlers::indexers::test_all_indexers_handler::TestA use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; use crate::matches_key; -use crate::models::{BlockSelectionState, Route}; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, }; +use crate::models::{BlockSelectionState, Route}; use crate::network::sonarr_network::SonarrEvent; mod edit_indexer_handler; diff --git a/src/handlers/sonarr_handlers/library/delete_series_handler.rs b/src/handlers/sonarr_handlers/library/delete_series_handler.rs index 6b6dac5..479545f 100644 --- a/src/handlers/sonarr_handlers/library/delete_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/delete_series_handler.rs @@ -1,3 +1,4 @@ +use crate::models::Route; use crate::models::sonarr_models::DeleteSeriesParams; use crate::network::sonarr_network::SonarrEvent; use crate::{ @@ -7,7 +8,6 @@ use crate::{ matches_key, models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS}, }; -use crate::models::Route; #[cfg(test)] #[path = "delete_series_handler_tests.rs"] diff --git a/src/handlers/sonarr_handlers/library/edit_series_handler.rs b/src/handlers/sonarr_handlers/library/edit_series_handler.rs index 7e872d8..4bd4d79 100644 --- a/src/handlers/sonarr_handlers/library/edit_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/edit_series_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; -use crate::models::{Route, Scrollable}; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS}; use crate::models::sonarr_models::EditSeriesParams; +use crate::models::{Route, Scrollable}; use crate::network::sonarr_network::SonarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; diff --git a/src/handlers/sonarr_handlers/library/season_details_handler.rs b/src/handlers/sonarr_handlers/library/season_details_handler.rs index 2d4b2e1..903351d 100644 --- a/src/handlers/sonarr_handlers/library/season_details_handler.rs +++ b/src/handlers/sonarr_handlers/library/season_details_handler.rs @@ -4,6 +4,7 @@ use crate::handlers::sonarr_handlers::history::history_sorting_options; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SEASON_DETAILS_BLOCKS}; use crate::models::servarr_models::Language; use crate::models::sonarr_models::{ @@ -12,7 +13,6 @@ use crate::models::sonarr_models::{ use crate::models::stateful_table::SortOption; use crate::network::sonarr_network::SonarrEvent; use serde_json::Number; -use crate::models::Route; #[cfg(test)] #[path = "season_details_handler_tests.rs"] diff --git a/src/handlers/sonarr_handlers/library/series_details_handler.rs b/src/handlers/sonarr_handlers/library/series_details_handler.rs index 478ef3f..c089bff 100644 --- a/src/handlers/sonarr_handlers/library/series_details_handler.rs +++ b/src/handlers/sonarr_handlers/library/series_details_handler.rs @@ -4,11 +4,11 @@ use crate::handlers::sonarr_handlers::history::history_sorting_options; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; -use crate::models::{BlockSelectionState, Route}; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EDIT_SERIES_SELECTION_BLOCKS, SERIES_DETAILS_BLOCKS, }; use crate::models::sonarr_models::{Season, SonarrHistoryItem}; +use crate::models::{BlockSelectionState, Route}; use crate::network::sonarr_network::SonarrEvent; #[cfg(test)] diff --git a/src/handlers/sonarr_handlers/mod.rs b/src/handlers/sonarr_handlers/mod.rs index e33eecb..ebd139d 100644 --- a/src/handlers/sonarr_handlers/mod.rs +++ b/src/handlers/sonarr_handlers/mod.rs @@ -6,11 +6,11 @@ use library::LibraryHandler; use root_folders::RootFoldersHandler; use system::SystemHandler; +use super::KeyEventHandler; +use crate::models::Route; use crate::{ app::App, event::Key, matches_key, models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock, }; -use crate::models::Route; -use super::KeyEventHandler; mod blocklist; mod downloads; diff --git a/src/handlers/sonarr_handlers/root_folders/mod.rs b/src/handlers/sonarr_handlers/root_folders/mod.rs index 9d6a3ee..964060c 100644 --- a/src/handlers/sonarr_handlers/root_folders/mod.rs +++ b/src/handlers/sonarr_handlers/root_folders/mod.rs @@ -3,9 +3,9 @@ use crate::event::Key; use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; -use crate::models::{HorizontallyScrollableText, Route}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::servarr_models::AddRootFolderBody; +use crate::models::{HorizontallyScrollableText, Route}; use crate::network::sonarr_network::SonarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; diff --git a/src/handlers/sonarr_handlers/system/mod.rs b/src/handlers/sonarr_handlers/system/mod.rs index 34c0fff..0734350 100644 --- a/src/handlers/sonarr_handlers/system/mod.rs +++ b/src/handlers/sonarr_handlers/system/mod.rs @@ -4,8 +4,8 @@ use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::sonarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::handlers::{KeyEventHandler, handle_clear_errors}; use crate::matches_key; -use crate::models::{Route, Scrollable}; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; +use crate::models::{Route, Scrollable}; mod system_details_handler; diff --git a/src/handlers/sonarr_handlers/system/system_details_handler.rs b/src/handlers/sonarr_handlers/system/system_details_handler.rs index 3b79e0d..63495fd 100644 --- a/src/handlers/sonarr_handlers/system/system_details_handler.rs +++ b/src/handlers/sonarr_handlers/system/system_details_handler.rs @@ -2,10 +2,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; -use crate::models::{Route, Scrollable}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS}; use crate::models::sonarr_models::SonarrTaskName; use crate::models::stateful_list::StatefulList; +use crate::models::{Route, Scrollable}; use crate::network::sonarr_network::SonarrEvent; #[cfg(test)] diff --git a/src/handlers/table_handler_tests.rs b/src/handlers/table_handler_tests.rs index fb0585d..0e3ff10 100644 --- a/src/handlers/table_handler_tests.rs +++ b/src/handlers/table_handler_tests.rs @@ -9,12 +9,12 @@ mod tests { use crate::handlers::KeyEventHandler; use crate::handlers::table_handler::TableHandlingConfig; use crate::handlers::table_handler::handle_table; + use crate::models::Route; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_models::Language; use crate::models::stateful_table::SortOption; use rstest::rstest; - use crate::models::Route; struct TableHandlerUnit<'a, 'b> { key: Key, diff --git a/src/models/servarr_data/lidarr/lidarr_data.rs b/src/models/servarr_data/lidarr/lidarr_data.rs index bc54f32..240f68d 100644 --- a/src/models/servarr_data/lidarr/lidarr_data.rs +++ b/src/models/servarr_data/lidarr/lidarr_data.rs @@ -1,5 +1,6 @@ use serde_json::Number; +use super::modals::EditArtistModal; use crate::app::lidarr::lidarr_context_clues::ARTISTS_CONTEXT_CLUES; use crate::models::{ BlockSelectionState, Route, TabRoute, TabState, @@ -10,16 +11,17 @@ use crate::models::{ use crate::network::lidarr_network::LidarrEvent; use bimap::BiMap; use chrono::{DateTime, Utc}; -use strum::{EnumIter}; -use super::modals::EditArtistModal; +use strum::EnumIter; #[cfg(test)] use { - strum::{Display, EnumString, IntoEnumIterator}, crate::models::lidarr_models::NewItemMonitorType, crate::models::stateful_table::SortOption, crate::network::lidarr_network::lidarr_network_test_utils::test_utils::quality_profile_map, + crate::network::lidarr_network::lidarr_network_test_utils::test_utils::{ + download_record, metadata_profile, metadata_profile_map, quality_profile, root_folder, tags_map, + }, crate::network::servarr_test_utils::diskspace, - crate::network::lidarr_network::lidarr_network_test_utils::test_utils::{download_record, metadata_profile, metadata_profile_map, quality_profile, root_folder, tags_map}, + strum::{Display, EnumString, IntoEnumIterator}, }; #[cfg(test)] @@ -114,9 +116,15 @@ impl LidarrData<'_> { tags: "alex".into(), ..EditArtistModal::default() }; - edit_artist_modal.monitor_list.set_items(NewItemMonitorType::iter().collect()); - edit_artist_modal.quality_profile_list.set_items(vec![quality_profile().name]); - edit_artist_modal.metadata_profile_list.set_items(vec![metadata_profile().name]); + edit_artist_modal + .monitor_list + .set_items(NewItemMonitorType::iter().collect()); + edit_artist_modal + .quality_profile_list + .set_items(vec![quality_profile().name]); + edit_artist_modal + .metadata_profile_list + .set_items(vec![metadata_profile().name]); let mut lidarr_data = LidarrData { delete_artist_files: true, @@ -134,12 +142,8 @@ impl LidarrData<'_> { }]); lidarr_data.artists.search = Some("artist search".into()); lidarr_data.artists.filter = Some("artist filter".into()); - lidarr_data - .downloads - .set_items(vec![download_record()]); - lidarr_data - .root_folders - .set_items(vec![root_folder()]); + lidarr_data.downloads.set_items(vec![download_record()]); + lidarr_data.root_folders.set_items(vec![root_folder()]); lidarr_data.version = "1.0.0".to_owned(); lidarr_data diff --git a/src/models/servarr_data/lidarr/lidarr_data_tests.rs b/src/models/servarr_data/lidarr/lidarr_data_tests.rs index 182bf48..ceb3417 100644 --- a/src/models/servarr_data/lidarr/lidarr_data_tests.rs +++ b/src/models/servarr_data/lidarr/lidarr_data_tests.rs @@ -1,12 +1,15 @@ #[cfg(test)] mod tests { - use bimap::BiMap; use crate::app::lidarr::lidarr_context_clues::ARTISTS_CONTEXT_CLUES; - use crate::models::servarr_data::lidarr::lidarr_data::{DELETE_ARTIST_BLOCKS, DELETE_ARTIST_SELECTION_BLOCKS, EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS}; + use crate::models::servarr_data::lidarr::lidarr_data::{ + DELETE_ARTIST_BLOCKS, DELETE_ARTIST_SELECTION_BLOCKS, EDIT_ARTIST_BLOCKS, + EDIT_ARTIST_SELECTION_BLOCKS, + }; use crate::models::{ BlockSelectionState, Route, servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, LIBRARY_BLOCKS, LidarrData}, }; + use bimap::BiMap; use chrono::{DateTime, Utc}; use pretty_assertions::{assert_eq, assert_str_eq}; use serde_json::Number; @@ -52,7 +55,10 @@ mod tests { ..LidarrData::default() }; - assert_str_eq!(lidarr_data.tag_ids_to_display(&[Number::from(1), Number::from(2)]), "test 1, test 2"); + assert_str_eq!( + lidarr_data.tag_ids_to_display(&[Number::from(1), Number::from(2)]), + "test 1, test 2" + ); } #[test] @@ -65,9 +71,16 @@ mod tests { quality_profile_map, ..LidarrData::default() }; - let expected_quality_profile_vec = vec!["test 1".to_owned(), "test 2".to_owned(), "test 3".to_owned()]; + let expected_quality_profile_vec = vec![ + "test 1".to_owned(), + "test 2".to_owned(), + "test 3".to_owned(), + ]; - assert_iter_eq!(lidarr_data.sorted_quality_profile_names(), expected_quality_profile_vec); + assert_iter_eq!( + lidarr_data.sorted_quality_profile_names(), + expected_quality_profile_vec + ); } #[test] @@ -80,9 +93,16 @@ mod tests { metadata_profile_map, ..LidarrData::default() }; - let expected_metadata_profile_vec = vec!["test 1".to_owned(), "test 2".to_owned(), "test 3".to_owned()]; + let expected_metadata_profile_vec = vec![ + "test 1".to_owned(), + "test 2".to_owned(), + "test 3".to_owned(), + ]; - assert_iter_eq!(lidarr_data.sorted_metadata_profile_names(), expected_metadata_profile_vec); + assert_iter_eq!( + lidarr_data.sorted_metadata_profile_names(), + expected_metadata_profile_vec + ); } #[test] @@ -176,13 +196,34 @@ mod tests { fn test_edit_artist_selection_blocks_ordering() { let mut edit_artist_block_iter = EDIT_ARTIST_SELECTION_BLOCKS.iter(); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistToggleMonitored]); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistSelectMonitorNewItems]); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistSelectQualityProfile]); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistSelectMetadataProfile]); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistPathInput]); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistTagsInput]); - assert_eq!(edit_artist_block_iter.next().unwrap(), &[ActiveLidarrBlock::EditArtistConfirmPrompt]); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistToggleMonitored] + ); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistSelectMonitorNewItems] + ); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistSelectQualityProfile] + ); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistSelectMetadataProfile] + ); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistPathInput] + ); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistTagsInput] + ); + assert_eq!( + edit_artist_block_iter.next().unwrap(), + &[ActiveLidarrBlock::EditArtistConfirmPrompt] + ); assert_none!(edit_artist_block_iter.next()); } } diff --git a/src/models/servarr_data/lidarr/modals_tests.rs b/src/models/servarr_data/lidarr/modals_tests.rs index 0889091..ae8b512 100644 --- a/src/models/servarr_data/lidarr/modals_tests.rs +++ b/src/models/servarr_data/lidarr/modals_tests.rs @@ -10,10 +10,16 @@ mod tests { #[test] fn test_edit_artist_modal_from_lidarr_data() { let mut lidarr_data = LidarrData { - quality_profile_map: BiMap::from_iter([(1i64, "HD - 1080p".to_owned()), (2i64, "Any".to_owned())]), - metadata_profile_map: BiMap::from_iter([(1i64, "Standard".to_owned()), (2i64, "None".to_owned())]), + quality_profile_map: BiMap::from_iter([ + (1i64, "HD - 1080p".to_owned()), + (2i64, "Any".to_owned()), + ]), + metadata_profile_map: BiMap::from_iter([ + (1i64, "Standard".to_owned()), + (2i64, "None".to_owned()), + ]), tags_map: BiMap::from_iter([(1i64, "usenet".to_owned())]), - ..LidarrData::default() + ..LidarrData::default() }; let artist = Artist { id: 1, diff --git a/src/models/servarr_data/radarr/radarr_data_tests.rs b/src/models/servarr_data/radarr/radarr_data_tests.rs index 15c8b6d..3ddde2e 100644 --- a/src/models/servarr_data/radarr/radarr_data_tests.rs +++ b/src/models/servarr_data/radarr/radarr_data_tests.rs @@ -1,10 +1,6 @@ #[cfg(test)] mod tests { mod radarr_data_tests { - use bimap::BiMap; - use chrono::{DateTime, Utc}; - use pretty_assertions::{assert_eq, assert_str_eq}; - use serde_json::Number; use crate::app::context_clues::{ BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, @@ -13,6 +9,10 @@ mod tests { COLLECTIONS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES, MOVIE_DETAILS_CONTEXT_CLUES, }; + use bimap::BiMap; + use chrono::{DateTime, Utc}; + use pretty_assertions::{assert_eq, assert_str_eq}; + use serde_json::Number; use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils; @@ -73,7 +73,10 @@ mod tests { ..RadarrData::default() }; - assert_str_eq!(radarr_data.tag_ids_to_display(&[Number::from(1), Number::from(2)]), "test 1, test 2"); + assert_str_eq!( + radarr_data.tag_ids_to_display(&[Number::from(1), Number::from(2)]), + "test 1, test 2" + ); } #[test] @@ -86,9 +89,16 @@ mod tests { quality_profile_map, ..RadarrData::default() }; - let expected_quality_profile_vec = vec!["test 1".to_owned(), "test 2".to_owned(), "test 3".to_owned()]; + let expected_quality_profile_vec = vec![ + "test 1".to_owned(), + "test 2".to_owned(), + "test 3".to_owned(), + ]; - assert_iter_eq!(radarr_data.sorted_quality_profile_names(), expected_quality_profile_vec); + assert_iter_eq!( + radarr_data.sorted_quality_profile_names(), + expected_quality_profile_vec + ); } #[test] diff --git a/src/models/servarr_data/sonarr/sonarr_data_tests.rs b/src/models/servarr_data/sonarr/sonarr_data_tests.rs index 641a5f6..c166cfb 100644 --- a/src/models/servarr_data/sonarr/sonarr_data_tests.rs +++ b/src/models/servarr_data/sonarr/sonarr_data_tests.rs @@ -1,10 +1,6 @@ #[cfg(test)] mod tests { mod sonarr_data_tests { - use bimap::BiMap; - use chrono::{DateTime, Utc}; - use pretty_assertions::{assert_eq, assert_str_eq}; - use serde_json::Number; use crate::app::sonarr::sonarr_context_clues::SERIES_HISTORY_CONTEXT_CLUES; use crate::models::sonarr_models::{Season, SonarrHistoryItem}; use crate::models::stateful_table::StatefulTable; @@ -23,6 +19,10 @@ mod tests { servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}, }, }; + use bimap::BiMap; + use chrono::{DateTime, Utc}; + use pretty_assertions::{assert_eq, assert_str_eq}; + use serde_json::Number; #[test] fn test_from_active_sonarr_block_to_route() { @@ -89,7 +89,10 @@ mod tests { ..SonarrData::default() }; - assert_str_eq!(sonarr_data.tag_ids_to_display(&[Number::from(1), Number::from(2)]), "test 1, test 2"); + assert_str_eq!( + sonarr_data.tag_ids_to_display(&[Number::from(1), Number::from(2)]), + "test 1, test 2" + ); } #[test] @@ -102,9 +105,16 @@ mod tests { quality_profile_map, ..SonarrData::default() }; - let expected_quality_profile_vec = vec!["test 1".to_owned(), "test 2".to_owned(), "test 3".to_owned()]; + let expected_quality_profile_vec = vec![ + "test 1".to_owned(), + "test 2".to_owned(), + "test 3".to_owned(), + ]; - assert_iter_eq!(sonarr_data.sorted_quality_profile_names(), expected_quality_profile_vec); + assert_iter_eq!( + sonarr_data.sorted_quality_profile_names(), + expected_quality_profile_vec + ); } #[test] @@ -117,9 +127,16 @@ mod tests { language_profiles_map, ..SonarrData::default() }; - let expected_language_profiles_vec = vec!["test 1".to_owned(), "test 2".to_owned(), "test 3".to_owned()]; + let expected_language_profiles_vec = vec![ + "test 1".to_owned(), + "test 2".to_owned(), + "test 3".to_owned(), + ]; - assert_iter_eq!(sonarr_data.sorted_language_profile_names(), expected_language_profiles_vec); + assert_iter_eq!( + sonarr_data.sorted_language_profile_names(), + expected_language_profiles_vec + ); } #[test] diff --git a/src/network/lidarr_network/library/lidarr_library_network_tests.rs b/src/network/lidarr_network/library/lidarr_library_network_tests.rs index 6cb6c3e..ebdefaf 100644 --- a/src/network/lidarr_network/library/lidarr_library_network_tests.rs +++ b/src/network/lidarr_network/library/lidarr_library_network_tests.rs @@ -1,11 +1,16 @@ #[cfg(test)] mod tests { - use crate::models::lidarr_models::{Artist, DeleteArtistParams, LidarrSerdeable}; + use crate::models::lidarr_models::{ + Artist, DeleteArtistParams, EditArtistParams, LidarrSerdeable, NewItemMonitorType, + }; + use crate::network::NetworkResource; use crate::network::lidarr_network::LidarrEvent; use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use bimap::BiMap; use mockito::Matcher; use pretty_assertions::assert_eq; - use serde_json::json; + use serde_json::{Value, json}; + use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::ARTIST_JSON; #[tokio::test] async fn test_handle_list_artists_event() { @@ -70,36 +75,9 @@ mod tests { #[tokio::test] async fn test_handle_get_artist_details_event() { - let artist_json = json!({ - "id": 1, - "artistName": "Test Artist", - "foreignArtistId": "test-foreign-id", - "status": "continuing", - "overview": "some interesting description of the artist", - "artistType": "Person", - "disambiguation": "American pianist", - "path": "/music/test-artist", - "members": [{"name": "alex", "instrument": "piano"}], - "qualityProfileId": 1, - "metadataProfileId": 1, - "monitored": true, - "monitorNewItems": "all", - "genres": ["soundtrack"], - "tags": [1], - "added": "2023-01-01T00:00:00Z", - "ratings": { "votes": 15, "value": 8.4 }, - "statistics": { - "albumCount": 1, - "trackFileCount": 15, - "trackCount": 15, - "totalTrackCount": 15, - "sizeOnDisk": 12345, - "percentOfTracks": 99.9 - } - }); - let response: Artist = serde_json::from_value(artist_json.clone()).unwrap(); + let expected_artist: Artist = serde_json::from_str(ARTIST_JSON).unwrap(); let (mock, app, _server) = MockServarrApi::get() - .returns(artist_json) + .returns(serde_json::from_str(ARTIST_JSON).unwrap()) .path("/1") .build_for(LidarrEvent::GetArtistDetails(1)) .await; @@ -116,7 +94,7 @@ mod tests { panic!("Expected Artist"); }; - assert_eq!(artist, response); + assert_eq!(artist, expected_artist); } #[tokio::test] @@ -184,4 +162,198 @@ mod tests { mock.assert_async().await; } + + #[tokio::test] + async fn test_handle_edit_artist_event() { + let mut expected_body: Value = serde_json::from_str(ARTIST_JSON).unwrap(); + *expected_body.get_mut("monitored").unwrap() = json!(false); + *expected_body.get_mut("monitorNewItems").unwrap() = json!("none"); + *expected_body.get_mut("qualityProfileId").unwrap() = json!(1111); + *expected_body.get_mut("metadataProfileId").unwrap() = json!(2222); + *expected_body.get_mut("path").unwrap() = json!("/nfs/Test Path"); + *expected_body.get_mut("tags").unwrap() = json!([1, 2]); + let edit_artist_params = EditArtistParams { + artist_id: 1, + monitored: Some(false), + monitor_new_items: Some(NewItemMonitorType::None), + quality_profile_id: Some(1111), + metadata_profile_id: Some(2222), + root_folder_path: Some("/nfs/Test Path".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + ..EditArtistParams::default() + }; + + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(ARTIST_JSON).unwrap()) + .path("/1") + .build_for(LidarrEvent::GetArtistDetails(1)) + .await; + let async_edit_server = server + .mock( + "PUT", + format!( + "/api/v1{}/1", + LidarrEvent::EditArtist(edit_artist_params.clone()).resource() + ) + .as_str(), + ) + .with_status(202) + .match_header("X-Api-Key", "test1234") + .match_body(Matcher::Json(expected_body)) + .create_async() + .await; + app.lock().await.data.lidarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); + app.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app); + + assert!( + network + .handle_lidarr_event(LidarrEvent::EditArtist(edit_artist_params)) + .await + .is_ok() + ); + + async_details_server.assert_async().await; + async_edit_server.assert_async().await; + } + + #[tokio::test] + async fn test_handle_edit_artist_event_does_not_overwrite_tag_ids_vec_when_tag_input_string_is_none() + { + let mut expected_body: Value = serde_json::from_str(ARTIST_JSON).unwrap(); + *expected_body.get_mut("monitored").unwrap() = json!(false); + *expected_body.get_mut("monitorNewItems").unwrap() = json!("none"); + *expected_body.get_mut("qualityProfileId").unwrap() = json!(1111); + *expected_body.get_mut("metadataProfileId").unwrap() = json!(2222); + *expected_body.get_mut("path").unwrap() = json!("/nfs/Test Path"); + *expected_body.get_mut("tags").unwrap() = json!([1, 2]); + let edit_artist_params = EditArtistParams { + artist_id: 1, + monitored: Some(false), + monitor_new_items: Some(NewItemMonitorType::None), + quality_profile_id: Some(1111), + metadata_profile_id: Some(2222), + root_folder_path: Some("/nfs/Test Path".to_owned()), + tags: Some(vec![1, 2]), + ..EditArtistParams::default() + }; + + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(ARTIST_JSON).unwrap()) + .path("/1") + .build_for(LidarrEvent::GetArtistDetails(1)) + .await; + let async_edit_server = server + .mock( + "PUT", + format!( + "/api/v1{}/1", + LidarrEvent::EditArtist(edit_artist_params.clone()).resource() + ) + .as_str(), + ) + .with_status(202) + .match_header("X-Api-Key", "test1234") + .match_body(Matcher::Json(expected_body)) + .create_async() + .await; + app.lock().await.data.lidarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); + app.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app); + + assert!( + network + .handle_lidarr_event(LidarrEvent::EditArtist(edit_artist_params)) + .await + .is_ok() + ); + + async_details_server.assert_async().await; + async_edit_server.assert_async().await; + } + + #[tokio::test] + async fn test_handle_edit_artist_event_defaults_to_previous_values() { + let edit_artist_params = EditArtistParams { + artist_id: 1, + ..EditArtistParams::default() + }; + let expected_body: Value = serde_json::from_str(ARTIST_JSON).unwrap(); + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(ARTIST_JSON).unwrap()) + .path("/1") + .build_for(LidarrEvent::GetArtistDetails(1)) + .await; + let async_edit_server = server + .mock( + "PUT", + format!( + "/api/v1{}/1", + LidarrEvent::EditArtist(edit_artist_params.clone()).resource() + ) + .as_str(), + ) + .with_status(202) + .match_header("X-Api-Key", "test1234") + .match_body(Matcher::Json(expected_body)) + .create_async() + .await; + app.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app); + + assert!( + network + .handle_lidarr_event(LidarrEvent::EditArtist(edit_artist_params)) + .await + .is_ok() + ); + + async_details_server.assert_async().await; + async_edit_server.assert_async().await; + } + + #[tokio::test] + async fn test_handle_edit_artist_event_returns_empty_tags_vec_when_clear_tags_is_true() { + let mut expected_body: Value = serde_json::from_str(ARTIST_JSON).unwrap(); + *expected_body.get_mut("tags").unwrap() = json!([]); + + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(ARTIST_JSON).unwrap()) + .path("/1") + .build_for(LidarrEvent::GetArtistDetails(1)) + .await; + let edit_artist_params = EditArtistParams { + artist_id: 1, + clear_tags: true, + ..EditArtistParams::default() + }; + let async_edit_server = server + .mock( + "PUT", + format!( + "/api/v1{}/1", + LidarrEvent::EditArtist(edit_artist_params.clone()).resource() + ) + .as_str(), + ) + .with_status(202) + .match_header("X-Api-Key", "test1234") + .match_body(Matcher::Json(expected_body)) + .create_async() + .await; + app.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app); + + assert!( + network + .handle_lidarr_event(LidarrEvent::EditArtist(edit_artist_params)) + .await + .is_ok() + ); + + async_details_server.assert_async().await; + async_edit_server.assert_async().await; + } } diff --git a/src/network/lidarr_network/lidarr_network_test_utils.rs b/src/network/lidarr_network/lidarr_network_test_utils.rs index 8677e6c..4e6f9dc 100644 --- a/src/network/lidarr_network/lidarr_network_test_utils.rs +++ b/src/network/lidarr_network/lidarr_network_test_utils.rs @@ -1,132 +1,177 @@ #[cfg(test)] #[allow(dead_code)] // TODO: maybe remove? pub mod test_utils { - use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus, DownloadRecord, DownloadStatus, DownloadsResponse, Member, MetadataProfile, NewItemMonitorType, Ratings, SystemStatus}; - use crate::models::servarr_models::{QualityProfile, RootFolder, Tag}; - use crate::models::HorizontallyScrollableText; - use bimap::BiMap; - use chrono::DateTime; - use serde_json::Number; + use crate::models::HorizontallyScrollableText; + use crate::models::lidarr_models::{ + Artist, ArtistStatistics, ArtistStatus, DownloadRecord, DownloadStatus, DownloadsResponse, + EditArtistParams, Member, MetadataProfile, NewItemMonitorType, Ratings, SystemStatus, + }; + use crate::models::servarr_models::{QualityProfile, RootFolder, Tag}; + use bimap::BiMap; + use chrono::DateTime; + use serde_json::Number; - pub fn member() -> Member { - Member { - name: Some("alex".to_owned()), - instrument: Some("piano".to_owned()) - } - } + pub const ARTIST_JSON: &str = r#"{ + "id": 1, + "artistName": "Test Artist", + "foreignArtistId": "test-foreign-id", + "status": "continuing", + "overview": "some interesting description of the artist", + "artistType": "Person", + "disambiguation": "American pianist", + "path": "/music/test-artist", + "members": [{"name": "alex", "instrument": "piano"}], + "qualityProfileId": 1, + "metadataProfileId": 1, + "monitored": true, + "monitorNewItems": "all", + "genres": ["soundtrack"], + "tags": [1], + "added": "2023-01-01T00:00:00Z", + "ratings": { "votes": 15, "value": 8.4 }, + "statistics": { + "albumCount": 1, + "trackFileCount": 15, + "trackCount": 15, + "totalTrackCount": 15, + "sizeOnDisk": 12345, + "percentOfTracks": 99.9 + } + }"#; - pub fn ratings() -> Ratings { - Ratings { - votes: 15, - value: 8.4 - } - } + pub fn member() -> Member { + Member { + name: Some("alex".to_owned()), + instrument: Some("piano".to_owned()), + } + } - pub fn artist_statistics() -> ArtistStatistics { - ArtistStatistics { - album_count: 1, - track_file_count: 15, - track_count: 15, - total_track_count: 15, - size_on_disk: 12345, - percent_of_tracks: 99.9 - } - } + pub fn ratings() -> Ratings { + Ratings { + votes: 15, + value: 8.4, + } + } - pub fn artist() -> Artist { - Artist { - id: 1, - artist_name: "Alex".into(), - foreign_artist_id: "test-foreign-id".to_owned(), - status: ArtistStatus::Continuing, - overview: Some("some interesting description of the artist".to_owned()), - artist_type: Some("Person".to_owned()), - disambiguation: Some("American pianist".to_owned()), - members: Some(vec![member()]), - path: "/nfs/music/test-artist".to_owned(), - quality_profile_id: quality_profile().id, - metadata_profile_id: metadata_profile().id, - monitored: true, - monitor_new_items: NewItemMonitorType::All, - genres: vec!["soundtrack".to_owned()], - tags: vec![Number::from(tag().id)], - added: DateTime::from(DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z").unwrap()), - ratings: Some(ratings()), - statistics: Some(artist_statistics()) - } - } + pub fn artist_statistics() -> ArtistStatistics { + ArtistStatistics { + album_count: 1, + track_file_count: 15, + track_count: 15, + total_track_count: 15, + size_on_disk: 12345, + percent_of_tracks: 99.9, + } + } - pub fn quality_profile() -> QualityProfile { - QualityProfile { - id: 1, - name: "Lossless".to_owned() - } - } + pub fn artist() -> Artist { + Artist { + id: 1, + artist_name: "Alex".into(), + foreign_artist_id: "test-foreign-id".to_owned(), + status: ArtistStatus::Continuing, + overview: Some("some interesting description of the artist".to_owned()), + artist_type: Some("Person".to_owned()), + disambiguation: Some("American pianist".to_owned()), + members: Some(vec![member()]), + path: "/nfs/music/test-artist".to_owned(), + quality_profile_id: quality_profile().id, + metadata_profile_id: metadata_profile().id, + monitored: true, + monitor_new_items: NewItemMonitorType::All, + genres: vec!["soundtrack".to_owned()], + tags: vec![Number::from(tag().id)], + added: DateTime::from(DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z").unwrap()), + ratings: Some(ratings()), + statistics: Some(artist_statistics()), + } + } - pub fn quality_profile_map() -> BiMap { - let quality_profile = quality_profile(); - BiMap::from_iter(vec![(quality_profile.id, quality_profile.name)]) - } + pub fn quality_profile() -> QualityProfile { + QualityProfile { + id: 1, + name: "Lossless".to_owned(), + } + } - pub fn metadata_profile() -> MetadataProfile { - MetadataProfile { - id: 1, - name: "Standard".to_owned() - } - } + pub fn quality_profile_map() -> BiMap { + let quality_profile = quality_profile(); + BiMap::from_iter(vec![(quality_profile.id, quality_profile.name)]) + } - pub fn metadata_profile_map() -> BiMap { - let metadata_profile = metadata_profile(); - BiMap::from_iter(vec![(metadata_profile.id, metadata_profile.name)]) - } + pub fn metadata_profile() -> MetadataProfile { + MetadataProfile { + id: 1, + name: "Standard".to_owned(), + } + } - pub fn tag() -> Tag { - Tag { - id: 1, - label: "alex".to_owned() - } - } + pub fn metadata_profile_map() -> BiMap { + let metadata_profile = metadata_profile(); + BiMap::from_iter(vec![(metadata_profile.id, metadata_profile.name)]) + } - pub fn tags_map() -> BiMap { - let tag = tag(); - BiMap::from_iter(vec![(tag.id, tag.label)]) - } + pub fn tag() -> Tag { + Tag { + id: 1, + label: "alex".to_owned(), + } + } - pub fn download_record() -> DownloadRecord { - DownloadRecord { - title: "Test download title".to_owned(), - status: DownloadStatus::Downloading, - id: 1, - album_id: Some(Number::from(1i64)), - artist_id: Some(Number::from(1i64)), - size: 3543348019f64, - sizeleft: 1771674009f64, - output_path: Some(HorizontallyScrollableText::from("/nfs/music/alex/album")), - indexer: "kickass torrents".to_owned(), - download_client: Some("transmission".to_owned()) - } - } + pub fn tags_map() -> BiMap { + let tag = tag(); + BiMap::from_iter(vec![(tag.id, tag.label)]) + } - pub fn downloads_response() -> DownloadsResponse { - DownloadsResponse { - records: vec![download_record()] - } - } - - pub fn system_status() -> SystemStatus { - SystemStatus { - version: "1.0".to_owned(), - start_time: DateTime::from(DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z").unwrap()), - } - } - - pub fn root_folder() -> RootFolder { - RootFolder { - id: 1, - path: "/nfs".to_owned(), - accessible: true, - free_space: 219902325555200, - unmapped_folders: None, - } - } -} \ No newline at end of file + pub fn download_record() -> DownloadRecord { + DownloadRecord { + title: "Test download title".to_owned(), + status: DownloadStatus::Downloading, + id: 1, + album_id: Some(Number::from(1i64)), + artist_id: Some(Number::from(1i64)), + size: 3543348019f64, + sizeleft: 1771674009f64, + output_path: Some(HorizontallyScrollableText::from("/nfs/music/alex/album")), + indexer: "kickass torrents".to_owned(), + download_client: Some("transmission".to_owned()), + } + } + + pub fn downloads_response() -> DownloadsResponse { + DownloadsResponse { + records: vec![download_record()], + } + } + + pub fn system_status() -> SystemStatus { + SystemStatus { + version: "1.0".to_owned(), + start_time: DateTime::from(DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z").unwrap()), + } + } + + pub fn root_folder() -> RootFolder { + RootFolder { + id: 1, + path: "/nfs".to_owned(), + accessible: true, + free_space: 219902325555200, + unmapped_folders: None, + } + } + + pub fn edit_artist_params() -> EditArtistParams { + EditArtistParams { + artist_id: artist().id, + monitored: Some(true), + monitor_new_items: Some(NewItemMonitorType::All), + quality_profile_id: Some(quality_profile().id), + metadata_profile_id: Some(metadata_profile().id), + root_folder_path: Some("/nfs/music/test-artist".to_owned()), + tags: Some(vec![tag().id]), + tag_input_string: Some("alex".to_owned()), + clear_tags: false, + } + } +} diff --git a/src/network/lidarr_network/lidarr_network_tests.rs b/src/network/lidarr_network/lidarr_network_tests.rs index 837885f..0e487a3 100644 --- a/src/network/lidarr_network/lidarr_network_tests.rs +++ b/src/network/lidarr_network/lidarr_network_tests.rs @@ -1,12 +1,17 @@ #[cfg(test)] mod tests { + use std::sync::Arc; use crate::models::lidarr_models::{LidarrSerdeable, MetadataProfile}; use crate::models::servarr_models::{QualityProfile, Tag}; use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::{NetworkEvent, NetworkResource, lidarr_network::LidarrEvent}; + use bimap::BiMap; use pretty_assertions::{assert_eq, assert_str_eq}; use rstest::rstest; use serde_json::json; + use tokio::sync::Mutex; + use crate::app::App; + use crate::models::servarr_data::lidarr::modals::EditArtistModal; #[rstest] fn test_resource_artist( @@ -170,4 +175,91 @@ mod tests { Some(&"usenet".to_owned()) ); } + + #[tokio::test] + async fn test_handle_add_lidarr_tag_event() { + let tag_json = json!({ + "id": 1, + "label": "usenet" + }); + let response: Tag = serde_json::from_value(tag_json.clone()).unwrap(); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "label": "usenet" })) + .returns(tag_json) + .build_for(LidarrEvent::AddTag("usenet".to_owned())) + .await; + app.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app); + + let result = network + .handle_lidarr_event(LidarrEvent::AddTag("usenet".to_owned())) + .await; + + mock.assert_async().await; + + let LidarrSerdeable::Tag(tag) = result.unwrap() else { + panic!("Expected Tag"); + }; + + assert_eq!(tag, response); + assert_eq!( + app.lock().await.data.lidarr_data.tags_map.get_by_left(&1), + Some(&"usenet".to_owned()) + ); + } + + #[tokio::test] + async fn test_extract_and_add_lidarr_tag_ids_vec() { + let app_arc = Arc::new(Mutex::new(App::test_default())); + let tags = " test,HI ,, usenet "; + { + let mut app = app_arc.lock().await; + app.data.lidarr_data.tags_map = BiMap::from_iter([ + (1, "usenet".to_owned()), + (2, "test".to_owned()), + (3, "hi".to_owned()), + ]); + } + app_arc.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app_arc); + + assert_eq!( + network.extract_and_add_lidarr_tag_ids_vec(tags).await, + vec![2, 3, 1] + ); + } + + #[tokio::test] + async fn test_extract_and_add_lidarr_tag_ids_vec_add_missing_tags_first() { + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "label": "TESTING" })) + .returns(json!({ "id": 3, "label": "testing" })) + .build_for(LidarrEvent::GetTags) + .await; + let tags = "usenet, test, TESTING"; + { + let mut app_guard = app.lock().await; + app_guard.data.lidarr_data.edit_artist_modal = Some(EditArtistModal { + tags: tags.into(), + ..EditArtistModal::default() + }); + app_guard.data.lidarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); + } + app.lock().await.server_tabs.set_index(2); + let mut network = test_network(&app); + + let tag_ids_vec = network.extract_and_add_lidarr_tag_ids_vec(tags).await; + + mock.assert_async().await; + assert_eq!(tag_ids_vec, vec![1, 2, 3]); + assert_eq!( + app.lock().await.data.lidarr_data.tags_map, + BiMap::from_iter([ + (1, "usenet".to_owned()), + (2, "test".to_owned()), + (3, "testing".to_owned()) + ]) + ); + } } diff --git a/src/ui/lidarr_ui/library/edit_artist_ui.rs b/src/ui/lidarr_ui/library/edit_artist_ui.rs index 7137904..9a45554 100644 --- a/src/ui/lidarr_ui/library/edit_artist_ui.rs +++ b/src/ui/lidarr_ui/library/edit_artist_ui.rs @@ -12,7 +12,7 @@ use crate::models::servarr_data::lidarr::modals::EditArtistModal; use crate::render_selectable_input_box; use crate::ui::styles::ManagarrStyle; -use crate::ui::utils::{title_block_centered}; +use crate::ui::utils::title_block_centered; use crate::ui::widgets::button::Button; use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; @@ -91,7 +91,7 @@ fn draw_edit_artist_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, ar let selected_metadata_profile = metadata_profile_list.current_selection(); let [ - _, + _, monitored_area, monitor_new_items_area, quality_profile_area, diff --git a/src/ui/lidarr_ui/library/edit_artist_ui_tests.rs b/src/ui/lidarr_ui/library/edit_artist_ui_tests.rs index 2980d1d..f6a12cc 100644 --- a/src/ui/lidarr_ui/library/edit_artist_ui_tests.rs +++ b/src/ui/lidarr_ui/library/edit_artist_ui_tests.rs @@ -1,22 +1,49 @@ #[cfg(test)] mod tests { - use pretty_assertions::assert_eq; use strum::IntoEnumIterator; - use crate::models::Route; - use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, EDIT_ARTIST_BLOCKS}; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::lidarr::lidarr_data::{ + ActiveLidarrBlock, EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, + }; use crate::ui::DrawUi; use crate::ui::lidarr_ui::library::edit_artist_ui::EditArtistUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_edit_artist_ui_accepts() { - let mut edit_artist_ui_blocks = Vec::new(); - for block in ActiveLidarrBlock::iter() { - if EditArtistUi::accepts(Route::Lidarr(block, None)) { - edit_artist_ui_blocks.push(block); + ActiveLidarrBlock::iter().for_each(|active_lidarr_block| { + if EDIT_ARTIST_BLOCKS.contains(&active_lidarr_block) { + assert!(EditArtistUi::accepts(active_lidarr_block.into())); + } else { + assert!(!EditArtistUi::accepts(active_lidarr_block.into())); } - } + }); + } - assert_eq!(edit_artist_ui_blocks, EDIT_ARTIST_BLOCKS.to_vec()); + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveLidarrBlock::EditArtistPrompt)] + #[case(ActiveLidarrBlock::EditArtistConfirmPrompt)] + #[case(ActiveLidarrBlock::EditArtistSelectMetadataProfile)] + #[case(ActiveLidarrBlock::EditArtistSelectMonitorNewItems)] + #[case(ActiveLidarrBlock::EditArtistSelectQualityProfile)] + fn test_edit_artist_ui_renders(#[case] active_lidarr_block: ActiveLidarrBlock) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_lidarr_block.into()); + app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditArtistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("edit_artist_{active_lidarr_block}"), output); + } } } diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__delete_artist_ui__delete_artist_ui_tests__tests__snapshot_tests__delete_artist_ui_renders_delete_artist.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__delete_artist_ui__delete_artist_ui_tests__tests__snapshot_tests__delete_artist_ui_renders_delete_artist.snap index 6329eb8..7c770ca 100644 --- a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__delete_artist_ui__delete_artist_ui_tests__tests__snapshot_tests__delete_artist_ui_renders_delete_artist.snap +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__delete_artist_ui__delete_artist_ui_tests__tests__snapshot_tests__delete_artist_ui_renders_delete_artist.snap @@ -24,7 +24,7 @@ expression: output │ │ │ │ │ ╭───╮ │ - │ Delete Artist Files: │ │ │ + │ Delete Artist Files: │ ✔ │ │ │ ╰───╯ │ │ ╭───╮ │ │ Add List Exclusion: │ │ │ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistConfirmPrompt.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistConfirmPrompt.snap new file mode 100644 index 0000000..0518e01 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistConfirmPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/lidarr_ui/library/edit_artist_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────── Edit - ───────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Monitor New Albums: │All Albums ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Quality Profile: │Lossless ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Metadata Profile: │Standard ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Path: │/nfs/music │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistPrompt.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistPrompt.snap new file mode 100644 index 0000000..0518e01 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/lidarr_ui/library/edit_artist_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────── Edit - ───────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Monitor New Albums: │All Albums ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Quality Profile: │Lossless ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Metadata Profile: │Standard ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Path: │/nfs/music │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectMetadataProfile.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectMetadataProfile.snap new file mode 100644 index 0000000..e07f1c6 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectMetadataProfile.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/lidarr_ui/library/edit_artist_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────── Edit - ───────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───────────────────────────────╮──────────────────────────────╮ │ + │ Monitor│Standard │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Qual│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Metad│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ ╰───────────────────────────────╯──────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectMonitorNewItems.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectMonitorNewItems.snap new file mode 100644 index 0000000..b8d5af3 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectMonitorNewItems.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/lidarr_ui/library/edit_artist_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────── Edit - ───────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───────────────────────────────╮──────────────────────────────╮ │ + │ Monitor│All Albums │ ▼ │ │ + │ │No New Albums │──────────────────────────────╯ │ + │ │New Albums │──────────────────────────────╮ │ + │ Qual│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Metad│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ ╰───────────────────────────────╯──────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectQualityProfile.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectQualityProfile.snap new file mode 100644 index 0000000..fdb719d --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__edit_artist_ui__edit_artist_ui_tests__tests__snapshot_tests__edit_artist_EditArtistSelectQualityProfile.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/lidarr_ui/library/edit_artist_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────── Edit - ───────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───────────────────────────────╮──────────────────────────────╮ │ + │ Monitor│Lossless │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Qual│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Metad│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ ╰───────────────────────────────╯──────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_artist_over_library.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_artist_over_library.snap index 83323e6..a85e622 100644 --- a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_artist_over_library.snap +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_artist_over_library.snap @@ -24,7 +24,7 @@ expression: output │ │ │ │ │ ╭───╮ │ - │ Delete Artist Files: │ │ │ + │ Delete Artist Files: │ ✔ │ │ │ ╰───╯ │ │ ╭───╮ │ │ Add List Exclusion: │ │ │