From 7bb5f83a5648c67f04a12b4f3a8d6f1a87a3649a Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Fri, 16 Jan 2026 23:21:25 -0700 Subject: [PATCH] feat: Lidarr UI support for album details popup --- src/app/lidarr/lidarr_tests.rs | 168 +- src/app/lidarr/mod.rs | 16 +- .../library/album_details_handler.rs | 834 ++++---- .../library/album_details_handler_tests.rs | 1676 ++++++++--------- .../library/artist_details_handler.rs | 6 +- .../library/artist_details_handler_tests.rs | 8 +- .../library/library_handler_tests.rs | 11 +- src/handlers/lidarr_handlers/library/mod.rs | 32 +- src/models/lidarr_models.rs | 2 +- .../lidarr_network_test_utils.rs | 2 +- src/ui/lidarr_ui/library/album_details_ui.rs | 505 +++++ .../library/album_details_ui_tests.rs | 131 ++ src/ui/lidarr_ui/library/artist_details_ui.rs | 9 +- .../library/artist_details_ui_tests.rs | 3 +- src/ui/lidarr_ui/library/library_ui_tests.rs | 5 +- src/ui/lidarr_ui/library/mod.rs | 1 + ..._album_details_renders_AlbumDetails_0.snap | 50 + ...details_renders_AlbumHistoryDetails_1.snap | 50 + ...ails_renders_AlbumHistorySortPrompt_1.snap | 50 + ..._album_details_renders_AlbumHistory_1.snap | 50 + ...ders_AutomaticallySearchAlbumPrompt_0.snap | 50 + ...ders_AutomaticallySearchAlbumPrompt_1.snap | 50 + ...ders_AutomaticallySearchAlbumPrompt_2.snap | 50 + ...tails_renders_DeleteTrackFilePrompt_0.snap | 50 + ...ils_renders_FilterAlbumHistoryError_1.snap | 50 + ..._details_renders_FilterAlbumHistory_1.snap | 50 + ...ders_ManualAlbumSearchConfirmPrompt_2.snap | 50 + ...renders_ManualAlbumSearchSortPrompt_2.snap | 50 + ...m_details_renders_ManualAlbumSearch_2.snap | 50 + ...ils_renders_SearchAlbumHistoryError_1.snap | 50 + ..._details_renders_SearchAlbumHistory_1.snap | 50 + ...m_details_renders_SearchTracksError_0.snap | 50 + ..._album_details_renders_SearchTracks_0.snap | 50 + ...s__empty_album_details_AlbumDetails_0.snap | 50 + ...y_album_details_AlbumHistoryDetails_1.snap | 50 + ...s__empty_album_details_AlbumHistory_1.snap | 50 + ...pty_album_details_ManualAlbumSearch_2.snap | 50 + ..._loading_album_details_AlbumDetails_0.snap | 50 + ...g_album_details_AlbumHistoryDetails_1.snap | 50 + ..._loading_album_details_AlbumHistory_1.snap | 50 + ...ing_album_details_ManualAlbumSearch_2.snap | 50 + src/ui/ui_tests.rs | 102 +- 42 files changed, 3330 insertions(+), 1431 deletions(-) create mode 100644 src/ui/lidarr_ui/library/album_details_ui.rs create mode 100644 src/ui/lidarr_ui/library/album_details_ui_tests.rs create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumDetails_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistoryDetails_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistorySortPrompt_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistory_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_2.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_DeleteTrackFilePrompt_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistoryError_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistory_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchConfirmPrompt_2.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchSortPrompt_2.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearch_2.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistoryError_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistory_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracksError_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracks_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumDetails_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistoryDetails_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistory_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_ManualAlbumSearch_2.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumDetails_0.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistoryDetails_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistory_1.snap create mode 100644 src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_ManualAlbumSearch_2.snap diff --git a/src/app/lidarr/lidarr_tests.rs b/src/app/lidarr/lidarr_tests.rs index b595595..a2fa691 100644 --- a/src/app/lidarr/lidarr_tests.rs +++ b/src/app/lidarr/lidarr_tests.rs @@ -3,13 +3,13 @@ mod tests { use crate::app::App; use crate::models::lidarr_models::{Album, Artist, LidarrRelease}; use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock; + use crate::models::servarr_data::lidarr::modals::AlbumDetailsModal; use crate::models::servarr_models::Indexer; use crate::network::NetworkEvent; use crate::network::lidarr_network::LidarrEvent; use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::artist; use pretty_assertions::{assert_eq, assert_str_eq}; use tokio::sync::mpsc; - use crate::models::servarr_data::lidarr::modals::AlbumDetailsModal; #[tokio::test] async fn test_dispatch_by_lidarr_block_artists() { @@ -158,7 +158,7 @@ mod tests { } #[tokio::test] - async fn test_dispatch_by_album_history_block() { + async fn test_dispatch_by_album_history_block() { let (tx, mut rx) = mpsc::channel::(500); let mut app = App::test_default(); app.data.lidarr_data.prompt_confirm = true; @@ -172,101 +172,101 @@ mod tests { ..Album::default() }]); - app - .dispatch_by_lidarr_block(&ActiveLidarrBlock::AlbumHistory) - .await; + app + .dispatch_by_lidarr_block(&ActiveLidarrBlock::AlbumHistory) + .await; - assert!(app.is_loading); - assert_eq!( - rx.recv().await.unwrap(), - LidarrEvent::GetAlbumHistory(1, 1).into() - ); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_eq!(app.tick_count, 0); - } + assert!(app.is_loading); + assert_eq!( + rx.recv().await.unwrap(), + LidarrEvent::GetAlbumHistory(1, 1).into() + ); + assert!(!app.data.lidarr_data.prompt_confirm); + assert_eq!(app.tick_count, 0); + } - #[tokio::test] - async fn test_dispatch_by_album_history_block_no_op_when_albums_table_is_empty() { - let (tx, _) = mpsc::channel::(500); - let mut app = App::test_default(); - app.data.lidarr_data.prompt_confirm = true; - app.network_tx = Some(tx); - app.data.lidarr_data.artists.set_items(vec![Artist { - id: 1, - ..Artist::default() - }]); + #[tokio::test] + async fn test_dispatch_by_album_history_block_no_op_when_albums_table_is_empty() { + let (tx, _) = mpsc::channel::(500); + let mut app = App::test_default(); + app.data.lidarr_data.prompt_confirm = true; + app.network_tx = Some(tx); + app.data.lidarr_data.artists.set_items(vec![Artist { + id: 1, + ..Artist::default() + }]); - app - .dispatch_by_lidarr_block(&ActiveLidarrBlock::AlbumHistory) - .await; + app + .dispatch_by_lidarr_block(&ActiveLidarrBlock::AlbumHistory) + .await; - assert!(!app.is_loading); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_eq!(app.tick_count, 0); - } + assert!(!app.is_loading); + assert!(!app.data.lidarr_data.prompt_confirm); + assert_eq!(app.tick_count, 0); + } - #[tokio::test] - async fn test_dispatch_by_manual_album_search_block() { - let (tx, mut rx) = mpsc::channel::(500); - let mut app = App::test_default(); - app.data.lidarr_data.prompt_confirm = true; - app.network_tx = Some(tx); - app.data.lidarr_data.artists.set_items(vec![Artist { - id: 1, - ..Artist::default() - }]); - app.data.lidarr_data.albums.set_items(vec![Album { - id: 1, - ..Album::default() - }]); - app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); + #[tokio::test] + async fn test_dispatch_by_manual_album_search_block() { + let (tx, mut rx) = mpsc::channel::(500); + let mut app = App::test_default(); + app.data.lidarr_data.prompt_confirm = true; + app.network_tx = Some(tx); + app.data.lidarr_data.artists.set_items(vec![Artist { + id: 1, + ..Artist::default() + }]); + app.data.lidarr_data.albums.set_items(vec![Album { + id: 1, + ..Album::default() + }]); + app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); - app - .dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch) - .await; + app + .dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch) + .await; - assert!(app.is_loading); - assert_eq!( - rx.recv().await.unwrap(), - LidarrEvent::GetAlbumReleases(1, 1).into() - ); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_eq!(app.tick_count, 0); - } + assert!(app.is_loading); + assert_eq!( + rx.recv().await.unwrap(), + LidarrEvent::GetAlbumReleases(1, 1).into() + ); + assert!(!app.data.lidarr_data.prompt_confirm); + assert_eq!(app.tick_count, 0); + } - #[tokio::test] - async fn test_dispatch_by_manual_album_search_block_is_loading() { - let mut app = App { - is_loading: true, - ..App::test_default() - }; + #[tokio::test] + async fn test_dispatch_by_manual_album_search_block_is_loading() { + let mut app = App { + is_loading: true, + ..App::test_default() + }; - app - .dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch) - .await; + app + .dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch) + .await; - assert!(app.is_loading); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_eq!(app.tick_count, 0); - } + assert!(app.is_loading); + assert!(!app.data.lidarr_data.prompt_confirm); + assert_eq!(app.tick_count, 0); + } - #[tokio::test] - async fn test_dispatch_by_manual_album_search_block_album_releases_non_empty() { - let mut app = App::test_default(); - let mut album_details_modal = AlbumDetailsModal::default(); - album_details_modal - .album_releases - .set_items(vec![LidarrRelease::default()]); - app.data.lidarr_data.album_details_modal = Some(album_details_modal); + #[tokio::test] + async fn test_dispatch_by_manual_album_search_block_album_releases_non_empty() { + let mut app = App::test_default(); + let mut album_details_modal = AlbumDetailsModal::default(); + album_details_modal + .album_releases + .set_items(vec![LidarrRelease::default()]); + app.data.lidarr_data.album_details_modal = Some(album_details_modal); - app - .dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch) - .await; + app + .dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch) + .await; - assert!(!app.is_loading); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_eq!(app.tick_count, 0); - } + assert!(!app.is_loading); + assert!(!app.data.lidarr_data.prompt_confirm); + assert_eq!(app.tick_count, 0); + } #[tokio::test] async fn test_dispatch_by_downloads_block() { diff --git a/src/app/lidarr/mod.rs b/src/app/lidarr/mod.rs index ef7f57b..ad3a4ae 100644 --- a/src/app/lidarr/mod.rs +++ b/src/app/lidarr/mod.rs @@ -1,8 +1,8 @@ +use super::App; use crate::{ models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock, network::lidarr_network::LidarrEvent, }; -use super::App; pub mod lidarr_context_clues; @@ -70,8 +70,11 @@ impl App<'_> { if !self.data.lidarr_data.albums.is_empty() { self .dispatch_network_event( - LidarrEvent::GetAlbumHistory(self.extract_artist_id().await, self.extract_album_id().await) - .into(), + LidarrEvent::GetAlbumHistory( + self.extract_artist_id().await, + self.extract_album_id().await, + ) + .into(), ) .await; } @@ -81,8 +84,11 @@ impl App<'_> { Some(album_details_modal) if album_details_modal.album_releases.is_empty() => { self .dispatch_network_event( - LidarrEvent::GetAlbumReleases(self.extract_artist_id().await, self.extract_album_id().await) - .into(), + LidarrEvent::GetAlbumReleases( + self.extract_artist_id().await, + self.extract_album_id().await, + ) + .into(), ) .await; } diff --git a/src/handlers/lidarr_handlers/library/album_details_handler.rs b/src/handlers/lidarr_handlers/library/album_details_handler.rs index 34e96f8..2186f81 100644 --- a/src/handlers/lidarr_handlers/library/album_details_handler.rs +++ b/src/handlers/lidarr_handlers/library/album_details_handler.rs @@ -5,10 +5,10 @@ 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::lidarr::lidarr_data::{ActiveLidarrBlock, ALBUM_DETAILS_BLOCKS}; use crate::models::lidarr_models::{ - Track, LidarrHistoryItem, LidarrRelease, LidarrReleaseDownloadBody, + LidarrHistoryItem, LidarrRelease, LidarrReleaseDownloadBody, Track, }; +use crate::models::servarr_data::lidarr::lidarr_data::{ALBUM_DETAILS_BLOCKS, ActiveLidarrBlock}; use crate::models::stateful_table::SortOption; use crate::network::lidarr_network::LidarrEvent; use serde_json::Number; @@ -18,459 +18,451 @@ use serde_json::Number; mod album_details_handler_tests; pub(in crate::handlers::lidarr_handlers) struct AlbumDetailsHandler<'a, 'b> { - key: Key, - app: &'a mut App<'b>, - active_lidarr_block: ActiveLidarrBlock, - _context: Option, + key: Key, + app: &'a mut App<'b>, + active_lidarr_block: ActiveLidarrBlock, + _context: Option, } impl AlbumDetailsHandler<'_, '_> { - fn extract_track_file_id(&self) -> i64 { - self - .app - .data - .lidarr_data - .album_details_modal - .as_ref() - .expect("Album details have not been loaded") - .tracks - .current_selection() - .track_file_id - } + fn extract_track_file_id(&self) -> i64 { + self + .app + .data + .lidarr_data + .album_details_modal + .as_ref() + .expect("Album details have not been loaded") + .tracks + .current_selection() + .track_file_id + } - fn extract_album_id(&self) -> i64 { - self - .app - .data - .lidarr_data - .albums - .current_selection() - .id - } + fn extract_album_id(&self) -> i64 { + self.app.data.lidarr_data.albums.current_selection().id + } } impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for AlbumDetailsHandler<'a, 'b> { - fn handle(&mut self) { - let tracks_table_handling_config = - TableHandlingConfig::new(ActiveLidarrBlock::AlbumDetails.into()) - .searching_block(ActiveLidarrBlock::SearchTracks.into()) - .search_error_block(ActiveLidarrBlock::SearchTracksError.into()) - .search_field_fn(|track: &Track| &track.title); - let album_history_table_handling_config = - TableHandlingConfig::new(ActiveLidarrBlock::AlbumHistory.into()) - .sorting_block(ActiveLidarrBlock::AlbumHistorySortPrompt.into()) - .sort_options(history_sorting_options()) - .searching_block(ActiveLidarrBlock::SearchAlbumHistory.into()) - .search_error_block(ActiveLidarrBlock::SearchAlbumHistoryError.into()) - .search_field_fn(|history_item: &LidarrHistoryItem| &history_item.source_title.text) - .filtering_block(ActiveLidarrBlock::FilterAlbumHistory.into()) - .filter_error_block(ActiveLidarrBlock::FilterAlbumHistoryError.into()) - .filter_field_fn(|history_item: &LidarrHistoryItem| &history_item.source_title.text); - let album_releases_table_handling_config = - TableHandlingConfig::new(ActiveLidarrBlock::ManualAlbumSearch.into()) - .sorting_block(ActiveLidarrBlock::ManualAlbumSearchSortPrompt.into()) - .sort_options(releases_sorting_options()); + fn handle(&mut self) { + let tracks_table_handling_config = + TableHandlingConfig::new(ActiveLidarrBlock::AlbumDetails.into()) + .searching_block(ActiveLidarrBlock::SearchTracks.into()) + .search_error_block(ActiveLidarrBlock::SearchTracksError.into()) + .search_field_fn(|track: &Track| &track.title); + let album_history_table_handling_config = + TableHandlingConfig::new(ActiveLidarrBlock::AlbumHistory.into()) + .sorting_block(ActiveLidarrBlock::AlbumHistorySortPrompt.into()) + .sort_options(history_sorting_options()) + .searching_block(ActiveLidarrBlock::SearchAlbumHistory.into()) + .search_error_block(ActiveLidarrBlock::SearchAlbumHistoryError.into()) + .search_field_fn(|history_item: &LidarrHistoryItem| &history_item.source_title.text) + .filtering_block(ActiveLidarrBlock::FilterAlbumHistory.into()) + .filter_error_block(ActiveLidarrBlock::FilterAlbumHistoryError.into()) + .filter_field_fn(|history_item: &LidarrHistoryItem| &history_item.source_title.text); + let album_releases_table_handling_config = + TableHandlingConfig::new(ActiveLidarrBlock::ManualAlbumSearch.into()) + .sorting_block(ActiveLidarrBlock::ManualAlbumSearchSortPrompt.into()) + .sort_options(releases_sorting_options()); - if !handle_table( - self, - |app| { - &mut app - .data - .lidarr_data - .album_details_modal - .as_mut() - .expect("Album details modal is undefined") - .tracks - }, - tracks_table_handling_config, - ) && !handle_table( - self, - |app| { - &mut app - .data - .lidarr_data - .album_details_modal - .as_mut() - .expect("Album details modal is undefined") - .album_history - }, - album_history_table_handling_config, - ) && !handle_table( - self, - |app| { - &mut app - .data - .lidarr_data - .album_details_modal - .as_mut() - .expect("Album details modal is undefined") - .album_releases - }, - album_releases_table_handling_config, - ) { - self.handle_key_event(); - } - } + if !handle_table( + self, + |app| { + &mut app + .data + .lidarr_data + .album_details_modal + .as_mut() + .expect("Album details modal is undefined") + .tracks + }, + tracks_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .lidarr_data + .album_details_modal + .as_mut() + .expect("Album details modal is undefined") + .album_history + }, + album_history_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .lidarr_data + .album_details_modal + .as_mut() + .expect("Album details modal is undefined") + .album_releases + }, + album_releases_table_handling_config, + ) { + self.handle_key_event(); + } + } - fn accepts(active_block: ActiveLidarrBlock) -> bool { - ALBUM_DETAILS_BLOCKS.contains(&active_block) - } + fn accepts(active_block: ActiveLidarrBlock) -> bool { + ALBUM_DETAILS_BLOCKS.contains(&active_block) + } - fn ignore_special_keys(&self) -> bool { - self.app.ignore_special_keys_for_textbox_input - } + fn ignore_special_keys(&self) -> bool { + self.app.ignore_special_keys_for_textbox_input + } - fn new( - key: Key, - app: &'a mut App<'b>, - active_block: ActiveLidarrBlock, - context: Option, - ) -> AlbumDetailsHandler<'a, 'b> { - AlbumDetailsHandler { - key, - app, - active_lidarr_block: active_block, - _context: context, - } - } + fn new( + key: Key, + app: &'a mut App<'b>, + active_block: ActiveLidarrBlock, + context: Option, + ) -> AlbumDetailsHandler<'a, 'b> { + AlbumDetailsHandler { + key, + app, + active_lidarr_block: active_block, + _context: context, + } + } - fn get_key(&self) -> Key { - self.key - } + fn get_key(&self) -> Key { + self.key + } - fn is_ready(&self) -> bool { - if self.app.is_loading { - return false; - } + fn is_ready(&self) -> bool { + if self.app.is_loading { + return false; + } - let Some(album_details_modal) = &self.app.data.lidarr_data.album_details_modal else { - return false; - }; + let Some(album_details_modal) = &self.app.data.lidarr_data.album_details_modal else { + return false; + }; - match self.active_lidarr_block { - ActiveLidarrBlock::AlbumDetails => !album_details_modal.tracks.is_empty(), - ActiveLidarrBlock::AlbumHistory => !album_details_modal.album_history.is_empty(), - ActiveLidarrBlock::ManualAlbumSearch => !album_details_modal.album_releases.is_empty(), - _ => true, - } - } + match self.active_lidarr_block { + ActiveLidarrBlock::AlbumDetails => !album_details_modal.tracks.is_empty(), + ActiveLidarrBlock::AlbumHistory => !album_details_modal.album_history.is_empty(), + ActiveLidarrBlock::ManualAlbumSearch => !album_details_modal.album_releases.is_empty(), + _ => true, + } + } - fn handle_scroll_up(&mut self) {} + fn handle_scroll_up(&mut self) {} - fn handle_scroll_down(&mut self) {} + fn handle_scroll_down(&mut self) {} - fn handle_home(&mut self) {} + fn handle_home(&mut self) {} - fn handle_end(&mut self) {} + fn handle_end(&mut self) {} - fn handle_delete(&mut self) { - if self.active_lidarr_block == ActiveLidarrBlock::AlbumDetails { - self - .app - .push_navigation_stack(ActiveLidarrBlock::DeleteTrackFilePrompt.into()); - } - } + fn handle_delete(&mut self) { + if self.active_lidarr_block == ActiveLidarrBlock::AlbumDetails { + self + .app + .push_navigation_stack(ActiveLidarrBlock::DeleteTrackFilePrompt.into()); + } + } - fn handle_left_right_action(&mut self) { - match self.active_lidarr_block { - ActiveLidarrBlock::AlbumDetails - | ActiveLidarrBlock::AlbumHistory - | ActiveLidarrBlock::ManualAlbumSearch => match self.key { - _ if matches_key!(left, self.key) => { - self - .app - .data - .lidarr_data - .album_details_modal - .as_mut() - .unwrap() - .album_details_tabs - .previous(); - self.app.pop_and_push_navigation_stack( - self - .app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_details_tabs - .get_active_route(), - ); - } - _ if matches_key!(right, self.key) => { - self - .app - .data - .lidarr_data - .album_details_modal - .as_mut() - .unwrap() - .album_details_tabs - .next(); - self.app.pop_and_push_navigation_stack( - self - .app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_details_tabs - .get_active_route(), - ); - } - _ => (), - }, - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt - | ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt - | ActiveLidarrBlock::DeleteTrackFilePrompt => { - handle_prompt_toggle(self.app, self.key); - } - _ => (), - } - } + fn handle_left_right_action(&mut self) { + match self.active_lidarr_block { + ActiveLidarrBlock::AlbumDetails + | ActiveLidarrBlock::AlbumHistory + | ActiveLidarrBlock::ManualAlbumSearch => match self.key { + _ if matches_key!(left, self.key) => { + self + .app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_details_tabs + .previous(); + self.app.pop_and_push_navigation_stack( + self + .app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_details_tabs + .get_active_route(), + ); + } + _ if matches_key!(right, self.key) => { + self + .app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_details_tabs + .next(); + self.app.pop_and_push_navigation_stack( + self + .app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_details_tabs + .get_active_route(), + ); + } + _ => (), + }, + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt + | ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt + | ActiveLidarrBlock::DeleteTrackFilePrompt => { + handle_prompt_toggle(self.app, self.key); + } + _ => (), + } + } - fn handle_submit(&mut self) { - match self.active_lidarr_block { - // ActiveLidarrBlock::AlbumDetails - // if self.app.data.lidarr_data.album_details_modal.is_some() - // && !self - // .app - // .data - // .lidarr_data - // .album_details_modal - // .as_ref() - // .unwrap() - // .tracks - // .is_empty() => - // { - // self - // .app - // .push_navigation_stack(ActiveLidarrBlock::TrackDetails.into()) - // } - ActiveLidarrBlock::AlbumHistory => self - .app - .push_navigation_stack(ActiveLidarrBlock::AlbumHistoryDetails.into()), - ActiveLidarrBlock::DeleteTrackFilePrompt => { - if self.app.data.lidarr_data.prompt_confirm { - self.app.data.lidarr_data.prompt_confirm_action = Some(LidarrEvent::DeleteTrackFile( - self.extract_track_file_id(), - )); - } + fn handle_submit(&mut self) { + match self.active_lidarr_block { + // ActiveLidarrBlock::AlbumDetails + // if self.app.data.lidarr_data.album_details_modal.is_some() + // && !self + // .app + // .data + // .lidarr_data + // .album_details_modal + // .as_ref() + // .unwrap() + // .tracks + // .is_empty() => + // { + // self + // .app + // .push_navigation_stack(ActiveLidarrBlock::TrackDetails.into()) + // } + ActiveLidarrBlock::AlbumHistory => self + .app + .push_navigation_stack(ActiveLidarrBlock::AlbumHistoryDetails.into()), + ActiveLidarrBlock::DeleteTrackFilePrompt => { + if self.app.data.lidarr_data.prompt_confirm { + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::DeleteTrackFile(self.extract_track_file_id())); + } - self.app.pop_navigation_stack(); - } - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt => { - if self.app.data.lidarr_data.prompt_confirm { - self.app.data.lidarr_data.prompt_confirm_action = Some( - LidarrEvent::TriggerAutomaticAlbumSearch(self.extract_album_id()), - ); - } + self.app.pop_navigation_stack(); + } + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt => { + if self.app.data.lidarr_data.prompt_confirm { + self.app.data.lidarr_data.prompt_confirm_action = Some( + LidarrEvent::TriggerAutomaticAlbumSearch(self.extract_album_id()), + ); + } - self.app.pop_navigation_stack(); - } - ActiveLidarrBlock::ManualAlbumSearch => { - self - .app - .push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into()); - } - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt => { - if self.app.data.lidarr_data.prompt_confirm { - let LidarrRelease { - guid, indexer_id, .. - } = self - .app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_releases - .current_selection(); - let params = LidarrReleaseDownloadBody { - guid: guid.clone(), - indexer_id: *indexer_id, - }; - self.app.data.lidarr_data.prompt_confirm_action = - Some(LidarrEvent::DownloadRelease(params)); - } + self.app.pop_navigation_stack(); + } + ActiveLidarrBlock::ManualAlbumSearch => { + self + .app + .push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into()); + } + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt => { + if self.app.data.lidarr_data.prompt_confirm { + let LidarrRelease { + guid, indexer_id, .. + } = self + .app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_releases + .current_selection(); + let params = LidarrReleaseDownloadBody { + guid: guid.clone(), + indexer_id: *indexer_id, + }; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::DownloadRelease(params)); + } - self.app.pop_navigation_stack(); - } - _ => (), - } - } + self.app.pop_navigation_stack(); + } + _ => (), + } + } - fn handle_esc(&mut self) { - match self.active_lidarr_block { - ActiveLidarrBlock::AlbumDetails | ActiveLidarrBlock::ManualAlbumSearch => { - self.app.pop_navigation_stack(); - self.app.data.lidarr_data.album_details_modal = None; - } - ActiveLidarrBlock::AlbumHistoryDetails => { - self.app.pop_navigation_stack(); - } - ActiveLidarrBlock::AlbumHistory => { - if self - .app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_history - .filtered_items - .is_some() - { - self - .app - .data - .lidarr_data - .album_details_modal - .as_mut() - .unwrap() - .album_history - .filtered_items = None; - } else { - self.app.pop_navigation_stack(); - self.app.data.lidarr_data.album_details_modal = None; - } - } - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt - | ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt - | ActiveLidarrBlock::DeleteTrackFilePrompt => { - self.app.pop_navigation_stack(); - self.app.data.lidarr_data.prompt_confirm = false; - } - _ => (), - } - } + fn handle_esc(&mut self) { + match self.active_lidarr_block { + ActiveLidarrBlock::AlbumDetails | ActiveLidarrBlock::ManualAlbumSearch => { + self.app.pop_navigation_stack(); + self.app.data.lidarr_data.album_details_modal = None; + } + ActiveLidarrBlock::AlbumHistoryDetails => { + self.app.pop_navigation_stack(); + } + ActiveLidarrBlock::AlbumHistory => { + if self + .app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_history + .filtered_items + .is_some() + { + self + .app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_history + .filtered_items = None; + } else { + self.app.pop_navigation_stack(); + self.app.data.lidarr_data.album_details_modal = None; + } + } + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt + | ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt + | ActiveLidarrBlock::DeleteTrackFilePrompt => { + self.app.pop_navigation_stack(); + self.app.data.lidarr_data.prompt_confirm = false; + } + _ => (), + } + } - fn handle_char_key_event(&mut self) { - let key = self.key; - match self.active_lidarr_block { - ActiveLidarrBlock::AlbumDetails - | ActiveLidarrBlock::AlbumHistory - | ActiveLidarrBlock::ManualAlbumSearch => match self.key { - _ if matches_key!(refresh, self.key) => { - self - .app - .pop_and_push_navigation_stack(self.active_lidarr_block.into()); - } - _ if matches_key!(auto_search, self.key) => { - self - .app - .push_navigation_stack(ActiveLidarrBlock::AutomaticallySearchAlbumPrompt.into()); - } - _ => (), - }, - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt if matches_key!(confirm, key) => { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = Some( - LidarrEvent::TriggerAutomaticAlbumSearch(self.extract_album_id()), - ); + fn handle_char_key_event(&mut self) { + let key = self.key; + match self.active_lidarr_block { + ActiveLidarrBlock::AlbumDetails + | ActiveLidarrBlock::AlbumHistory + | ActiveLidarrBlock::ManualAlbumSearch => match self.key { + _ if matches_key!(refresh, self.key) => { + self + .app + .pop_and_push_navigation_stack(self.active_lidarr_block.into()); + } + _ if matches_key!(auto_search, self.key) => { + self + .app + .push_navigation_stack(ActiveLidarrBlock::AutomaticallySearchAlbumPrompt.into()); + } + _ => (), + }, + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt if matches_key!(confirm, key) => { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = Some( + LidarrEvent::TriggerAutomaticAlbumSearch(self.extract_album_id()), + ); - self.app.pop_navigation_stack(); - } - ActiveLidarrBlock::DeleteTrackFilePrompt if matches_key!(confirm, key) => { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = Some(LidarrEvent::DeleteTrackFile( - self.extract_track_file_id(), - )); + self.app.pop_navigation_stack(); + } + ActiveLidarrBlock::DeleteTrackFilePrompt if matches_key!(confirm, key) => { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::DeleteTrackFile(self.extract_track_file_id())); - self.app.pop_navigation_stack(); - } - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt if matches_key!(confirm, key) => { - self.app.data.lidarr_data.prompt_confirm = true; - let LidarrRelease { - guid, indexer_id, .. - } = self - .app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_releases - .current_selection(); - let params = LidarrReleaseDownloadBody { - guid: guid.clone(), - indexer_id: *indexer_id, - }; - self.app.data.lidarr_data.prompt_confirm_action = - Some(LidarrEvent::DownloadRelease(params)); + self.app.pop_navigation_stack(); + } + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt if matches_key!(confirm, key) => { + self.app.data.lidarr_data.prompt_confirm = true; + let LidarrRelease { + guid, indexer_id, .. + } = self + .app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_releases + .current_selection(); + let params = LidarrReleaseDownloadBody { + guid: guid.clone(), + indexer_id: *indexer_id, + }; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::DownloadRelease(params)); - self.app.pop_navigation_stack(); - } - _ => (), - } - } + self.app.pop_navigation_stack(); + } + _ => (), + } + } - fn app_mut(&mut self) -> &mut App<'b> { - self.app - } + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } - fn current_route(&self) -> Route { - self.app.get_current_route() - } + fn current_route(&self) -> Route { + self.app.get_current_route() + } } pub(in crate::handlers::lidarr_handlers::library) fn releases_sorting_options() - -> Vec> { - vec![ - SortOption { - name: "Source", - cmp_fn: Some(|a, b| a.protocol.cmp(&b.protocol)), - }, - SortOption { - name: "Age", - cmp_fn: Some(|a, b| a.age.cmp(&b.age)), - }, - SortOption { - name: "Rejected", - cmp_fn: Some(|a, b| a.rejected.cmp(&b.rejected)), - }, - SortOption { - name: "Title", - cmp_fn: Some(|a, b| { - a.title - .text - .to_lowercase() - .cmp(&b.title.text.to_lowercase()) - }), - }, - SortOption { - name: "Indexer", - cmp_fn: Some(|a, b| a.indexer.to_lowercase().cmp(&b.indexer.to_lowercase())), - }, - SortOption { - name: "Size", - cmp_fn: Some(|a, b| a.size.cmp(&b.size)), - }, - SortOption { - name: "Peers", - cmp_fn: Some(|a, b| { - let default_number = Number::from(i64::MAX); - let seeder_a = a - .seeders - .as_ref() - .unwrap_or(&default_number) - .as_u64() - .unwrap(); - let seeder_b = b - .seeders - .as_ref() - .unwrap_or(&default_number) - .as_u64() - .unwrap(); +-> Vec> { + vec![ + SortOption { + name: "Source", + cmp_fn: Some(|a, b| a.protocol.cmp(&b.protocol)), + }, + SortOption { + name: "Age", + cmp_fn: Some(|a, b| a.age.cmp(&b.age)), + }, + SortOption { + name: "Rejected", + cmp_fn: Some(|a, b| a.rejected.cmp(&b.rejected)), + }, + SortOption { + name: "Title", + cmp_fn: Some(|a, b| { + a.title + .text + .to_lowercase() + .cmp(&b.title.text.to_lowercase()) + }), + }, + SortOption { + name: "Indexer", + cmp_fn: Some(|a, b| a.indexer.to_lowercase().cmp(&b.indexer.to_lowercase())), + }, + SortOption { + name: "Size", + cmp_fn: Some(|a, b| a.size.cmp(&b.size)), + }, + SortOption { + name: "Peers", + cmp_fn: Some(|a, b| { + let default_number = Number::from(i64::MAX); + let seeder_a = a + .seeders + .as_ref() + .unwrap_or(&default_number) + .as_u64() + .unwrap(); + let seeder_b = b + .seeders + .as_ref() + .unwrap_or(&default_number) + .as_u64() + .unwrap(); - seeder_a.cmp(&seeder_b) - }), - }, - SortOption { - name: "Quality", - cmp_fn: Some(|a, b| a.quality.cmp(&b.quality)), - }, - ] + seeder_a.cmp(&seeder_b) + }), + }, + SortOption { + name: "Quality", + cmp_fn: Some(|a, b| a.quality.cmp(&b.quality)), + }, + ] } diff --git a/src/handlers/lidarr_handlers/library/album_details_handler_tests.rs b/src/handlers/lidarr_handlers/library/album_details_handler_tests.rs index 3d1b8ca..c56b6db 100644 --- a/src/handlers/lidarr_handlers/library/album_details_handler_tests.rs +++ b/src/handlers/lidarr_handlers/library/album_details_handler_tests.rs @@ -1,452 +1,446 @@ #[cfg(test)] mod tests { - use crate::app::App; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; - use crate::assert_modal_absent; - use crate::assert_navigation_pushed; - use crate::handlers::KeyEventHandler; - use crate::handlers::lidarr_handlers::library::album_details_handler::{ - AlbumDetailsHandler, releases_sorting_options, - }; - use crate::models::HorizontallyScrollableText; - use crate::models::servarr_data::lidarr::modals::AlbumDetailsModal; - use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, ALBUM_DETAILS_BLOCKS}; - use crate::models::servarr_models::{Quality, QualityWrapper}; - use crate::models::lidarr_models::{LidarrRelease, LidarrReleaseDownloadBody}; - use pretty_assertions::{assert_eq, assert_str_eq}; - use rstest::rstest; - use serde_json::Number; - use std::cmp::Ordering; - 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::handlers::KeyEventHandler; + use crate::handlers::lidarr_handlers::library::album_details_handler::{ + AlbumDetailsHandler, releases_sorting_options, + }; + use crate::models::HorizontallyScrollableText; + use crate::models::lidarr_models::{LidarrRelease, LidarrReleaseDownloadBody}; + use crate::models::servarr_data::lidarr::lidarr_data::{ALBUM_DETAILS_BLOCKS, ActiveLidarrBlock}; + use crate::models::servarr_data::lidarr::modals::AlbumDetailsModal; + use crate::models::servarr_models::{Quality, QualityWrapper}; + use pretty_assertions::{assert_eq, assert_str_eq}; + use rstest::rstest; + use serde_json::Number; + use std::cmp::Ordering; + use strum::IntoEnumIterator; - mod test_handle_delete { - use super::*; - use crate::event::Key; - use pretty_assertions::assert_eq; + mod test_handle_delete { + use super::*; + use crate::event::Key; + use pretty_assertions::assert_eq; - const DELETE_KEY: Key = DEFAULT_KEYBINDINGS.delete.key; + const DELETE_KEY: Key = DEFAULT_KEYBINDINGS.delete.key; - #[test] - fn test_delete_track_prompt() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + #[test] + fn test_delete_track_prompt() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - AlbumDetailsHandler::new(DELETE_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) - .handle(); + AlbumDetailsHandler::new(DELETE_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) + .handle(); - assert_navigation_pushed!(app, ActiveLidarrBlock::DeleteTrackFilePrompt.into()); - } + assert_navigation_pushed!(app, ActiveLidarrBlock::DeleteTrackFilePrompt.into()); + } - #[test] - fn test_delete_track_prompt_no_op_when_not_ready() { - let mut app = App::test_default(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - app.is_loading = true; + #[test] + fn test_delete_track_prompt_no_op_when_not_ready() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + app.is_loading = true; - AlbumDetailsHandler::new(DELETE_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) - .handle(); + AlbumDetailsHandler::new(DELETE_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) + .handle(); - assert_eq!( - app.get_current_route(), - ActiveLidarrBlock::AlbumDetails.into() - ); - } - } + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::AlbumDetails.into() + ); + } + } - mod test_handle_left_right_actions { - use super::*; - use crate::event::Key; - use pretty_assertions::assert_eq; - use rstest::rstest; + mod test_handle_left_right_actions { + use super::*; + use crate::event::Key; + use pretty_assertions::assert_eq; + use rstest::rstest; - #[rstest] - fn test_left_right_prompt_toggle( - #[values( - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, - ActiveLidarrBlock::DeleteTrackFilePrompt - )] - active_lidarr_block: ActiveLidarrBlock, - #[values(Key::Left, Key::Right)] key: Key, - ) { - let mut app = App::test_default(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + #[rstest] + fn test_left_right_prompt_toggle( + #[values( + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, + ActiveLidarrBlock::DeleteTrackFilePrompt + )] + active_lidarr_block: ActiveLidarrBlock, + #[values(Key::Left, Key::Right)] key: Key, + ) { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - AlbumDetailsHandler::new(key, &mut app, active_lidarr_block, None).handle(); + AlbumDetailsHandler::new(key, &mut app, active_lidarr_block, None).handle(); - assert!(app.data.lidarr_data.prompt_confirm); + assert!(app.data.lidarr_data.prompt_confirm); - AlbumDetailsHandler::new(key, &mut app, active_lidarr_block, None).handle(); + AlbumDetailsHandler::new(key, &mut app, active_lidarr_block, None).handle(); - assert!(!app.data.lidarr_data.prompt_confirm); - } + assert!(!app.data.lidarr_data.prompt_confirm); + } - #[rstest] - #[case(ActiveLidarrBlock::AlbumDetails, ActiveLidarrBlock::AlbumHistory)] - #[case( - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - #[case( - ActiveLidarrBlock::ManualAlbumSearch, - ActiveLidarrBlock::AlbumDetails - )] - fn test_album_details_tabs_left_right_action( - #[case] left_block: ActiveLidarrBlock, - #[case] right_block: ActiveLidarrBlock, - #[values(true, false)] is_ready: bool, - ) { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); - app.is_loading = is_ready; - app.push_navigation_stack(right_block.into()); - app - .data - .lidarr_data - .album_details_modal - .as_mut() - .unwrap() - .album_details_tabs - .index = app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_details_tabs - .tabs - .iter() - .position(|tab_route| tab_route.route == right_block.into()) - .unwrap_or_default(); + #[rstest] + #[case(ActiveLidarrBlock::AlbumDetails, ActiveLidarrBlock::AlbumHistory)] + #[case(ActiveLidarrBlock::AlbumHistory, ActiveLidarrBlock::ManualAlbumSearch)] + #[case(ActiveLidarrBlock::ManualAlbumSearch, ActiveLidarrBlock::AlbumDetails)] + fn test_album_details_tabs_left_right_action( + #[case] left_block: ActiveLidarrBlock, + #[case] right_block: ActiveLidarrBlock, + #[values(true, false)] is_ready: bool, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); + app.is_loading = is_ready; + app.push_navigation_stack(right_block.into()); + app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_details_tabs + .index = app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_details_tabs + .tabs + .iter() + .position(|tab_route| tab_route.route == right_block.into()) + .unwrap_or_default(); - AlbumDetailsHandler::new(DEFAULT_KEYBINDINGS.left.key, &mut app, right_block, None).handle(); + AlbumDetailsHandler::new(DEFAULT_KEYBINDINGS.left.key, &mut app, right_block, None).handle(); - assert_eq!( - app.get_current_route(), - app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_details_tabs - .get_active_route() - ); - assert_navigation_pushed!(app, left_block.into()); + assert_eq!( + app.get_current_route(), + app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_details_tabs + .get_active_route() + ); + assert_navigation_pushed!(app, left_block.into()); - AlbumDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle(); + AlbumDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle(); - assert_eq!( - app.get_current_route(), - app - .data - .lidarr_data - .album_details_modal - .as_ref() - .unwrap() - .album_details_tabs - .get_active_route() - ); - assert_navigation_pushed!(app, right_block.into()); - } - } + assert_eq!( + app.get_current_route(), + app + .data + .lidarr_data + .album_details_modal + .as_ref() + .unwrap() + .album_details_tabs + .get_active_route() + ); + assert_navigation_pushed!(app, right_block.into()); + } + } - mod test_handle_submit { - use super::*; - use crate::assert_navigation_popped; - use crate::event::Key; - use crate::models::stateful_table::StatefulTable; - use crate::network::lidarr_network::LidarrEvent; - use pretty_assertions::assert_eq; + mod test_handle_submit { + use super::*; + use crate::assert_navigation_popped; + use crate::event::Key; + use crate::models::stateful_table::StatefulTable; + use crate::network::lidarr_network::LidarrEvent; + use pretty_assertions::assert_eq; - const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; + const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; - // #[test] - // fn test_album_details_submit() { - // let mut app = App::test_default_fully_populated(); - // app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - // - // AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) - // .handle(); - // - // assert_navigation_pushed!(app, ActiveLidarrBlock::TrackDetails.into()); - // } + // #[test] + // fn test_album_details_submit() { + // let mut app = App::test_default_fully_populated(); + // app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + // + // AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) + // .handle(); + // + // assert_navigation_pushed!(app, ActiveLidarrBlock::TrackDetails.into()); + // } - // #[test] - // fn test_album_details_submit_no_op_on_empty_tracks_table() { - // let mut app = App::test_default_fully_populated(); - // app - // .data - // .lidarr_data - // .album_details_modal - // .as_mut() - // .unwrap() - // .tracks = StatefulTable::default(); - // app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - // - // AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) - // .handle(); - // - // assert_eq!( - // app.get_current_route(), - // ActiveLidarrBlock::AlbumDetails.into() - // ); - // } + // #[test] + // fn test_album_details_submit_no_op_on_empty_tracks_table() { + // let mut app = App::test_default_fully_populated(); + // app + // .data + // .lidarr_data + // .album_details_modal + // .as_mut() + // .unwrap() + // .tracks = StatefulTable::default(); + // app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + // + // AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) + // .handle(); + // + // assert_eq!( + // app.get_current_route(), + // ActiveLidarrBlock::AlbumDetails.into() + // ); + // } - #[test] - fn test_album_details_submit_no_op_when_not_ready() { - let mut app = App::test_default(); - app.is_loading = true; - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + #[test] + fn test_album_details_submit_no_op_when_not_ready() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) - .handle(); + AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumDetails, None) + .handle(); - assert_eq!( - app.get_current_route(), - ActiveLidarrBlock::AlbumDetails.into() - ); - } + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::AlbumDetails.into() + ); + } - #[test] - fn test_album_history_submit() { - let mut app = App::test_default_fully_populated(); + #[test] + fn test_album_history_submit() { + let mut app = App::test_default_fully_populated(); - AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None) - .handle(); + AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None) + .handle(); - assert_navigation_pushed!(app, ActiveLidarrBlock::AlbumHistoryDetails.into()); - } + assert_navigation_pushed!(app, ActiveLidarrBlock::AlbumHistoryDetails.into()); + } - #[test] - fn test_album_history_submit_no_op_when_album_history_is_empty() { - let mut app = App::test_default_fully_populated(); - app - .data - .lidarr_data - .album_details_modal - .as_mut() - .unwrap() - .album_history = StatefulTable::default(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); + #[test] + fn test_album_history_submit_no_op_when_album_history_is_empty() { + let mut app = App::test_default_fully_populated(); + app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_history = StatefulTable::default(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); - AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None) - .handle(); + AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None) + .handle(); - assert_eq!( - app.get_current_route(), - ActiveLidarrBlock::AlbumHistory.into() - ); - } + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::AlbumHistory.into() + ); + } - #[test] - fn test_album_history_submit_no_op_when_not_ready() { - let mut app = App::test_default_fully_populated(); - app.is_loading = true; - app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); + #[test] + fn test_album_history_submit_no_op_when_not_ready() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); - AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None) - .handle(); + AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None) + .handle(); - assert_eq!( - app.get_current_route(), - ActiveLidarrBlock::AlbumHistory.into() - ); - } + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::AlbumHistory.into() + ); + } - #[rstest] - #[case( - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, - LidarrEvent::TriggerAutomaticAlbumSearch(1) - )] - #[case( - ActiveLidarrBlock::DeleteTrackFilePrompt, - LidarrEvent::DeleteTrackFile(1) - )] - fn test_album_details_prompt_confirm_submit( - #[case] prompt_block: ActiveLidarrBlock, - #[case] expected_action: LidarrEvent, - #[values(ActiveLidarrBlock::AlbumDetails, ActiveLidarrBlock::AlbumHistory)] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.data.lidarr_data.prompt_confirm = true; - app.push_navigation_stack(active_lidarr_block.into()); - app.push_navigation_stack(prompt_block.into()); + #[rstest] + #[case( + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, + LidarrEvent::TriggerAutomaticAlbumSearch(1) + )] + #[case( + ActiveLidarrBlock::DeleteTrackFilePrompt, + LidarrEvent::DeleteTrackFile(1) + )] + fn test_album_details_prompt_confirm_submit( + #[case] prompt_block: ActiveLidarrBlock, + #[case] expected_action: LidarrEvent, + #[values(ActiveLidarrBlock::AlbumDetails, ActiveLidarrBlock::AlbumHistory)] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.data.lidarr_data.prompt_confirm = true; + app.push_navigation_stack(active_lidarr_block.into()); + app.push_navigation_stack(prompt_block.into()); - AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); + AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); - assert!(app.data.lidarr_data.prompt_confirm); - assert_navigation_popped!(app, active_lidarr_block.into()); - assert_some_eq_x!( + assert!(app.data.lidarr_data.prompt_confirm); + assert_navigation_popped!(app, active_lidarr_block.into()); + assert_some_eq_x!( &app.data.lidarr_data.prompt_confirm_action, &expected_action ); - } + } - #[test] - fn test_album_details_manual_search_confirm_prompt_confirm_submit() { - let mut app = App::test_default_fully_populated(); - app.data.lidarr_data.prompt_confirm = true; - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into()); + #[test] + fn test_album_details_manual_search_confirm_prompt_confirm_submit() { + let mut app = App::test_default_fully_populated(); + app.data.lidarr_data.prompt_confirm = true; + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into()); - AlbumDetailsHandler::new( - SUBMIT_KEY, - &mut app, - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, - None, - ) - .handle(); + AlbumDetailsHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, + None, + ) + .handle(); - assert!(app.data.lidarr_data.prompt_confirm); - assert_navigation_popped!(app, ActiveLidarrBlock::ManualAlbumSearch.into()); - assert_some_eq_x!( + assert!(app.data.lidarr_data.prompt_confirm); + assert_navigation_popped!(app, ActiveLidarrBlock::ManualAlbumSearch.into()); + assert_some_eq_x!( &app.data.lidarr_data.prompt_confirm_action, &LidarrEvent::DownloadRelease(LidarrReleaseDownloadBody { guid: "1234".to_owned(), indexer_id: 2, }) ); - } + } - #[rstest] - fn test_album_details_prompt_decline_submit( - #[values( - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, - ActiveLidarrBlock::DeleteTrackFilePrompt, - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt - )] - prompt_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - app.push_navigation_stack(prompt_block.into()); + #[rstest] + fn test_album_details_prompt_decline_submit( + #[values( + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, + ActiveLidarrBlock::DeleteTrackFilePrompt, + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt + )] + prompt_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + app.push_navigation_stack(prompt_block.into()); - AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); + AlbumDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_navigation_popped!(app, ActiveLidarrBlock::AlbumDetails.into()); - assert_none!(app.data.lidarr_data.prompt_confirm_action); - } + assert!(!app.data.lidarr_data.prompt_confirm); + assert_navigation_popped!(app, ActiveLidarrBlock::AlbumDetails.into()); + assert_none!(app.data.lidarr_data.prompt_confirm_action); + } - #[test] - fn test_manual_album_search_submit() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); + #[test] + fn test_manual_album_search_submit() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); - AlbumDetailsHandler::new( - SUBMIT_KEY, - &mut app, - ActiveLidarrBlock::ManualAlbumSearch, - None, - ) - .handle(); + AlbumDetailsHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::ManualAlbumSearch, + None, + ) + .handle(); - assert_navigation_pushed!( + assert_navigation_pushed!( app, ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into() ); - } + } - #[test] - fn test_manual_album_search_submit_no_op_when_not_ready() { - let mut app = App::test_default_fully_populated(); - app.is_loading = true; - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); + #[test] + fn test_manual_album_search_submit_no_op_when_not_ready() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); - AlbumDetailsHandler::new( - SUBMIT_KEY, - &mut app, - ActiveLidarrBlock::ManualAlbumSearch, - None, - ) - .handle(); + AlbumDetailsHandler::new( + SUBMIT_KEY, + &mut app, + ActiveLidarrBlock::ManualAlbumSearch, + None, + ) + .handle(); - assert_eq!( - app.get_current_route(), - ActiveLidarrBlock::ManualAlbumSearch.into() - ); - } - } + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::ManualAlbumSearch.into() + ); + } + } - mod test_handle_esc { - use super::*; - use crate::assert_navigation_popped; - use crate::event::Key; - use crate::models::lidarr_models::LidarrHistoryItem; - use crate::models::stateful_table::StatefulTable; - use pretty_assertions::assert_eq; - use ratatui::widgets::TableState; + mod test_handle_esc { + use super::*; + use crate::assert_navigation_popped; + use crate::event::Key; + use crate::models::lidarr_models::LidarrHistoryItem; + use crate::models::stateful_table::StatefulTable; + use pretty_assertions::assert_eq; + use ratatui::widgets::TableState; - const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; + const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; - #[test] - fn test_album_history_details_block_esc() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); - app.push_navigation_stack(ActiveLidarrBlock::AlbumHistoryDetails.into()); + #[test] + fn test_album_history_details_block_esc() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); + app.push_navigation_stack(ActiveLidarrBlock::AlbumHistoryDetails.into()); - AlbumDetailsHandler::new( - ESC_KEY, - &mut app, - ActiveLidarrBlock::AlbumHistoryDetails, - None, - ) - .handle(); + AlbumDetailsHandler::new( + ESC_KEY, + &mut app, + ActiveLidarrBlock::AlbumHistoryDetails, + None, + ) + .handle(); - assert_navigation_popped!(app, ActiveLidarrBlock::AlbumHistory.into()); - } + assert_navigation_popped!(app, ActiveLidarrBlock::AlbumHistory.into()); + } - #[rstest] - fn test_album_details_prompts_esc( - #[values( - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, - ActiveLidarrBlock::DeleteTrackFilePrompt, - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt - )] - prompt_block: ActiveLidarrBlock, - #[values(true, false)] is_ready: bool, - ) { - let mut app = App::test_default_fully_populated(); - app.is_loading = is_ready; - app.data.lidarr_data.prompt_confirm = true; - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - app.push_navigation_stack(prompt_block.into()); + #[rstest] + fn test_album_details_prompts_esc( + #[values( + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, + ActiveLidarrBlock::DeleteTrackFilePrompt, + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt + )] + prompt_block: ActiveLidarrBlock, + #[values(true, false)] is_ready: bool, + ) { + let mut app = App::test_default_fully_populated(); + app.is_loading = is_ready; + app.data.lidarr_data.prompt_confirm = true; + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + app.push_navigation_stack(prompt_block.into()); - AlbumDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); + AlbumDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); - assert!(!app.data.lidarr_data.prompt_confirm); - assert_navigation_popped!(app, ActiveLidarrBlock::AlbumDetails.into()); - } + assert!(!app.data.lidarr_data.prompt_confirm); + assert_navigation_popped!(app, ActiveLidarrBlock::AlbumDetails.into()); + } - #[test] - fn test_album_history_esc_resets_filter_if_one_is_set_instead_of_closing_the_window() { - let mut app = App::test_default_fully_populated(); - let mut album_history = StatefulTable { - filter: Some("Test".into()), - filtered_items: Some(vec![LidarrHistoryItem::default()]), - filtered_state: Some(TableState::default()), - ..StatefulTable::default() - }; - album_history.set_items(vec![LidarrHistoryItem::default()]); - app - .data - .lidarr_data - .album_details_modal - .as_mut() - .unwrap() - .album_history = album_history; - app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); - app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); + #[test] + fn test_album_history_esc_resets_filter_if_one_is_set_instead_of_closing_the_window() { + let mut app = App::test_default_fully_populated(); + let mut album_history = StatefulTable { + filter: Some("Test".into()), + filtered_items: Some(vec![LidarrHistoryItem::default()]), + filtered_state: Some(TableState::default()), + ..StatefulTable::default() + }; + album_history.set_items(vec![LidarrHistoryItem::default()]); + app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_history = album_history; + app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); + app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); - AlbumDetailsHandler::new(ESC_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None).handle(); + AlbumDetailsHandler::new(ESC_KEY, &mut app, ActiveLidarrBlock::AlbumHistory, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveLidarrBlock::AlbumHistory.into() - ); - assert_none!( + assert_eq!( + app.get_current_route(), + ActiveLidarrBlock::AlbumHistory.into() + ); + assert_none!( app .data .lidarr_data @@ -456,7 +450,7 @@ mod tests { .album_history .filter ); - assert_none!( + assert_none!( app .data .lidarr_data @@ -466,7 +460,7 @@ mod tests { .album_history .filtered_items ); - assert_none!( + assert_none!( app .data .lidarr_data @@ -476,559 +470,559 @@ mod tests { .album_history .filtered_state ); - } + } - #[rstest] - fn test_album_details_tabs_esc( - #[values( - ActiveLidarrBlock::AlbumDetails, - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); - app.push_navigation_stack(active_lidarr_block.into()); + #[rstest] + fn test_album_details_tabs_esc( + #[values( + ActiveLidarrBlock::AlbumDetails, + ActiveLidarrBlock::AlbumHistory, + ActiveLidarrBlock::ManualAlbumSearch + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); + app.push_navigation_stack(active_lidarr_block.into()); - AlbumDetailsHandler::new(ESC_KEY, &mut app, active_lidarr_block, None).handle(); + AlbumDetailsHandler::new(ESC_KEY, &mut app, active_lidarr_block, None).handle(); - assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into()); - assert_modal_absent!(app.data.lidarr_data.album_details_modal); - } - } + assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into()); + assert_modal_absent!(app.data.lidarr_data.album_details_modal); + } + } - mod test_handle_key_char { - use super::*; - use crate::assert_navigation_popped; - use crate::network::lidarr_network::LidarrEvent; - use pretty_assertions::assert_eq; + mod test_handle_key_char { + use super::*; + use crate::assert_navigation_popped; + use crate::network::lidarr_network::LidarrEvent; + use pretty_assertions::assert_eq; - #[rstest] - fn test_auto_search_key( - #[values( - ActiveLidarrBlock::AlbumDetails, - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(active_lidarr_block.into()); + #[rstest] + fn test_auto_search_key( + #[values( + ActiveLidarrBlock::AlbumDetails, + ActiveLidarrBlock::AlbumHistory, + ActiveLidarrBlock::ManualAlbumSearch + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_lidarr_block.into()); - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.auto_search.key, - &mut app, - active_lidarr_block, - None, - ) - .handle(); + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.auto_search.key, + &mut app, + active_lidarr_block, + None, + ) + .handle(); - assert_navigation_pushed!( + assert_navigation_pushed!( app, ActiveLidarrBlock::AutomaticallySearchAlbumPrompt.into() ); - } + } - #[rstest] - fn test_auto_search_key_no_op_when_not_ready( - #[values( - ActiveLidarrBlock::AlbumDetails, - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default(); - app.is_loading = true; - app.push_navigation_stack(active_lidarr_block.into()); + #[rstest] + fn test_auto_search_key_no_op_when_not_ready( + #[values( + ActiveLidarrBlock::AlbumDetails, + ActiveLidarrBlock::AlbumHistory, + ActiveLidarrBlock::ManualAlbumSearch + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(active_lidarr_block.into()); - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.auto_search.key, - &mut app, - active_lidarr_block, - None, - ) - .handle(); + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.auto_search.key, + &mut app, + active_lidarr_block, + None, + ) + .handle(); - assert_eq!(app.get_current_route(), active_lidarr_block.into()); - } + assert_eq!(app.get_current_route(), active_lidarr_block.into()); + } - #[rstest] - fn test_refresh_key( - #[values( - ActiveLidarrBlock::AlbumDetails, - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(active_lidarr_block.into()); - app.is_routing = false; + #[rstest] + fn test_refresh_key( + #[values( + ActiveLidarrBlock::AlbumDetails, + ActiveLidarrBlock::AlbumHistory, + ActiveLidarrBlock::ManualAlbumSearch + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_lidarr_block.into()); + app.is_routing = false; - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.refresh.key, - &mut app, - active_lidarr_block, - None, - ) - .handle(); + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.refresh.key, + &mut app, + active_lidarr_block, + None, + ) + .handle(); - assert_navigation_pushed!(app, active_lidarr_block.into()); - assert!(app.is_routing); - } + assert_navigation_pushed!(app, active_lidarr_block.into()); + assert!(app.is_routing); + } - #[rstest] - fn test_refresh_key_no_op_when_not_ready( - #[values( - ActiveLidarrBlock::AlbumDetails, - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.is_loading = true; - app.push_navigation_stack(active_lidarr_block.into()); - app.is_routing = false; + #[rstest] + fn test_refresh_key_no_op_when_not_ready( + #[values( + ActiveLidarrBlock::AlbumDetails, + ActiveLidarrBlock::AlbumHistory, + ActiveLidarrBlock::ManualAlbumSearch + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(active_lidarr_block.into()); + app.is_routing = false; - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.refresh.key, - &mut app, - active_lidarr_block, - None, - ) - .handle(); + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.refresh.key, + &mut app, + active_lidarr_block, + None, + ) + .handle(); - assert_eq!(app.get_current_route(), active_lidarr_block.into()); - assert!(!app.is_routing); - } + assert_eq!(app.get_current_route(), active_lidarr_block.into()); + assert!(!app.is_routing); + } - #[rstest] - #[case( - ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, - LidarrEvent::TriggerAutomaticAlbumSearch(1) - )] - #[case( - ActiveLidarrBlock::DeleteTrackFilePrompt, - LidarrEvent::DeleteTrackFile(1) - )] - fn test_album_details_prompt_confirm_confirm_key( - #[case] prompt_block: ActiveLidarrBlock, - #[case] expected_action: LidarrEvent, - #[values(ActiveLidarrBlock::AlbumDetails, ActiveLidarrBlock::AlbumHistory)] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.data.lidarr_data.prompt_confirm = true; - app.push_navigation_stack(active_lidarr_block.into()); - app.push_navigation_stack(prompt_block.into()); + #[rstest] + #[case( + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, + LidarrEvent::TriggerAutomaticAlbumSearch(1) + )] + #[case( + ActiveLidarrBlock::DeleteTrackFilePrompt, + LidarrEvent::DeleteTrackFile(1) + )] + fn test_album_details_prompt_confirm_confirm_key( + #[case] prompt_block: ActiveLidarrBlock, + #[case] expected_action: LidarrEvent, + #[values(ActiveLidarrBlock::AlbumDetails, ActiveLidarrBlock::AlbumHistory)] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.data.lidarr_data.prompt_confirm = true; + app.push_navigation_stack(active_lidarr_block.into()); + app.push_navigation_stack(prompt_block.into()); - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.confirm.key, - &mut app, - prompt_block, - None, - ) - .handle(); + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.confirm.key, + &mut app, + prompt_block, + None, + ) + .handle(); - assert!(app.data.lidarr_data.prompt_confirm); - assert_navigation_popped!(app, active_lidarr_block.into()); - assert_some_eq_x!( + assert!(app.data.lidarr_data.prompt_confirm); + assert_navigation_popped!(app, active_lidarr_block.into()); + assert_some_eq_x!( &app.data.lidarr_data.prompt_confirm_action, &expected_action ); - } + } - #[test] - fn test_album_details_manual_search_confirm_prompt_confirm_confirm_key() { - let mut app = App::test_default_fully_populated(); - app.data.lidarr_data.prompt_confirm = true; - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into()); + #[test] + fn test_album_details_manual_search_confirm_prompt_confirm_confirm_key() { + let mut app = App::test_default_fully_populated(); + app.data.lidarr_data.prompt_confirm = true; + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt.into()); - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.confirm.key, - &mut app, - ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, - None, - ) - .handle(); + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.confirm.key, + &mut app, + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, + None, + ) + .handle(); - assert!(app.data.lidarr_data.prompt_confirm); - assert_navigation_popped!(app, ActiveLidarrBlock::ManualAlbumSearch.into()); - assert_some_eq_x!( + assert!(app.data.lidarr_data.prompt_confirm); + assert_navigation_popped!(app, ActiveLidarrBlock::ManualAlbumSearch.into()); + assert_some_eq_x!( &app.data.lidarr_data.prompt_confirm_action, &LidarrEvent::DownloadRelease(LidarrReleaseDownloadBody { guid: "1234".to_owned(), indexer_id: 2, }) ); - } - } + } + } - #[test] - fn test_album_details_handler_accepts() { - ActiveLidarrBlock::iter().for_each(|active_lidarr_block| { - if ALBUM_DETAILS_BLOCKS.contains(&active_lidarr_block) { - assert!(AlbumDetailsHandler::accepts(active_lidarr_block)); - } else { - assert!(!AlbumDetailsHandler::accepts(active_lidarr_block)); - } - }); - } + #[test] + fn test_album_details_handler_accepts() { + ActiveLidarrBlock::iter().for_each(|active_lidarr_block| { + if ALBUM_DETAILS_BLOCKS.contains(&active_lidarr_block) { + assert!(AlbumDetailsHandler::accepts(active_lidarr_block)); + } else { + assert!(!AlbumDetailsHandler::accepts(active_lidarr_block)); + } + }); + } - #[rstest] - fn test_album_details_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 = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::default(), - None, - ); + #[rstest] + fn test_album_details_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 = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::default(), + None, + ); - assert_eq!( - handler.ignore_special_keys(), - ignore_special_keys_for_textbox_input - ); - } + assert_eq!( + handler.ignore_special_keys(), + ignore_special_keys_for_textbox_input + ); + } - #[test] - fn test_extract_track_file_id() { - let mut app = App::test_default_fully_populated(); + #[test] + fn test_extract_track_file_id() { + let mut app = App::test_default_fully_populated(); - let track_file_id = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumDetails, - None, - ) - .extract_track_file_id(); + let track_file_id = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumDetails, + None, + ) + .extract_track_file_id(); - assert_eq!(track_file_id, 1); - } + assert_eq!(track_file_id, 1); + } - #[test] - #[should_panic(expected = "Album details have not been loaded")] - fn test_extract_track_file_id_empty_album_details_modal_panics() { - let mut app = App::test_default(); + #[test] + #[should_panic(expected = "Album details have not been loaded")] + fn test_extract_track_file_id_empty_album_details_modal_panics() { + let mut app = App::test_default(); - AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumDetails, - None, - ) - .extract_track_file_id(); - } + AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumDetails, + None, + ) + .extract_track_file_id(); + } - #[test] - fn test_extract_album_id() { - let mut app = App::test_default_fully_populated(); + #[test] + fn test_extract_album_id() { + let mut app = App::test_default_fully_populated(); - let track_file_id = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumDetails, - None, - ) - .extract_album_id(); + let track_file_id = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumDetails, + None, + ) + .extract_album_id(); - assert_eq!(track_file_id, 1); - } + assert_eq!(track_file_id, 1); + } - #[test] - fn test_album_details_handler_is_not_ready_when_loading() { - let mut app = App::test_default(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - app.is_loading = true; + #[test] + fn test_album_details_handler_is_not_ready_when_loading() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + app.is_loading = true; - let handler = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumDetails, - None, - ); + let handler = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumDetails, + None, + ); - assert!(!handler.is_ready()); - } + assert!(!handler.is_ready()); + } - #[test] - fn test_album_details_handler_is_not_ready_when_not_loading_and_album_details_is_none() { - let mut app = App::test_default(); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + #[test] + fn test_album_details_handler_is_not_ready_when_not_loading_and_album_details_is_none() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - let handler = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumDetails, - None, - ); + let handler = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumDetails, + None, + ); - assert!(!handler.is_ready()); - } + assert!(!handler.is_ready()); + } - #[test] - fn test_album_details_handler_is_not_ready_when_not_loading_and_tracks_table_is_empty() { - let mut app = App::test_default(); - app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); - app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); + #[test] + fn test_album_details_handler_is_not_ready_when_not_loading_and_tracks_table_is_empty() { + let mut app = App::test_default(); + app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::AlbumDetails.into()); - let handler = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumDetails, - None, - ); + let handler = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumDetails, + None, + ); - assert!(!handler.is_ready()); - } + assert!(!handler.is_ready()); + } - #[test] - fn test_album_details_handler_is_not_ready_when_not_loading_and_history_table_is_empty() { - let mut app = App::test_default(); - app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); - app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); + #[test] + fn test_album_details_handler_is_not_ready_when_not_loading_and_history_table_is_empty() { + let mut app = App::test_default(); + app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::AlbumHistory.into()); - let handler = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::AlbumHistory, - None, - ); + let handler = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::AlbumHistory, + None, + ); - assert!(!handler.is_ready()); - } + assert!(!handler.is_ready()); + } - #[test] - fn test_album_details_handler_is_not_ready_when_not_loading_and_releases_table_is_empty() { - let mut app = App::test_default(); - app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); - app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); + #[test] + fn test_album_details_handler_is_not_ready_when_not_loading_and_releases_table_is_empty() { + let mut app = App::test_default(); + app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default()); + app.push_navigation_stack(ActiveLidarrBlock::ManualAlbumSearch.into()); - let handler = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - ActiveLidarrBlock::ManualAlbumSearch, - None, - ); + let handler = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveLidarrBlock::ManualAlbumSearch, + None, + ); - assert!(!handler.is_ready()); - } + assert!(!handler.is_ready()); + } - #[rstest] - fn test_album_details_handler_is_ready_when_not_loading_and_album_details_modal_is_populated( - #[values( - ActiveLidarrBlock::AlbumDetails, - ActiveLidarrBlock::AlbumHistory, - ActiveLidarrBlock::ManualAlbumSearch - )] - active_lidarr_block: ActiveLidarrBlock, - ) { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); - app.push_navigation_stack(active_lidarr_block.into()); + #[rstest] + fn test_album_details_handler_is_ready_when_not_loading_and_album_details_modal_is_populated( + #[values( + ActiveLidarrBlock::AlbumDetails, + ActiveLidarrBlock::AlbumHistory, + ActiveLidarrBlock::ManualAlbumSearch + )] + active_lidarr_block: ActiveLidarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into()); + app.push_navigation_stack(active_lidarr_block.into()); - let handler = AlbumDetailsHandler::new( - DEFAULT_KEYBINDINGS.esc.key, - &mut app, - active_lidarr_block, - None, - ); + let handler = AlbumDetailsHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + active_lidarr_block, + None, + ); - assert!(handler.is_ready()); - } + assert!(handler.is_ready()); + } - #[test] - fn test_releases_sorting_options_source() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = - |a, b| a.protocol.cmp(&b.protocol); - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_source() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = + |a, b| a.protocol.cmp(&b.protocol); + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[0].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[0].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Source"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Source"); + } - #[test] - fn test_releases_sorting_options_age() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = |a, b| a.age.cmp(&b.age); - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_age() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = |a, b| a.age.cmp(&b.age); + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[1].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[1].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Age"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Age"); + } - #[test] - fn test_releases_sorting_options_rejected() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = - |a, b| a.rejected.cmp(&b.rejected); - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_rejected() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = + |a, b| a.rejected.cmp(&b.rejected); + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[2].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[2].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Rejected"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Rejected"); + } - #[test] - fn test_releases_sorting_options_title() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = |a, b| { - a.title - .text - .to_lowercase() - .cmp(&b.title.text.to_lowercase()) - }; - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_title() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = |a, b| { + a.title + .text + .to_lowercase() + .cmp(&b.title.text.to_lowercase()) + }; + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[3].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[3].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Title"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Title"); + } - #[test] - fn test_releases_sorting_options_indexer() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = - |a, b| a.indexer.to_lowercase().cmp(&b.indexer.to_lowercase()); - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_indexer() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = + |a, b| a.indexer.to_lowercase().cmp(&b.indexer.to_lowercase()); + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[4].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[4].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Indexer"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Indexer"); + } - #[test] - fn test_releases_sorting_options_size() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = - |a, b| a.size.cmp(&b.size); - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_size() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = + |a, b| a.size.cmp(&b.size); + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[5].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[5].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Size"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Size"); + } - #[test] - fn test_releases_sorting_options_peers() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = |a, b| { - let default_number = Number::from(i64::MAX); - let seeder_a = a - .seeders - .as_ref() - .unwrap_or(&default_number) - .as_u64() - .unwrap(); - let seeder_b = b - .seeders - .as_ref() - .unwrap_or(&default_number) - .as_u64() - .unwrap(); + #[test] + fn test_releases_sorting_options_peers() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = |a, b| { + let default_number = Number::from(i64::MAX); + let seeder_a = a + .seeders + .as_ref() + .unwrap_or(&default_number) + .as_u64() + .unwrap(); + let seeder_b = b + .seeders + .as_ref() + .unwrap_or(&default_number) + .as_u64() + .unwrap(); - seeder_a.cmp(&seeder_b) - }; - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + seeder_a.cmp(&seeder_b) + }; + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[6].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[6].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Peers"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Peers"); + } - #[test] - fn test_releases_sorting_options_quality() { - let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = - |a, b| a.quality.cmp(&b.quality); - let mut expected_releases_vec = release_vec(); - expected_releases_vec.sort_by(expected_cmp_fn); + #[test] + fn test_releases_sorting_options_quality() { + let expected_cmp_fn: fn(&LidarrRelease, &LidarrRelease) -> Ordering = + |a, b| a.quality.cmp(&b.quality); + let mut expected_releases_vec = release_vec(); + expected_releases_vec.sort_by(expected_cmp_fn); - let sort_option = releases_sorting_options()[7].clone(); - let mut sorted_releases_vec = release_vec(); - sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); + let sort_option = releases_sorting_options()[7].clone(); + let mut sorted_releases_vec = release_vec(); + sorted_releases_vec.sort_by(sort_option.cmp_fn.unwrap()); - assert_eq!(sorted_releases_vec, expected_releases_vec); - assert_str_eq!(sort_option.name, "Quality"); - } + assert_eq!(sorted_releases_vec, expected_releases_vec); + assert_str_eq!(sort_option.name, "Quality"); + } - fn release_vec() -> Vec { - let release_a = LidarrRelease { - protocol: "Protocol A".to_owned(), - age: 1, - title: HorizontallyScrollableText::from("Title A"), - indexer: "Indexer A".to_owned(), - size: 1, - rejected: true, - seeders: Some(Number::from(1)), - quality: QualityWrapper { - quality: Quality { - name: "Quality A".to_owned(), - }, - }, - ..LidarrRelease::default() - }; - let release_b = LidarrRelease { - protocol: "Protocol B".to_owned(), - age: 2, - title: HorizontallyScrollableText::from("title B"), - indexer: "indexer B".to_owned(), - size: 2, - rejected: false, - seeders: Some(Number::from(2)), - quality: QualityWrapper { - quality: Quality { - name: "Quality B".to_owned(), - }, - }, - ..LidarrRelease::default() - }; - let release_c = LidarrRelease { - protocol: "Protocol C".to_owned(), - age: 3, - title: HorizontallyScrollableText::from("Title C"), - indexer: "Indexer C".to_owned(), - size: 3, - rejected: false, - seeders: None, - quality: QualityWrapper { - quality: Quality { - name: "Quality C".to_owned(), - }, - }, - ..LidarrRelease::default() - }; + fn release_vec() -> Vec { + let release_a = LidarrRelease { + protocol: "Protocol A".to_owned(), + age: 1, + title: HorizontallyScrollableText::from("Title A"), + indexer: "Indexer A".to_owned(), + size: 1, + rejected: true, + seeders: Some(Number::from(1)), + quality: QualityWrapper { + quality: Quality { + name: "Quality A".to_owned(), + }, + }, + ..LidarrRelease::default() + }; + let release_b = LidarrRelease { + protocol: "Protocol B".to_owned(), + age: 2, + title: HorizontallyScrollableText::from("title B"), + indexer: "indexer B".to_owned(), + size: 2, + rejected: false, + seeders: Some(Number::from(2)), + quality: QualityWrapper { + quality: Quality { + name: "Quality B".to_owned(), + }, + }, + ..LidarrRelease::default() + }; + let release_c = LidarrRelease { + protocol: "Protocol C".to_owned(), + age: 3, + title: HorizontallyScrollableText::from("Title C"), + indexer: "Indexer C".to_owned(), + size: 3, + rejected: false, + seeders: None, + quality: QualityWrapper { + quality: Quality { + name: "Quality C".to_owned(), + }, + }, + ..LidarrRelease::default() + }; - vec![release_a, release_b, release_c] - } + vec![release_a, release_b, release_c] + } } diff --git a/src/handlers/lidarr_handlers/library/artist_details_handler.rs b/src/handlers/lidarr_handlers/library/artist_details_handler.rs index 37c909b..7efe05f 100644 --- a/src/handlers/lidarr_handlers/library/artist_details_handler.rs +++ b/src/handlers/lidarr_handlers/library/artist_details_handler.rs @@ -1,6 +1,7 @@ use crate::app::App; use crate::event::Key; use crate::handlers::lidarr_handlers::history::history_sorting_options; +use crate::handlers::lidarr_handlers::library::album_details_handler::AlbumDetailsHandler; use crate::handlers::lidarr_handlers::library::delete_album_handler::DeleteAlbumHandler; use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; @@ -16,7 +17,6 @@ use crate::models::stateful_table::SortOption; use crate::models::{BlockSelectionState, Route}; use crate::network::lidarr_network::LidarrEvent; use serde_json::Number; -use crate::handlers::lidarr_handlers::library::album_details_handler::AlbumDetailsHandler; #[cfg(test)] #[path = "artist_details_handler_tests.rs"] @@ -91,7 +91,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for ArtistDetailsHandler } fn accepts(active_block: ActiveLidarrBlock) -> bool { - DeleteAlbumHandler::accepts(active_block) || AlbumDetailsHandler::accepts(active_block) || ARTIST_DETAILS_BLOCKS.contains(&active_block) + DeleteAlbumHandler::accepts(active_block) + || AlbumDetailsHandler::accepts(active_block) + || ARTIST_DETAILS_BLOCKS.contains(&active_block) } fn ignore_special_keys(&self) -> bool { diff --git a/src/handlers/lidarr_handlers/library/artist_details_handler_tests.rs b/src/handlers/lidarr_handlers/library/artist_details_handler_tests.rs index b130db0..ad08d7b 100644 --- a/src/handlers/lidarr_handlers/library/artist_details_handler_tests.rs +++ b/src/handlers/lidarr_handlers/library/artist_details_handler_tests.rs @@ -14,11 +14,13 @@ mod tests { }; use crate::models::HorizontallyScrollableText; use crate::models::lidarr_models::{Album, LidarrHistoryItem, LidarrRelease}; - use crate::models::servarr_data::lidarr::lidarr_data::{ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, ALBUM_DETAILS_BLOCKS}; + use crate::models::servarr_data::lidarr::lidarr_data::{ + ALBUM_DETAILS_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, + }; use crate::models::servarr_models::{Quality, QualityWrapper}; - use crate::test_handler_delegation; + use crate::test_handler_delegation; - mod test_handle_delete { + mod test_handle_delete { use super::*; use crate::assert_delete_prompt; use crate::event::Key; diff --git a/src/handlers/lidarr_handlers/library/library_handler_tests.rs b/src/handlers/lidarr_handlers/library/library_handler_tests.rs index 89f2bdf..5d81f22 100644 --- a/src/handlers/lidarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/lidarr_handlers/library/library_handler_tests.rs @@ -12,10 +12,17 @@ mod tests { use crate::handlers::KeyEventHandler; use crate::handlers::lidarr_handlers::library::{LibraryHandler, artists_sorting_options}; use crate::models::lidarr_models::{Album, Artist, ArtistStatistics, ArtistStatus}; - use crate::models::servarr_data::lidarr::lidarr_data::{ADD_ARTIST_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, LIBRARY_BLOCKS, ALBUM_DETAILS_BLOCKS}; + use crate::models::servarr_data::lidarr::lidarr_data::{ + ADD_ARTIST_BLOCKS, ALBUM_DETAILS_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, + DELETE_ALBUM_BLOCKS, 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_modal_present, assert_navigation_popped, assert_navigation_pushed, test_handler_delegation}; + use crate::{ + assert_modal_absent, assert_modal_present, assert_navigation_popped, assert_navigation_pushed, + test_handler_delegation, + }; #[test] fn test_library_handler_accepts() { diff --git a/src/handlers/lidarr_handlers/library/mod.rs b/src/handlers/lidarr_handlers/library/mod.rs index 68a6c9c..dae1c06 100644 --- a/src/handlers/lidarr_handlers/library/mod.rs +++ b/src/handlers/lidarr_handlers/library/mod.rs @@ -1,22 +1,22 @@ use crate::{ - app::App, - event::Key, - handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}, - matches_key, - models::{ - lidarr_models::Artist, servarr_data::lidarr::lidarr_data::{ - ActiveLidarrBlock, DELETE_ARTIST_SELECTION_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, - LIBRARY_BLOCKS, - }, - stateful_table::SortOption, - BlockSelectionState, - HorizontallyScrollableText, - }, - network::lidarr_network::LidarrEvent, + app::App, + event::Key, + handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}, + matches_key, + models::{ + BlockSelectionState, HorizontallyScrollableText, + lidarr_models::Artist, + servarr_data::lidarr::lidarr_data::{ + ActiveLidarrBlock, DELETE_ARTIST_SELECTION_BLOCKS, EDIT_ARTIST_SELECTION_BLOCKS, + LIBRARY_BLOCKS, + }, + stateful_table::SortOption, + }, + network::lidarr_network::LidarrEvent, }; use super::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::{handle_table, TableHandlingConfig}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; mod add_artist_handler; mod artist_details_handler; @@ -30,10 +30,10 @@ pub(in crate::handlers::lidarr_handlers) use artist_details_handler::ArtistDetai pub(in crate::handlers::lidarr_handlers) use delete_artist_handler::DeleteArtistHandler; pub(in crate::handlers::lidarr_handlers) use edit_artist_handler::EditArtistHandler; +mod album_details_handler; #[cfg(test)] #[path = "library_handler_tests.rs"] mod library_handler_tests; -mod album_details_handler; pub(super) struct LibraryHandler<'a, 'b> { key: Key, diff --git a/src/models/lidarr_models.rs b/src/models/lidarr_models.rs index a8aaed8..f6b9eeb 100644 --- a/src/models/lidarr_models.rs +++ b/src/models/lidarr_models.rs @@ -515,7 +515,7 @@ pub struct TrackFile { #[derivative(Default)] #[serde(rename_all = "camelCase")] pub struct MediaInfo { - pub audio_bitrate: Option, + pub audio_bit_rate: Option, #[serde(deserialize_with = "super::from_i64")] pub audio_channels: i64, pub audio_codec: Option, diff --git a/src/network/lidarr_network/lidarr_network_test_utils.rs b/src/network/lidarr_network/lidarr_network_test_utils.rs index 9c87566..a86468a 100644 --- a/src/network/lidarr_network/lidarr_network_test_utils.rs +++ b/src/network/lidarr_network/lidarr_network_test_utils.rs @@ -440,7 +440,7 @@ pub mod test_utils { pub fn media_info() -> MediaInfo { MediaInfo { - audio_bitrate: Some("1563 kbps".to_owned()), + audio_bit_rate: Some("1563 kbps".to_owned()), audio_channels: 2, audio_codec: Some("FLAC".to_owned()), audio_bits: Some("24bit".to_owned()), diff --git a/src/ui/lidarr_ui/library/album_details_ui.rs b/src/ui/lidarr_ui/library/album_details_ui.rs new file mode 100644 index 0000000..64ee919 --- /dev/null +++ b/src/ui/lidarr_ui/library/album_details_ui.rs @@ -0,0 +1,505 @@ +use crate::app::App; +use crate::models::Route; +use crate::models::lidarr_models::{LidarrHistoryItem, LidarrRelease, Track}; +use crate::models::servarr_data::lidarr::lidarr_data::{ALBUM_DETAILS_BLOCKS, ActiveLidarrBlock}; +use crate::ui::lidarr_ui::lidarr_ui_utils::create_history_event_details; +use crate::ui::styles::{ManagarrStyle, secondary_style}; +use crate::ui::utils::{ + borderless_block, decorate_peer_style, get_width_from_percentage, layout_block_top_border, +}; +use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; +use crate::ui::widgets::loading_block::LoadingBlock; +use crate::ui::widgets::managarr_table::ManagarrTable; +use crate::ui::widgets::message::Message; +use crate::ui::widgets::popup::{Popup, Size}; +use crate::ui::{DrawUi, draw_popup, draw_tabs}; +use crate::utils::convert_to_gb; +use ratatui::Frame; +use ratatui::layout::{Alignment, Constraint, Rect}; +use ratatui::prelude::{Line, Stylize, Text}; +use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; +use serde_json::Number; + +#[cfg(test)] +#[path = "album_details_ui_tests.rs"] +mod album_details_ui_tests; + +pub(super) struct AlbumDetailsUi; + +impl DrawUi for AlbumDetailsUi { + fn accepts(route: Route) -> bool { + let Route::Lidarr(active_lidarr_block, _) = route else { + return false; + }; + ALBUM_DETAILS_BLOCKS.contains(&active_lidarr_block) + } + + fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { + if app.data.lidarr_data.album_details_modal.is_some() + && let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() + { + let draw_album_details_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| { + let content_area = draw_tabs( + f, + popup_area, + &format!( + "{} Details", + app.data.lidarr_data.albums.current_selection().title.text + ), + &app + .data + .lidarr_data + .album_details_modal + .as_ref() + .expect("album_details_modal must exist in this context") + .album_details_tabs, + ); + draw_album_details(f, app, content_area); + + match active_lidarr_block { + ActiveLidarrBlock::AutomaticallySearchAlbumPrompt => { + let prompt = format!( + "Do you want to trigger an automatic search of your indexers for the album: {}?", + app.data.lidarr_data.albums.current_selection().title.text + ); + let confirmation_prompt = ConfirmationPrompt::new() + .title("Automatic Album Search") + .prompt(&prompt) + .yes_no_value(app.data.lidarr_data.prompt_confirm); + + f.render_widget( + Popup::new(confirmation_prompt).size(Size::MediumPrompt), + f.area(), + ); + } + ActiveLidarrBlock::DeleteTrackFilePrompt => { + let prompt = format!( + "Do you really want to delete this track file: \n{}?", + app + .data + .lidarr_data + .album_details_modal + .as_ref() + .expect("album_details_modal must exist in this context") + .tracks + .current_selection() + .title + ); + let confirmation_prompt = ConfirmationPrompt::new() + .title("Delete Track File") + .prompt(&prompt) + .yes_no_value(app.data.lidarr_data.prompt_confirm); + + f.render_widget( + Popup::new(confirmation_prompt).size(Size::MediumPrompt), + f.area(), + ); + } + ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt => { + draw_manual_album_search_confirm_prompt(f, app); + } + ActiveLidarrBlock::AlbumHistoryDetails => { + draw_history_item_details_popup(f, app); + } + _ => (), + } + }; + + draw_popup(f, app, draw_album_details_popup, Size::XLarge); + } + } +} + +pub fn draw_album_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { + if let Some(album_details_modal) = app.data.lidarr_data.album_details_modal.as_ref() + && let Route::Lidarr(active_lidarr_block, _) = + album_details_modal.album_details_tabs.get_active_route() + { + match active_lidarr_block { + ActiveLidarrBlock::AlbumDetails => draw_tracks_table(f, app, area), + ActiveLidarrBlock::AlbumHistory => draw_album_history_table(f, app, area), + ActiveLidarrBlock::ManualAlbumSearch => draw_album_releases(f, app, area), + _ => (), + } + } +} + +fn draw_tracks_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { + if let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() { + let track_files = app + .data + .lidarr_data + .album_details_modal + .as_ref() + .expect("Album details modal is unpopulated") + .track_files + .items + .clone(); + let content = Some( + &mut app + .data + .lidarr_data + .album_details_modal + .as_mut() + .expect("Album details modal is unpopulated") + .tracks, + ); + + let track_row_mapping = |track: &Track| { + let Track { + track_number, + title, + duration, + track_file_id, + has_file, + .. + } = track; + + let track_file = track_files + .iter() + .find(|track_file| track_file.id == *track_file_id); + let quality = if let Some(track_file) = track_file { + track_file.quality.quality.name.to_owned() + } else { + String::new() + }; + + let audio_info = track_file + .and_then(|tf| tf.media_info.as_ref()) + .map(|mi| { + let codec = mi.audio_codec.as_deref().unwrap_or(""); + let channels = format!("{}.0", mi.audio_channels); + let bitrate = mi.audio_bit_rate.as_deref().unwrap_or(""); + let sample_rate = mi.audio_sample_rate.as_deref().unwrap_or(""); + let bits = mi.audio_bits.as_deref().unwrap_or(""); + format!("{codec} - {channels} - {bitrate} - {sample_rate} - {bits}") + }) + .unwrap_or_default(); + + let duration_secs = duration / 1000; + let mins = duration_secs / 60; + let secs = duration_secs % 60; + let duration_str = format!("{mins}:{secs:02}"); + + let row = Row::new(vec![ + Cell::from(track_number.clone()), + Cell::from(title.clone()), + Cell::from(duration_str), + Cell::from(audio_info), + Cell::from(quality), + ]); + + if *has_file { + row.downloaded() + } else { + row.missing() + } + }; + + let is_searching = active_lidarr_block == ActiveLidarrBlock::SearchTracks; + let tracks_table = ManagarrTable::new(content, track_row_mapping) + .block(layout_block_top_border()) + .loading(app.is_loading) + .searching(is_searching) + .search_produced_empty_results(active_lidarr_block == ActiveLidarrBlock::SearchTracksError) + .headers(["#", "Title", "Duration", "Audio Info", "Quality"]) + .constraints([ + Constraint::Percentage(5), + Constraint::Percentage(35), + Constraint::Percentage(8), + Constraint::Percentage(37), + Constraint::Percentage(15), + ]); + + if is_searching { + tracks_table.show_cursor(f, area); + } + + f.render_widget(tracks_table, area); + } +} + +fn draw_album_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { + match app.data.lidarr_data.album_details_modal.as_ref() { + Some(album_details_modal) if !app.is_loading => { + let current_selection = if album_details_modal.album_history.is_empty() { + LidarrHistoryItem::default() + } else { + album_details_modal + .album_history + .current_selection() + .clone() + }; + + if let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() { + let history_row_mapping = |history_item: &LidarrHistoryItem| { + let LidarrHistoryItem { + source_title, + quality, + event_type, + date, + .. + } = history_item; + + source_title.scroll_left_or_reset( + get_width_from_percentage(area, 40), + current_selection == *history_item, + app.ui_scroll_tick_count == 0, + ); + + Row::new(vec![ + Cell::from(source_title.to_string()), + Cell::from(event_type.to_string()), + Cell::from(quality.quality.name.to_owned()), + Cell::from(date.to_string()), + ]) + .primary() + }; + let mut album_history_table = &mut app + .data + .lidarr_data + .album_details_modal + .as_mut() + .expect("album_details_modal must exist in this context") + .album_history; + let history_table = ManagarrTable::new(Some(&mut album_history_table), history_row_mapping) + .block(layout_block_top_border()) + .loading(app.is_loading) + .sorting(active_lidarr_block == ActiveLidarrBlock::AlbumHistorySortPrompt) + .searching(active_lidarr_block == ActiveLidarrBlock::SearchAlbumHistory) + .search_produced_empty_results( + active_lidarr_block == ActiveLidarrBlock::SearchAlbumHistoryError, + ) + .filtering(active_lidarr_block == ActiveLidarrBlock::FilterAlbumHistory) + .filter_produced_empty_results( + active_lidarr_block == ActiveLidarrBlock::FilterAlbumHistoryError, + ) + .headers(["Source Title", "Event Type", "Quality", "Date"]) + .constraints([ + Constraint::Percentage(40), + Constraint::Percentage(20), + Constraint::Percentage(15), + Constraint::Percentage(25), + ]); + + if [ + ActiveLidarrBlock::SearchAlbumHistory, + ActiveLidarrBlock::FilterAlbumHistory, + ] + .contains(&active_lidarr_block) + { + history_table.show_cursor(f, area); + } + + f.render_widget(history_table, area); + } + } + _ => f.render_widget( + LoadingBlock::new( + app.is_loading || app.data.lidarr_data.album_details_modal.is_none(), + layout_block_top_border(), + ), + area, + ), + } +} + +fn draw_album_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { + match app.data.lidarr_data.album_details_modal.as_ref() { + Some(album_details_modal) if !app.is_loading => { + let (current_selection, is_empty) = if album_details_modal.album_releases.is_empty() { + (LidarrRelease::default(), true) + } else { + ( + album_details_modal + .album_releases + .current_selection() + .clone(), + album_details_modal.album_releases.is_empty(), + ) + }; + + if let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() { + let album_release_row_mapping = |release: &LidarrRelease| { + let LidarrRelease { + protocol, + age, + title, + indexer, + size, + rejected, + seeders, + leechers, + quality, + .. + } = release; + + let age = format!("{age} days"); + title.scroll_left_or_reset( + get_width_from_percentage(area, 35), + current_selection == *release + && active_lidarr_block != ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, + app.ui_scroll_tick_count == 0, + ); + let size = convert_to_gb(*size); + let rejected_str = if *rejected { "⛔" } else { "" }; + let peers = if seeders.is_none() || leechers.is_none() { + Text::from("") + } else { + let seeders = seeders + .clone() + .unwrap_or(Number::from(0u64)) + .as_u64() + .unwrap(); + let leechers = leechers + .clone() + .unwrap_or(Number::from(0u64)) + .as_u64() + .unwrap(); + + decorate_peer_style( + seeders, + leechers, + Text::from(format!("{seeders} / {leechers}")), + ) + }; + + let quality_name = quality.quality.name.clone(); + + Row::new(vec![ + Cell::from(protocol.clone()), + Cell::from(age), + Cell::from(rejected_str), + Cell::from(title.to_string()), + Cell::from(indexer.clone()), + Cell::from(format!("{size:.1} GB")), + Cell::from(peers), + Cell::from(quality_name), + ]) + .primary() + }; + let mut album_release_table = &mut app + .data + .lidarr_data + .album_details_modal + .as_mut() + .expect("album_details_modal must exist in this context") + .album_releases; + let release_table = + ManagarrTable::new(Some(&mut album_release_table), album_release_row_mapping) + .block(layout_block_top_border()) + .loading(app.is_loading || is_empty) + .sorting(active_lidarr_block == ActiveLidarrBlock::ManualAlbumSearchSortPrompt) + .headers([ + "Source", "Age", "⛔", "Title", "Indexer", "Size", "Peers", "Quality", + ]) + .constraints([ + Constraint::Length(9), + Constraint::Length(10), + Constraint::Length(5), + Constraint::Percentage(35), + Constraint::Percentage(15), + Constraint::Length(12), + Constraint::Length(12), + Constraint::Percentage(10), + ]); + + f.render_widget(release_table, area); + } + } + _ => f.render_widget( + LoadingBlock::new( + app.is_loading || app.data.lidarr_data.album_details_modal.is_none(), + layout_block_top_border(), + ), + area, + ), + } +} + +fn draw_manual_album_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_>) { + let current_selection = app + .data + .lidarr_data + .album_details_modal + .as_ref() + .expect("album_details_modal must exist in this context") + .album_releases + .current_selection(); + let title = if current_selection.rejected { + "Download Rejected Release" + } else { + "Download Release" + }; + let prompt = if current_selection.rejected { + format!( + "Do you really want to download the rejected release: {}?", + ¤t_selection.title.text + ) + } else { + format!( + "Do you want to download the release: {}?", + ¤t_selection.title.text + ) + }; + + if current_selection.rejected { + let mut lines_vec = vec![Line::from("Rejection reasons: ".primary().bold())]; + let mut rejections_spans = current_selection + .rejections + .clone() + .unwrap_or_default() + .iter() + .map(|item| Line::from(format!("• {item}").primary().bold())) + .collect::>>(); + lines_vec.append(&mut rejections_spans); + + let content_paragraph = Paragraph::new(lines_vec) + .block(borderless_block()) + .wrap(Wrap { trim: false }) + .left_aligned(); + let confirmation_prompt = ConfirmationPrompt::new() + .title(title) + .prompt(&prompt) + .content(content_paragraph) + .yes_no_value(app.data.lidarr_data.prompt_confirm); + + f.render_widget(Popup::new(confirmation_prompt).size(Size::Small), f.area()); + } else { + let confirmation_prompt = ConfirmationPrompt::new() + .title(title) + .prompt(&prompt) + .yes_no_value(app.data.lidarr_data.prompt_confirm); + + f.render_widget( + Popup::new(confirmation_prompt).size(Size::MediumPrompt), + f.area(), + ); + } +} + +fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>) { + let current_selection = + if let Some(album_details_modal) = app.data.lidarr_data.album_details_modal.as_ref() { + if album_details_modal.album_history.is_empty() { + LidarrHistoryItem::default() + } else { + album_details_modal + .album_history + .current_selection() + .clone() + } + } else { + LidarrHistoryItem::default() + }; + + let line_vec = create_history_event_details(current_selection); + let text = Text::from(line_vec); + + let message = Message::new(text) + .title("Details") + .style(secondary_style()) + .alignment(Alignment::Left); + + f.render_widget(Popup::new(message).size(Size::NarrowLongMessage), f.area()); +} diff --git a/src/ui/lidarr_ui/library/album_details_ui_tests.rs b/src/ui/lidarr_ui/library/album_details_ui_tests.rs new file mode 100644 index 0000000..be66f59 --- /dev/null +++ b/src/ui/lidarr_ui/library/album_details_ui_tests.rs @@ -0,0 +1,131 @@ +#[cfg(test)] +mod tests { + use strum::IntoEnumIterator; + + use crate::app::App; + use crate::models::servarr_data::lidarr::lidarr_data::{ALBUM_DETAILS_BLOCKS, ActiveLidarrBlock}; + use crate::models::stateful_table::StatefulTable; + use crate::ui::DrawUi; + use crate::ui::lidarr_ui::library::album_details_ui::AlbumDetailsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; + + #[test] + fn test_album_details_ui_accepts() { + ActiveLidarrBlock::iter().for_each(|active_lidarr_block| { + if ALBUM_DETAILS_BLOCKS.contains(&active_lidarr_block) { + assert!(AlbumDetailsUi::accepts(active_lidarr_block.into())); + } else { + assert!(!AlbumDetailsUi::accepts(active_lidarr_block.into())); + } + }); + } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveLidarrBlock::AlbumDetails, 0)] + #[case(ActiveLidarrBlock::AlbumHistory, 1)] + #[case(ActiveLidarrBlock::SearchTracks, 0)] + #[case(ActiveLidarrBlock::SearchTracksError, 0)] + #[case(ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, 0)] + #[case(ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, 1)] + #[case(ActiveLidarrBlock::AutomaticallySearchAlbumPrompt, 2)] + #[case(ActiveLidarrBlock::SearchAlbumHistory, 1)] + #[case(ActiveLidarrBlock::SearchAlbumHistoryError, 1)] + #[case(ActiveLidarrBlock::FilterAlbumHistory, 1)] + #[case(ActiveLidarrBlock::FilterAlbumHistoryError, 1)] + #[case(ActiveLidarrBlock::AlbumHistorySortPrompt, 1)] + #[case(ActiveLidarrBlock::AlbumHistoryDetails, 1)] + #[case(ActiveLidarrBlock::ManualAlbumSearch, 2)] + #[case(ActiveLidarrBlock::ManualAlbumSearchConfirmPrompt, 2)] + #[case(ActiveLidarrBlock::ManualAlbumSearchSortPrompt, 2)] + #[case(ActiveLidarrBlock::DeleteTrackFilePrompt, 0)] + fn test_album_details_ui_renders( + #[case] active_lidarr_block: ActiveLidarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_lidarr_block.into()); + app + .data + .lidarr_data + .album_details_modal + .as_mut() + .unwrap() + .album_details_tabs + .set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AlbumDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("album_details_renders_{active_lidarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveLidarrBlock::AlbumDetails, 0)] + #[case(ActiveLidarrBlock::AlbumHistory, 1)] + #[case(ActiveLidarrBlock::AlbumHistoryDetails, 1)] + #[case(ActiveLidarrBlock::ManualAlbumSearch, 2)] + fn test_album_details_ui_renders_loading( + #[case] active_lidarr_block: ActiveLidarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(active_lidarr_block.into()); + { + let album_details_modal = app.data.lidarr_data.album_details_modal.as_mut().unwrap(); + album_details_modal.album_releases = StatefulTable::default(); + album_details_modal.album_history = StatefulTable::default(); + album_details_modal.tracks = StatefulTable::default(); + album_details_modal.album_details_tabs.set_index(index); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AlbumDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("loading_album_details_{active_lidarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveLidarrBlock::AlbumDetails, 0)] + #[case(ActiveLidarrBlock::AlbumHistory, 1)] + #[case(ActiveLidarrBlock::AlbumHistoryDetails, 1)] + #[case(ActiveLidarrBlock::ManualAlbumSearch, 2)] + fn test_album_details_ui_renders_empty( + #[case] active_lidarr_block: ActiveLidarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_lidarr_block.into()); + { + let album_details_modal = app.data.lidarr_data.album_details_modal.as_mut().unwrap(); + album_details_modal.album_releases = StatefulTable::default(); + album_details_modal.album_history = StatefulTable::default(); + album_details_modal.tracks = StatefulTable::default(); + album_details_modal.album_details_tabs.set_index(index); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AlbumDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("empty_album_details_{active_lidarr_block}_{index}"), + output + ); + } + } +} diff --git a/src/ui/lidarr_ui/library/artist_details_ui.rs b/src/ui/lidarr_ui/library/artist_details_ui.rs index 8be4ff4..9a7d381 100644 --- a/src/ui/lidarr_ui/library/artist_details_ui.rs +++ b/src/ui/lidarr_ui/library/artist_details_ui.rs @@ -11,6 +11,7 @@ use crate::app::App; use crate::models::Route; use crate::models::lidarr_models::{Album, LidarrHistoryItem, LidarrRelease}; use crate::models::servarr_data::lidarr::lidarr_data::{ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock}; +use crate::ui::lidarr_ui::library::album_details_ui::AlbumDetailsUi; use crate::ui::lidarr_ui::library::delete_album_ui::DeleteAlbumUi; use crate::ui::lidarr_ui::lidarr_ui_utils::create_history_event_details; use crate::ui::styles::{ManagarrStyle, secondary_style}; @@ -40,7 +41,9 @@ impl DrawUi for ArtistDetailsUi { let Route::Lidarr(active_lidarr_block, _) = route else { return false; }; - DeleteAlbumUi::accepts(route) || ARTIST_DETAILS_BLOCKS.contains(&active_lidarr_block) + AlbumDetailsUi::accepts(route) + || DeleteAlbumUi::accepts(route) + || ARTIST_DETAILS_BLOCKS.contains(&active_lidarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { @@ -115,6 +118,10 @@ impl DrawUi for ArtistDetailsUi { }; draw_popup(f, app, draw_artist_details_popup, Size::XXLarge); + + if AlbumDetailsUi::accepts(route) { + AlbumDetailsUi::draw(f, app, area); + } } } } diff --git a/src/ui/lidarr_ui/library/artist_details_ui_tests.rs b/src/ui/lidarr_ui/library/artist_details_ui_tests.rs index 55d970e..f96e0a9 100644 --- a/src/ui/lidarr_ui/library/artist_details_ui_tests.rs +++ b/src/ui/lidarr_ui/library/artist_details_ui_tests.rs @@ -3,7 +3,7 @@ mod tests { use strum::IntoEnumIterator; use crate::models::servarr_data::lidarr::lidarr_data::{ - ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, + ALBUM_DETAILS_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, }; use crate::ui::DrawUi; use crate::ui::lidarr_ui::library::artist_details_ui::ArtistDetailsUi; @@ -12,6 +12,7 @@ mod tests { fn test_artist_details_ui_accepts() { let mut blocks = ARTIST_DETAILS_BLOCKS.clone().to_vec(); blocks.extend(DELETE_ALBUM_BLOCKS); + blocks.extend(ALBUM_DETAILS_BLOCKS); ActiveLidarrBlock::iter().for_each(|active_lidarr_block| { if blocks.contains(&active_lidarr_block) { diff --git a/src/ui/lidarr_ui/library/library_ui_tests.rs b/src/ui/lidarr_ui/library/library_ui_tests.rs index c50ef86..05751ee 100644 --- a/src/ui/lidarr_ui/library/library_ui_tests.rs +++ b/src/ui/lidarr_ui/library/library_ui_tests.rs @@ -4,8 +4,8 @@ mod tests { use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus}; use crate::models::servarr_data::lidarr::lidarr_data::{ - ADD_ARTIST_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, DELETE_ALBUM_BLOCKS, - DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS, + ADD_ARTIST_BLOCKS, ALBUM_DETAILS_BLOCKS, ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock, + DELETE_ALBUM_BLOCKS, DELETE_ARTIST_BLOCKS, EDIT_ARTIST_BLOCKS, LIBRARY_BLOCKS, }; use crate::ui::DrawUi; use crate::ui::lidarr_ui::library::{LibraryUi, decorate_artist_row_with_style}; @@ -22,6 +22,7 @@ mod tests { library_ui_blocks.extend(EDIT_ARTIST_BLOCKS); library_ui_blocks.extend(ADD_ARTIST_BLOCKS); library_ui_blocks.extend(ARTIST_DETAILS_BLOCKS); + library_ui_blocks.extend(ALBUM_DETAILS_BLOCKS); for active_lidarr_block in ActiveLidarrBlock::iter() { if library_ui_blocks.contains(&active_lidarr_block) { diff --git a/src/ui/lidarr_ui/library/mod.rs b/src/ui/lidarr_ui/library/mod.rs index dcce7c5..a26a0e4 100644 --- a/src/ui/lidarr_ui/library/mod.rs +++ b/src/ui/lidarr_ui/library/mod.rs @@ -29,6 +29,7 @@ use crate::{ }; mod add_artist_ui; +mod album_details_ui; mod artist_details_ui; mod delete_artist_ui; mod edit_artist_ui; diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumDetails_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumDetails_0.snap new file mode 100644 index 0000000..90b98a0 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumDetails_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ # Title Duration Audio Info Quality │ + │=> 1 Test title 3:20 FLAC - 2.0 - 1563 kbps - 44.1kHz - 24bit Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistoryDetails_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistoryDetails_1.snap new file mode 100644 index 0000000..5a09cac --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistoryDetails_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────────────── Details ───────────────────────────────────╮ │ + │ │Source Title: Test source title │ │ + │ │Event Type: grabbed │ │ + │ │Quality: Lossless │ │ + │ │Date: 2023-01-01 00:00:00 UTC │ │ + │ │Indexer: │ │ + │ │NZB Info URL: │ │ + │ │Release Group: │ │ + │ │Age: 0 days │ │ + │ │Published Date: 1970-01-01 00:00:00 UTC │ │ + │ │Download Client: │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistorySortPrompt_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistorySortPrompt_1.snap new file mode 100644 index 0000000..4c3f4bc --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistorySortPrompt_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────╮ │ + │ │Something │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistory_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistory_1.snap new file mode 100644 index 0000000..5c90284 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AlbumHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_0.snap new file mode 100644 index 0000000..515aa5e --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ # Title Duration Audio Info Quality │ + │=> 1 Test title 3:20 FLAC - 2.0 - 1563 kbps - 44.1kHz - 24bit Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Album Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the album: Test Album? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_1.snap new file mode 100644 index 0000000..9e73f3f --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Album Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the album: Test Album? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_2.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_2.snap new file mode 100644 index 0000000..70a533e --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_AutomaticallySearchAlbumPrompt_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 Lossless │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Album Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the album: Test Album? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_DeleteTrackFilePrompt_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_DeleteTrackFilePrompt_0.snap new file mode 100644 index 0000000..a0de373 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_DeleteTrackFilePrompt_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ # Title Duration Audio Info Quality │ + │=> 1 Test title 3:20 FLAC - 2.0 - 1563 kbps - 44.1kHz - 24bit Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────── Delete Track File ───────────────────╮ │ + │ │ Do you really want to delete this track file: │ │ + │ │ Test title? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistoryError_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistoryError_1.snap new file mode 100644 index 0000000..3125c1d --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistoryError_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────── Error ────────────╮ │ + │ │ The given filter produced empty│ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistory_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistory_1.snap new file mode 100644 index 0000000..f1b8013 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_FilterAlbumHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────── Filter ──────────────╮ │ + │ │album history filter │ │ + │ ╰─────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchConfirmPrompt_2.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchConfirmPrompt_2.snap new file mode 100644 index 0000000..6791f5c --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchConfirmPrompt_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 Lossless │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────── Download Rejected Release ──────────────────╮ │ + │ │ Do you really want to download the rejected release: Test │ │ + │ │ Release? │ │ + │ │ │ │ + │ │ │ │ + │ │Rejection reasons: │ │ + │ │• Unknown quality profile │ │ + │ │• Release is already mapped │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭──────────────────────────────╮╭──────────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰──────────────────────────────╯╰──────────────────────────────╯│ │ + │ ╰────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchSortPrompt_2.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchSortPrompt_2.snap new file mode 100644 index 0000000..9bfe80d --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearchSortPrompt_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Age ⛔ Title Indexer Size Peers Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 Lossless │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────╮ │ + │ │Something │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearch_2.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearch_2.snap new file mode 100644 index 0000000..9c73808 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_ManualAlbumSearch_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 Lossless │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistoryError_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistoryError_1.snap new file mode 100644 index 0000000..888ef32 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistoryError_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────── Error ────────────╮ │ + │ │ No items found matching search │ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistory_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistory_1.snap new file mode 100644 index 0000000..14a212c --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchAlbumHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Quality Date │ + │=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────── Search ──────────────╮ │ + │ │album history search │ │ + │ ╰─────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracksError_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracksError_0.snap new file mode 100644 index 0000000..534115d --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracksError_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ # Title Duration Audio Info Quality │ + │=> 1 Test title 3:20 FLAC - 2.0 - 1563 kbps - 44.1kHz - 24bit Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────── Error ────────────╮ │ + │ │ No items found matching search │ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracks_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracks_0.snap new file mode 100644 index 0000000..526377f --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__album_details_renders_SearchTracks_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ # Title Duration Audio Info Quality │ + │=> 1 Test title 3:20 FLAC - 2.0 - 1563 kbps - 44.1kHz - 24bit Lossless │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────── Search ──────────────╮ │ + │ │album search │ │ + │ ╰─────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumDetails_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumDetails_0.snap new file mode 100644 index 0000000..cadad28 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumDetails_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistoryDetails_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistoryDetails_1.snap new file mode 100644 index 0000000..161a3fb --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistoryDetails_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────────────── Details ───────────────────────────────────╮ │ + │ │Source Title: │ │ + │ │Event Type: unknown │ │ + │ │Quality: │ │ + │ │Date: 1970-01-01 00:00:00 UTC │ │ + │ │No additional details available. │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistory_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistory_1.snap new file mode 100644 index 0000000..cadad28 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_AlbumHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_ManualAlbumSearch_2.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_ManualAlbumSearch_2.snap new file mode 100644 index 0000000..1debade --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__empty_album_details_ManualAlbumSearch_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumDetails_0.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumDetails_0.snap new file mode 100644 index 0000000..1debade --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumDetails_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistoryDetails_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistoryDetails_1.snap new file mode 100644 index 0000000..e68a2f4 --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistoryDetails_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────────────── Details ───────────────────────────────────╮ │ + │ │Source Title: │ │ + │ │Event Type: unknown │ │ + │ │Quality: │ │ + │ │Date: 1970-01-01 00:00:00 UTC │ │ + │ │No additional details available. │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistory_1.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistory_1.snap new file mode 100644 index 0000000..1debade --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_AlbumHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_ManualAlbumSearch_2.snap b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_ManualAlbumSearch_2.snap new file mode 100644 index 0000000..1debade --- /dev/null +++ b/src/ui/lidarr_ui/library/snapshots/managarr__ui__lidarr_ui__library__album_details_ui__album_details_ui_tests__tests__snapshot_tests__loading_album_details_ManualAlbumSearch_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/lidarr_ui/library/album_details_ui_tests.rs +expression: output +--- + + + + + ╭ Test Album Details ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Tracks │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/ui_tests.rs b/src/ui/ui_tests.rs index 4ba188a..53dfe57 100644 --- a/src/ui/ui_tests.rs +++ b/src/ui/ui_tests.rs @@ -2,8 +2,8 @@ mod snapshot_tests { use crate::app::App; use crate::handlers::populate_keymapping_table; - use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock; - use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; + use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::ui; use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; @@ -48,77 +48,77 @@ mod snapshot_tests { #[test] fn test_sonarr_ui_renders_library_tab() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveSonarrBlock::default().into()); + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::default().into()); - let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { - ui(f, app); - }); + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); - insta::assert_snapshot!(output); + insta::assert_snapshot!(output); } #[test] fn test_sonarr_ui_renders_library_tab_with_error() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveSonarrBlock::default().into()); - app.error = "Some error".into(); + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::default().into()); + app.error = "Some error".into(); - let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { - ui(f, app); - }); + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); - insta::assert_snapshot!(output); + insta::assert_snapshot!(output); } #[test] fn test_sonarr_ui_renders_library_tab_error_popup() { - let mut app = App::test_default_fully_populated(); - populate_keymapping_table(&mut app); - app.push_navigation_stack(ActiveSonarrBlock::default().into()); + let mut app = App::test_default_fully_populated(); + populate_keymapping_table(&mut app); + app.push_navigation_stack(ActiveSonarrBlock::default().into()); - let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { - ui(f, app); - }); + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); - insta::assert_snapshot!(output); + insta::assert_snapshot!(output); } - #[test] - fn test_lidarr_ui_renders_library_tab() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::default().into()); + #[test] + fn test_lidarr_ui_renders_library_tab() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::default().into()); - let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { - ui(f, app); - }); + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); - insta::assert_snapshot!(output); - } + insta::assert_snapshot!(output); + } - #[test] - fn test_lidarr_ui_renders_library_tab_with_error() { - let mut app = App::test_default_fully_populated(); - app.push_navigation_stack(ActiveLidarrBlock::default().into()); - app.error = "Some error".into(); + #[test] + fn test_lidarr_ui_renders_library_tab_with_error() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveLidarrBlock::default().into()); + app.error = "Some error".into(); - let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { - ui(f, app); - }); + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); - insta::assert_snapshot!(output); - } + insta::assert_snapshot!(output); + } - #[test] - fn test_lidarr_ui_renders_library_tab_error_popup() { - let mut app = App::test_default_fully_populated(); - populate_keymapping_table(&mut app); - app.push_navigation_stack(ActiveLidarrBlock::default().into()); + #[test] + fn test_lidarr_ui_renders_library_tab_error_popup() { + let mut app = App::test_default_fully_populated(); + populate_keymapping_table(&mut app); + app.push_navigation_stack(ActiveLidarrBlock::default().into()); - let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { - ui(f, app); - }); + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); - insta::assert_snapshot!(output); - } + insta::assert_snapshot!(output); + } }