From 27c458307fdb47be959e5d57a4edbdd666eafe2e Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Tue, 8 Sep 2026 18:05:52 -0600 Subject: [PATCH] feat(readarr): add a scrollable overview popup to author details An author's overview renders as the last line of a description box that does not scroll, so a long overview overflows with no way to read the rest. Pressing v on the author details Books tab now opens a popup holding the full overview. The popup owns its own ScrollableText, built fresh from the author's overview when it opens and torn down on Esc so a reopened popup starts at the top. Scrolling mutates only that owned state. The background paragraph renders the Author record's overview, which carries no scroll offset, so it cannot scroll along with the popup. Add a view keybinding bound to v, cite it from the author details context clues, and give the popup its own clue set so it does not inherit the hints of the view underneath. --- src/app/key_binding.rs | 6 + src/app/key_binding_tests.rs | 1 + src/app/readarr/readarr_context_clues.rs | 20 +- .../readarr/readarr_context_clues_tests.rs | 40 +- .../library/author_details_handler.rs | 38 +- .../library/author_details_handler_tests.rs | 175 +++++++- .../library/author_overview_handler.rs | 111 +++++ .../library/author_overview_handler_tests.rs | 393 ++++++++++++++++++ .../library/library_handler_tests.rs | 7 +- src/handlers/readarr_handlers/library/mod.rs | 1 + src/models/servarr_data/readarr/modals.rs | 6 + .../servarr_data/readarr/modals_tests.rs | 11 +- .../servarr_data/readarr/readarr_data.rs | 23 +- .../readarr/readarr_data_tests.rs | 27 +- .../readarr_ui/library/author_details_ui.rs | 6 + .../library/author_details_ui_tests.rs | 46 +- .../readarr_ui/library/author_overview_ui.rs | 87 ++++ .../library/author_overview_ui_tests.rs | 205 +++++++++ src/ui/readarr_ui/library/library_ui_tests.rs | 7 +- src/ui/readarr_ui/library/mod.rs | 1 + ...tests__author_details_AuthorDetails_0.snap | 4 +- ...author_details_AuthorHistoryDetails_1.snap | 4 +- ...hor_details_AuthorHistorySortPrompt_1.snap | 4 +- ...tests__author_details_AuthorHistory_1.snap | 4 +- ...ils_AutomaticallySearchAuthorPrompt_0.snap | 4 +- ...ils_AutomaticallySearchAuthorPrompt_1.snap | 4 +- ...ils_AutomaticallySearchAuthorPrompt_2.snap | 4 +- ...or_details_FilterAuthorHistoryError_1.snap | 4 +- ..._author_details_FilterAuthorHistory_1.snap | 4 +- ...ils_ManualAuthorSearchConfirmPrompt_2.snap | 4 +- ...etails_ManualAuthorSearchSortPrompt_2.snap | 4 +- ...__author_details_ManualAuthorSearch_2.snap | 4 +- ...or_details_SearchAuthorHistoryError_1.snap | 4 +- ..._author_details_SearchAuthorHistory_1.snap | 4 +- ...ts__author_details_SearchBooksError_0.snap | 4 +- ...t_tests__author_details_SearchBooks_0.snap | 4 +- ...r_details_UpdateAndScanAuthorPrompt_0.snap | 4 +- ...r_details_UpdateAndScanAuthorPrompt_1.snap | 4 +- ...r_details_UpdateAndScanAuthorPrompt_2.snap | 4 +- ...s_author_overview_over_author_details.snap | 52 +++ ...tic_search_prompt_over_author_details.snap | 4 +- ...ders_book_details_over_author_details.snap | 4 +- ...nders_delete_book_over_author_details.snap | 4 +- ..._author_details_ui_renders_statistics.snap | 2 +- ...e_and_scan_prompt_over_author_details.snap | 4 +- ...s__empty_author_details_AuthorDetails.snap | 4 +- ...s__empty_author_details_AuthorHistory.snap | 4 +- ...y_author_details_AuthorHistoryDetails.snap | 4 +- ...pty_author_details_ManualAuthorSearch.snap | 4 +- ..._loading_author_details_AuthorDetails.snap | 4 +- ..._loading_author_details_AuthorHistory.snap | 4 +- ...ing_author_details_ManualAuthorSearch.snap | 4 +- ...hot_tests__author_overview_ui_renders.snap | 48 +++ ...ui_renders_an_author_with_no_overview.snap | 48 +++ ...s__author_overview_ui_renders_loading.snap | 48 +++ ...he_author_overview_modal_is_undefined.snap | 5 + ...__author_overview_ui_renders_scrolled.snap | 48 +++ ...author_ui_renders_over_author_details.snap | 4 +- ...i_renders_author_details_over_library.snap | 4 +- 59 files changed, 1493 insertions(+), 97 deletions(-) create mode 100644 src/handlers/readarr_handlers/library/author_overview_handler.rs create mode 100644 src/handlers/readarr_handlers/library/author_overview_handler_tests.rs create mode 100644 src/ui/readarr_ui/library/author_overview_ui.rs create mode 100644 src/ui/readarr_ui/library/author_overview_ui_tests.rs create mode 100644 src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_author_overview_over_author_details.snap create mode 100644 src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders.snap create mode 100644 src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_an_author_with_no_overview.snap create mode 100644 src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_loading.snap create mode 100644 src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_nothing_when_the_author_overview_modal_is_undefined.snap create mode 100644 src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_scrolled.snap diff --git a/src/app/key_binding.rs b/src/app/key_binding.rs index d63f9e85..6ddbf1b8 100644 --- a/src/app/key_binding.rs +++ b/src/app/key_binding.rs @@ -27,6 +27,7 @@ generate_keybindings! { filter, sort, edit, + view, logs, tasks, test, @@ -142,6 +143,11 @@ pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings { alt: None, desc: "edit", }, + view: KeyBinding { + key: Key::Char('v'), + alt: None, + desc: "view", + }, events: KeyBinding { key: Key::Char('e'), alt: None, diff --git a/src/app/key_binding_tests.rs b/src/app/key_binding_tests.rs index 7db65011..7186305a 100644 --- a/src/app/key_binding_tests.rs +++ b/src/app/key_binding_tests.rs @@ -26,6 +26,7 @@ mod test { #[case(DEFAULT_KEYBINDINGS.filter, Key::Char('f'), None, "filter")] #[case(DEFAULT_KEYBINDINGS.sort, Key::Char('o'), None, "sort")] #[case(DEFAULT_KEYBINDINGS.edit, Key::Char('e'), None, "edit")] + #[case(DEFAULT_KEYBINDINGS.view, Key::Char('v'), None, "view")] #[case(DEFAULT_KEYBINDINGS.events, Key::Char('e'), None, "events")] #[case(DEFAULT_KEYBINDINGS.logs, Key::Char('L'), None, "logs")] #[case(DEFAULT_KEYBINDINGS.tasks, Key::Char('t'), None, "tasks")] diff --git a/src/app/readarr/readarr_context_clues.rs b/src/app/readarr/readarr_context_clues.rs index 9f742241..25b1d179 100644 --- a/src/app/readarr/readarr_context_clues.rs +++ b/src/app/readarr/readarr_context_clues.rs @@ -6,9 +6,9 @@ use crate::app::context_clues::{ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::models::Route; use crate::models::servarr_data::readarr::readarr_data::{ - ADD_AUTHOR_BLOCKS, ADD_ROOT_FOLDER_BLOCKS, AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, - BOOK_DETAILS_BLOCKS, DELETE_AUTHOR_BLOCKS, DELETE_BOOK_BLOCKS, EDIT_AUTHOR_BLOCKS, - EDIT_INDEXER_BLOCKS, EDITION_DETAILS_BLOCKS, INDEXER_SETTINGS_BLOCKS, + ADD_AUTHOR_BLOCKS, ADD_ROOT_FOLDER_BLOCKS, AUTHOR_DETAILS_BLOCKS, AUTHOR_OVERVIEW_BLOCKS, + ActiveReadarrBlock, BOOK_DETAILS_BLOCKS, DELETE_AUTHOR_BLOCKS, DELETE_BOOK_BLOCKS, + EDIT_AUTHOR_BLOCKS, EDIT_INDEXER_BLOCKS, EDITION_DETAILS_BLOCKS, INDEXER_SETTINGS_BLOCKS, }; #[cfg(test)] @@ -39,7 +39,7 @@ pub static ADD_AUTHOR_SEARCH_RESULTS_CONTEXT_CLUES: [ContextClue; 2] = [ (DEFAULT_KEYBINDINGS.esc, "edit search"), ]; -pub static AUTHOR_DETAILS_CONTEXT_CLUES: [ContextClue; 8] = [ +pub static AUTHOR_DETAILS_CONTEXT_CLUES: [ContextClue; 9] = [ ( DEFAULT_KEYBINDINGS.refresh, DEFAULT_KEYBINDINGS.refresh.desc, @@ -56,6 +56,15 @@ pub static AUTHOR_DETAILS_CONTEXT_CLUES: [ContextClue; 8] = [ DEFAULT_KEYBINDINGS.auto_search, DEFAULT_KEYBINDINGS.auto_search.desc, ), + (DEFAULT_KEYBINDINGS.view, "view overview"), + (DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc), +]; + +pub static AUTHOR_OVERVIEW_CONTEXT_CLUES: [ContextClue; 2] = [ + ( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc, + ), (DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc), ]; @@ -168,6 +177,9 @@ impl ContextClueProvider for ReadarrContextClueProvider { .readarr_data .author_info_tabs .get_active_route_contextual_help(), + _ if AUTHOR_OVERVIEW_BLOCKS.contains(&active_readarr_block) => { + Some(&AUTHOR_OVERVIEW_CONTEXT_CLUES) + } _ if BOOK_DETAILS_BLOCKS.contains(&active_readarr_block) => app .data .readarr_data diff --git a/src/app/readarr/readarr_context_clues_tests.rs b/src/app/readarr/readarr_context_clues_tests.rs index 76112630..f9020633 100644 --- a/src/app/readarr/readarr_context_clues_tests.rs +++ b/src/app/readarr/readarr_context_clues_tests.rs @@ -8,10 +8,10 @@ mod tests { use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::readarr::readarr_context_clues::{ ADD_AUTHOR_SEARCH_RESULTS_CONTEXT_CLUES, AUTHOR_DETAILS_CONTEXT_CLUES, - AUTHOR_HISTORY_CONTEXT_CLUES, AUTHORS_CONTEXT_CLUES, BOOK_DETAILS_CONTEXT_CLUES, - BOOK_FILE_CONTEXT_CLUES, BOOK_HISTORY_CONTEXT_CLUES, EDITION_DETAILS_CONTEXT_CLUES, - MANUAL_AUTHOR_SEARCH_CONTEXT_CLUES, MANUAL_BOOK_SEARCH_CONTEXT_CLUES, - ReadarrContextClueProvider, + AUTHOR_HISTORY_CONTEXT_CLUES, AUTHOR_OVERVIEW_CONTEXT_CLUES, AUTHORS_CONTEXT_CLUES, + BOOK_DETAILS_CONTEXT_CLUES, BOOK_FILE_CONTEXT_CLUES, BOOK_HISTORY_CONTEXT_CLUES, + EDITION_DETAILS_CONTEXT_CLUES, MANUAL_AUTHOR_SEARCH_CONTEXT_CLUES, + MANUAL_BOOK_SEARCH_CONTEXT_CLUES, ReadarrContextClueProvider, }; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_data::readarr::modals::BookDetailsModal; @@ -115,6 +115,10 @@ mod tests { DEFAULT_KEYBINDINGS.auto_search.desc, ) ); + assert_some_eq_x!( + author_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.view, "view overview") + ); assert_some_eq_x!( author_details_context_clues_iter.next(), &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) @@ -122,6 +126,24 @@ mod tests { assert_none!(author_details_context_clues_iter.next()); } + #[test] + fn test_author_overview_context_clues() { + let mut author_overview_context_clues_iter = AUTHOR_OVERVIEW_CONTEXT_CLUES.iter(); + + assert_some_eq_x!( + author_overview_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + author_overview_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(author_overview_context_clues_iter.next()); + } + #[test] fn test_add_author_search_results_context_clues() { let mut add_author_search_results_context_clues_iter = @@ -440,6 +462,16 @@ mod tests { assert_some_eq_x!(context_clues, &EDITION_DETAILS_CONTEXT_CLUES); } + #[test] + fn test_readarr_context_clue_provider_author_overview_block() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + + let context_clues = ReadarrContextClueProvider::get_context_clues(&mut app); + + assert_some_eq_x!(context_clues, &AUTHOR_OVERVIEW_CONTEXT_CLUES); + } + #[test] fn test_readarr_context_clue_provider_authors_block() { let mut app = App::test_default(); diff --git a/src/handlers/readarr_handlers/library/author_details_handler.rs b/src/handlers/readarr_handlers/library/author_details_handler.rs index 26fa82a8..38a4db60 100644 --- a/src/handlers/readarr_handlers/library/author_details_handler.rs +++ b/src/handlers/readarr_handlers/library/author_details_handler.rs @@ -1,3 +1,4 @@ +use super::author_overview_handler::AuthorOverviewHandler; use crate::app::App; use crate::event::Key; use crate::handlers::readarr_handlers::history::history_sorting_options; @@ -5,13 +6,14 @@ use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; use crate::models::readarr_models::{Book, ReadarrHistoryItem, ReadarrRelease}; +use crate::models::servarr_data::readarr::modals::AuthorOverviewModal; use crate::models::servarr_data::readarr::readarr_data::{ AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, DELETE_BOOK_SELECTION_BLOCKS, EDIT_AUTHOR_SELECTION_BLOCKS, }; use crate::models::servarr_models::ReleaseDownloadBody; use crate::models::stateful_table::SortOption; -use crate::models::{BlockSelectionState, Route}; +use crate::models::{BlockSelectionState, Route, ScrollableText}; use crate::network::readarr_network::ReadarrEvent; use serde_json::Number; @@ -34,10 +36,36 @@ impl AuthorDetailsHandler<'_, '_> { fn extract_book_id(&self) -> i64 { self.app.data.readarr_data.books.current_selection().id } + + fn build_author_overview_modal(&mut self) { + let overview = self + .app + .data + .readarr_data + .authors + .current_selection() + .overview + .clone() + .unwrap_or_default(); + + self.app.data.readarr_data.author_overview_modal = Some(AuthorOverviewModal { + overview: ScrollableText::with_string(overview), + }); + } } impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for AuthorDetailsHandler<'a, 'b> { fn handle(&mut self) { + if AuthorOverviewHandler::accepts(self.active_readarr_block) { + return AuthorOverviewHandler::new( + self.key, + self.app, + self.active_readarr_block, + self._context, + ) + .handle(); + } + let books_table_handling_config = TableHandlingConfig::new(ActiveReadarrBlock::AuthorDetails.into()) .searching_block(ActiveReadarrBlock::SearchBooks.into()) @@ -78,7 +106,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for AuthorDetailsHandle } fn accepts(active_block: ActiveReadarrBlock) -> bool { - AUTHOR_DETAILS_BLOCKS.contains(&active_block) + AuthorOverviewHandler::accepts(active_block) || AUTHOR_DETAILS_BLOCKS.contains(&active_block) } fn ignore_special_keys(&self) -> bool { @@ -294,6 +322,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for AuthorDetailsHandle self.app.data.readarr_data.selected_block = BlockSelectionState::new(EDIT_AUTHOR_SELECTION_BLOCKS); } + _ if matches_key!(view, key) => { + self.build_author_overview_modal(); + self + .app + .push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + } _ if matches_key!(toggle_monitoring, key) && !self.app.data.readarr_data.books.is_empty() => { diff --git a/src/handlers/readarr_handlers/library/author_details_handler_tests.rs b/src/handlers/readarr_handlers/library/author_details_handler_tests.rs index aa028a8f..180aab68 100644 --- a/src/handlers/readarr_handlers/library/author_details_handler_tests.rs +++ b/src/handlers/readarr_handlers/library/author_details_handler_tests.rs @@ -15,9 +15,10 @@ mod tests { use crate::models::HorizontallyScrollableText; use crate::models::readarr_models::{ReadarrHistoryItem, ReadarrRelease}; use crate::models::servarr_data::readarr::readarr_data::{ - AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, + AUTHOR_DETAILS_BLOCKS, AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, }; use crate::models::servarr_models::{Quality, QualityWrapper}; + use crate::test_handler_delegation; mod test_handle_delete { use super::*; @@ -465,6 +466,7 @@ mod tests { use crate::assert_navigation_pushed; use crate::handlers::KeyEventHandler; use crate::handlers::readarr_handlers::library::author_details_handler::AuthorDetailsHandler; + use crate::handlers::readarr_handlers::library::author_overview_handler::AuthorOverviewHandler; use crate::models::readarr_models::Author; use crate::models::servarr_data::readarr::readarr_data::{ ActiveReadarrBlock, EDIT_AUTHOR_SELECTION_BLOCKS, @@ -473,7 +475,7 @@ mod tests { use crate::network::readarr_network::ReadarrEvent; use crate::network::readarr_network::readarr_network_test_utils::test_utils::torrent_release; use crate::{assert_modal_absent, assert_modal_present, assert_navigation_popped}; - use pretty_assertions::assert_eq; + use pretty_assertions::{assert_eq, assert_str_eq}; use rstest::rstest; #[rstest] @@ -538,6 +540,161 @@ mod tests { assert_modal_absent!(app.data.readarr_data.edit_author_modal); } + #[test] + fn test_author_details_view_key_opens_the_author_overview() { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.author_overview_modal = None; + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + + AuthorDetailsHandler::new( + DEFAULT_KEYBINDINGS.view.key, + &mut app, + ActiveReadarrBlock::AuthorDetails, + None, + ) + .handle(); + + assert_navigation_pushed!(app, ActiveReadarrBlock::AuthorOverview.into()); + assert_modal_present!(app.data.readarr_data.author_overview_modal); + } + + #[test] + fn test_author_details_view_key_builds_the_overview_from_the_selected_author() { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.author_overview_modal = None; + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + + AuthorDetailsHandler::new( + DEFAULT_KEYBINDINGS.view.key, + &mut app, + ActiveReadarrBlock::AuthorDetails, + None, + ) + .handle(); + + let overview = &app + .data + .readarr_data + .author_overview_modal + .as_ref() + .unwrap() + .overview; + assert_eq!(overview.offset, 0); + assert_eq!( + overview.get_text(), + app + .data + .readarr_data + .authors + .current_selection() + .overview + .clone() + .unwrap() + ); + } + + #[test] + fn test_author_details_view_key_for_an_author_with_no_overview() { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.author_overview_modal = None; + let mut author = app.data.readarr_data.authors.current_selection().clone(); + author.overview = None; + app.data.readarr_data.authors.set_items(vec![author]); + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + + AuthorDetailsHandler::new( + DEFAULT_KEYBINDINGS.view.key, + &mut app, + ActiveReadarrBlock::AuthorDetails, + None, + ) + .handle(); + + assert_navigation_pushed!(app, ActiveReadarrBlock::AuthorOverview.into()); + assert_str_eq!( + app + .data + .readarr_data + .author_overview_modal + .as_ref() + .unwrap() + .overview + .get_text(), + "" + ); + } + + #[test] + fn test_author_details_view_key_reopens_the_author_overview_at_the_top() { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.author_overview_modal = None; + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + AuthorDetailsHandler::new( + DEFAULT_KEYBINDINGS.view.key, + &mut app, + ActiveReadarrBlock::AuthorDetails, + None, + ) + .handle(); + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + AuthorDetailsHandler::new( + DEFAULT_KEYBINDINGS.view.key, + &mut app, + ActiveReadarrBlock::AuthorDetails, + None, + ) + .handle(); + + assert_navigation_pushed!(app, ActiveReadarrBlock::AuthorOverview.into()); + assert_eq!( + app + .data + .readarr_data + .author_overview_modal + .as_ref() + .unwrap() + .overview + .offset, + 0 + ); + } + + #[test] + fn test_author_details_view_key_no_op_when_not_ready() { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.author_overview_modal = None; + app.is_loading = true; + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + + AuthorDetailsHandler::new( + DEFAULT_KEYBINDINGS.view.key, + &mut app, + ActiveReadarrBlock::AuthorDetails, + None, + ) + .handle(); + + assert_eq!( + app.get_current_route(), + ActiveReadarrBlock::AuthorDetails.into() + ); + assert_modal_absent!(app.data.readarr_data.author_overview_modal); + } + #[test] fn test_author_details_toggle_monitoring_key() { let mut app = App::test_default_fully_populated(); @@ -828,8 +985,11 @@ mod tests { #[test] fn test_author_details_handler_accepts() { + let mut author_details_blocks = AUTHOR_DETAILS_BLOCKS.to_vec(); + author_details_blocks.extend(AUTHOR_OVERVIEW_BLOCKS); + ActiveReadarrBlock::iter().for_each(|readarr_block| { - if AUTHOR_DETAILS_BLOCKS.contains(&readarr_block) { + if author_details_blocks.contains(&readarr_block) { assert!( AuthorDetailsHandler::accepts(readarr_block), "{readarr_block} is not accepted by the AuthorDetailsHandler" @@ -840,6 +1000,15 @@ mod tests { }); } + #[test] + fn test_delegates_author_overview_blocks_to_author_overview_handler() { + test_handler_delegation!( + AuthorDetailsHandler, + ActiveReadarrBlock::AuthorDetails, + ActiveReadarrBlock::AuthorOverview + ); + } + #[test] fn test_extract_author_id() { let mut app = App::test_default_fully_populated(); diff --git a/src/handlers/readarr_handlers/library/author_overview_handler.rs b/src/handlers/readarr_handlers/library/author_overview_handler.rs new file mode 100644 index 00000000..5f404972 --- /dev/null +++ b/src/handlers/readarr_handlers/library/author_overview_handler.rs @@ -0,0 +1,111 @@ +use crate::app::App; +use crate::event::Key; +use crate::handlers::KeyEventHandler; +use crate::matches_key; +use crate::models::servarr_data::readarr::readarr_data::{ + AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, +}; +use crate::models::{Route, Scrollable, ScrollableText}; + +#[cfg(test)] +#[path = "author_overview_handler_tests.rs"] +mod author_overview_handler_tests; + +pub(super) struct AuthorOverviewHandler<'a, 'b> { + key: Key, + app: &'a mut App<'b>, + active_readarr_block: ActiveReadarrBlock, + _context: Option, +} + +impl AuthorOverviewHandler<'_, '_> { + fn overview(&mut self) -> &mut ScrollableText { + &mut self + .app + .data + .readarr_data + .author_overview_modal + .as_mut() + .expect("Author overview modal is undefined") + .overview + } +} + +impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for AuthorOverviewHandler<'a, 'b> { + fn accepts(active_block: ActiveReadarrBlock) -> bool { + AUTHOR_OVERVIEW_BLOCKS.contains(&active_block) + } + + 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: ActiveReadarrBlock, + _context: Option, + ) -> AuthorOverviewHandler<'a, 'b> { + AuthorOverviewHandler { + key, + app, + active_readarr_block: active_block, + _context, + } + } + + fn get_key(&self) -> Key { + self.key + } + + fn is_ready(&self) -> bool { + if self.app.is_loading { + return false; + } + + self.app.data.readarr_data.author_overview_modal.is_some() + } + + fn handle_scroll_up(&mut self) { + self.overview().scroll_up(); + } + + fn handle_scroll_down(&mut self) { + self.overview().scroll_down(); + } + + fn handle_home(&mut self) { + self.overview().scroll_to_top(); + } + + fn handle_end(&mut self) { + self.overview().scroll_to_bottom(); + } + + fn handle_delete(&mut self) {} + + fn handle_left_right_action(&mut self) {} + + fn handle_submit(&mut self) {} + + fn handle_esc(&mut self) { + self.app.pop_navigation_stack(); + self.app.data.readarr_data.author_overview_modal = None; + } + + fn handle_char_key_event(&mut self) { + if matches_key!(refresh, self.key) { + self + .app + .pop_and_push_navigation_stack(self.active_readarr_block.into()); + } + } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> Route { + self.app.get_current_route() + } +} diff --git a/src/handlers/readarr_handlers/library/author_overview_handler_tests.rs b/src/handlers/readarr_handlers/library/author_overview_handler_tests.rs new file mode 100644 index 00000000..107598f8 --- /dev/null +++ b/src/handlers/readarr_handlers/library/author_overview_handler_tests.rs @@ -0,0 +1,393 @@ +#[cfg(test)] +mod tests { + use strum::IntoEnumIterator; + + use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::handlers::KeyEventHandler; + use crate::handlers::readarr_handlers::library::author_overview_handler::AuthorOverviewHandler; + use crate::models::ScrollableText; + use crate::models::servarr_data::readarr::modals::AuthorOverviewModal; + use crate::models::servarr_data::readarr::readarr_data::{ + AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, + }; + + mod test_handle_scroll_up_and_down { + use super::*; + use pretty_assertions::assert_eq; + + #[test] + fn test_author_overview_scroll_up() { + let mut app = app_with_author_overview(); + set_offset(&mut app, 2); + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 1); + } + + #[test] + fn test_author_overview_scroll_up_no_op_when_not_ready() { + let mut app = app_with_author_overview(); + set_offset(&mut app, 2); + app.is_loading = true; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 2); + } + + #[test] + fn test_author_overview_scroll_down() { + let mut app = app_with_author_overview(); + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.down.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 1); + } + + #[test] + fn test_author_overview_scroll_down_no_op_when_not_ready() { + let mut app = app_with_author_overview(); + app.is_loading = true; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.down.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 0); + } + } + + mod test_handle_home_end { + use super::*; + use pretty_assertions::assert_eq; + + #[test] + fn test_author_overview_home() { + let mut app = app_with_author_overview(); + set_offset(&mut app, 3); + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 0); + } + + #[test] + fn test_author_overview_end() { + let mut app = app_with_author_overview(); + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 5); + } + + #[test] + fn test_author_overview_home_no_op_when_not_ready() { + let mut app = app_with_author_overview(); + set_offset(&mut app, 3); + app.is_loading = true; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 3); + } + + #[test] + fn test_author_overview_end_no_op_when_not_ready() { + let mut app = app_with_author_overview(); + app.is_loading = true; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 0); + } + } + + mod test_handle_esc { + use super::*; + use crate::{assert_modal_absent, assert_navigation_popped}; + + #[test] + fn test_author_overview_esc_tears_down_the_author_overview_modal() { + let mut app = app_with_author_overview(); + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_navigation_popped!(app, ActiveReadarrBlock::AuthorDetails.into()); + assert_modal_absent!(app.data.readarr_data.author_overview_modal); + } + + #[test] + fn test_author_overview_esc_tears_down_the_modal_even_when_loading() { + let mut app = app_with_author_overview(); + app.is_loading = true; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_navigation_popped!(app, ActiveReadarrBlock::AuthorDetails.into()); + assert_modal_absent!(app.data.readarr_data.author_overview_modal); + } + } + + mod test_handle_key_char { + use super::*; + use crate::assert_navigation_pushed; + + #[test] + fn test_author_overview_refresh_key() { + let mut app = app_with_author_overview(); + app.is_routing = false; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.refresh.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_navigation_pushed!(app, ActiveReadarrBlock::AuthorOverview.into()); + assert!(app.is_routing); + } + + #[test] + fn test_author_overview_refresh_key_no_op_when_not_ready() { + let mut app = app_with_author_overview(); + app.is_loading = true; + app.is_routing = false; + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.refresh.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert!(!app.is_routing); + } + } + + #[test] + fn test_scrolling_the_overview_does_not_mutate_the_author_record() { + let mut app = app_with_author_overview(); + let overview_before = app + .data + .readarr_data + .authors + .current_selection() + .overview + .clone(); + + AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.down.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ) + .handle(); + + assert_eq!(overview_offset(&app), 1); + assert_eq!( + app.data.readarr_data.authors.current_selection().overview, + overview_before + ); + } + + #[test] + fn test_author_overview_handler_accepts() { + ActiveReadarrBlock::iter().for_each(|active_readarr_block| { + if AUTHOR_OVERVIEW_BLOCKS.contains(&active_readarr_block) { + assert!( + AuthorOverviewHandler::accepts(active_readarr_block), + "{active_readarr_block} is not accepted by the AuthorOverviewHandler" + ); + } else { + assert!( + !AuthorOverviewHandler::accepts(active_readarr_block), + "{active_readarr_block} is wrongly accepted by the AuthorOverviewHandler" + ); + } + }); + } + + #[test] + fn test_author_overview_handler_dispatches_no_network_events() { + let mut app = app_with_author_overview(); + + for key in [ + DEFAULT_KEYBINDINGS.up.key, + DEFAULT_KEYBINDINGS.down.key, + DEFAULT_KEYBINDINGS.home.key, + DEFAULT_KEYBINDINGS.end.key, + DEFAULT_KEYBINDINGS.delete.key, + DEFAULT_KEYBINDINGS.left.key, + DEFAULT_KEYBINDINGS.right.key, + DEFAULT_KEYBINDINGS.submit.key, + DEFAULT_KEYBINDINGS.refresh.key, + ] { + AuthorOverviewHandler::new(key, &mut app, ActiveReadarrBlock::AuthorOverview, None).handle(); + + assert_none!(app.data.readarr_data.prompt_confirm_action); + assert!(!app.data.readarr_data.prompt_confirm); + } + } + + #[test] + fn test_author_overview_handler_is_not_ready_when_loading() { + let mut app = app_with_author_overview(); + app.is_loading = true; + + let handler = AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ); + + assert!(!handler.is_ready()); + } + + #[test] + fn test_author_overview_handler_is_not_ready_when_the_modal_is_absent() { + let mut app = app_with_author_overview(); + app.data.readarr_data.author_overview_modal = None; + + let handler = AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ); + + assert!(!handler.is_ready()); + } + + #[test] + fn test_author_overview_handler_is_ready() { + let mut app = app_with_author_overview(); + + let handler = AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ); + + assert!(handler.is_ready()); + } + + #[test] + fn test_author_overview_handler_ignores_special_keys_for_textbox_input() { + let mut app = app_with_author_overview(); + app.ignore_special_keys_for_textbox_input = true; + + let handler = AuthorOverviewHandler::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveReadarrBlock::AuthorOverview, + None, + ); + + assert!(handler.ignore_special_keys()); + } + + fn app_with_author_overview() -> App<'static> { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.author_overview_modal = Some(AuthorOverviewModal { + overview: ScrollableText::with_string( + "some interesting description of the author\r\n\ + \r\n\ + He was born in Madison, Wisconsin: a city he has never really left.\r\n\ + \r\n\ + His first novel took him seven years to finish.\r\n" + .to_owned(), + ), + }); + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + + app + } + + fn overview_offset(app: &App<'_>) -> u16 { + app + .data + .readarr_data + .author_overview_modal + .as_ref() + .unwrap() + .overview + .offset + } + + fn set_offset(app: &mut App<'_>, offset: u16) { + app + .data + .readarr_data + .author_overview_modal + .as_mut() + .unwrap() + .overview + .offset = offset; + } +} diff --git a/src/handlers/readarr_handlers/library/library_handler_tests.rs b/src/handlers/readarr_handlers/library/library_handler_tests.rs index 5f215732..ebd1f1dd 100644 --- a/src/handlers/readarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/readarr_handlers/library/library_handler_tests.rs @@ -14,9 +14,9 @@ mod tests { use crate::models::HorizontallyScrollableText; use crate::models::readarr_models::{Author, AuthorStatistics, AuthorStatus}; use crate::models::servarr_data::readarr::readarr_data::{ - ADD_AUTHOR_BLOCKS, AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, BOOK_DETAILS_BLOCKS, - DELETE_AUTHOR_BLOCKS, DELETE_BOOK_BLOCKS, EDIT_AUTHOR_BLOCKS, EDITION_DETAILS_BLOCKS, - LIBRARY_BLOCKS, + ADD_AUTHOR_BLOCKS, AUTHOR_DETAILS_BLOCKS, AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, + BOOK_DETAILS_BLOCKS, DELETE_AUTHOR_BLOCKS, DELETE_BOOK_BLOCKS, EDIT_AUTHOR_BLOCKS, + EDITION_DETAILS_BLOCKS, LIBRARY_BLOCKS, }; use crate::test_handler_delegation; @@ -931,6 +931,7 @@ mod tests { let mut library_handler_blocks = Vec::new(); library_handler_blocks.extend(LIBRARY_BLOCKS); library_handler_blocks.extend(AUTHOR_DETAILS_BLOCKS); + library_handler_blocks.extend(AUTHOR_OVERVIEW_BLOCKS); library_handler_blocks.extend(BOOK_DETAILS_BLOCKS); library_handler_blocks.extend(EDITION_DETAILS_BLOCKS); library_handler_blocks.extend(ADD_AUTHOR_BLOCKS); diff --git a/src/handlers/readarr_handlers/library/mod.rs b/src/handlers/readarr_handlers/library/mod.rs index cfc03e5f..8df9d253 100644 --- a/src/handlers/readarr_handlers/library/mod.rs +++ b/src/handlers/readarr_handlers/library/mod.rs @@ -21,6 +21,7 @@ use crate::models::Route; mod add_author_handler; mod author_details_handler; +mod author_overview_handler; mod book_details_handler; mod delete_author_handler; mod delete_book_handler; diff --git a/src/models/servarr_data/readarr/modals.rs b/src/models/servarr_data/readarr/modals.rs index b696796d..c9ff5cf4 100644 --- a/src/models/servarr_data/readarr/modals.rs +++ b/src/models/servarr_data/readarr/modals.rs @@ -276,3 +276,9 @@ impl Default for BookDetailsModal { pub struct EditionDetailsModal { pub edition_details: ScrollableText, } + +#[derive(Default)] +#[cfg_attr(test, derive(Debug))] +pub struct AuthorOverviewModal { + pub overview: ScrollableText, +} diff --git a/src/models/servarr_data/readarr/modals_tests.rs b/src/models/servarr_data/readarr/modals_tests.rs index c6695a15..f790ac53 100644 --- a/src/models/servarr_data/readarr/modals_tests.rs +++ b/src/models/servarr_data/readarr/modals_tests.rs @@ -7,8 +7,8 @@ mod tests { use crate::models::readarr_models::{Author, MonitorType, NewItemMonitorType}; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::readarr::modals::{ - AddAuthorModal, AddReadarrRootFolderModal, BookDetailsModal, EditAuthorModal, - EditionDetailsModal, + AddAuthorModal, AddReadarrRootFolderModal, AuthorOverviewModal, BookDetailsModal, + EditAuthorModal, EditionDetailsModal, }; use crate::models::servarr_data::readarr::readarr_data::{ActiveReadarrBlock, ReadarrData}; use crate::models::servarr_models::{Indexer, IndexerField, RootFolder}; @@ -331,4 +331,11 @@ mod tests { assert_is_empty!(edition_details_modal.edition_details); } + + #[test] + fn test_author_overview_modal_default() { + let author_overview_modal = AuthorOverviewModal::default(); + + assert_is_empty!(author_overview_modal.overview); + } } diff --git a/src/models/servarr_data/readarr/readarr_data.rs b/src/models/servarr_data/readarr/readarr_data.rs index 27a37483..4162aa05 100644 --- a/src/models/servarr_data/readarr/readarr_data.rs +++ b/src/models/servarr_data/readarr/readarr_data.rs @@ -1,6 +1,8 @@ use serde_json::Number; -use super::modals::{AddAuthorModal, AddReadarrRootFolderModal, BookDetailsModal, EditAuthorModal}; +use super::modals::{ + AddAuthorModal, AddReadarrRootFolderModal, AuthorOverviewModal, BookDetailsModal, EditAuthorModal, +}; use crate::app::context_clues::{ BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, HISTORY_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, @@ -55,6 +57,7 @@ pub struct ReadarrData<'a> { pub add_searched_authors: Option>, pub author_history: StatefulTable, pub author_info_tabs: TabState, + pub author_overview_modal: Option, pub author_releases: StatefulTable, pub authors: StatefulTable, pub blocklist: StatefulTable, @@ -141,6 +144,7 @@ impl<'a> Default for ReadarrData<'a> { add_root_folder_modal: None, add_searched_authors: None, author_history: StatefulTable::default(), + author_overview_modal: None, author_releases: StatefulTable::default(), authors: StatefulTable::default(), blocklist: StatefulTable::default(), @@ -262,7 +266,14 @@ impl ReadarrData<'_> { author_name: "Test Author".into(), foreign_author_id: "test-foreign-id".to_owned(), status: AuthorStatus::Continuing, - overview: Some("some interesting description of the author".to_owned()), + overview: Some( + "some interesting description of the author\r\n\ + \r\n\ + He was born in Madison, Wisconsin: a city he has never really left.\r\n\ + \r\n\ + His first novel took him seven years to finish.\r\n" + .to_owned(), + ), path: "/nfs/books/Test Author".to_owned(), quality_profile_id: 1, metadata_profile_id: 1, @@ -551,9 +562,14 @@ impl ReadarrData<'_> { let mut indexer_test_all_results = StatefulTable::default(); indexer_test_all_results.set_items(vec![indexer_test_result()]); + let author_overview_modal = AuthorOverviewModal { + overview: ScrollableText::with_string(author.overview.clone().unwrap_or_default()), + }; + let mut readarr_data = ReadarrData { add_author_modal: Some(add_author_modal), add_root_folder_modal: Some(add_root_folder_modal), + author_overview_modal: Some(author_overview_modal), book_details_modal: Some(book_details_modal), delete_files: true, disk_space_vec: vec![diskspace()], @@ -647,6 +663,7 @@ pub enum ActiveReadarrBlock { AuthorHistory, AuthorHistoryDetails, AuthorHistorySortPrompt, + AuthorOverview, AuthorsSortPrompt, AutomaticallySearchAuthorPrompt, AutomaticallySearchBookPrompt, @@ -770,6 +787,8 @@ pub static AUTHOR_DETAILS_BLOCKS: [ActiveReadarrBlock; 15] = [ ActiveReadarrBlock::UpdateAndScanAuthorPrompt, ]; +pub static AUTHOR_OVERVIEW_BLOCKS: [ActiveReadarrBlock; 1] = [ActiveReadarrBlock::AuthorOverview]; + pub static BOOK_DETAILS_BLOCKS: [ActiveReadarrBlock; 16] = [ ActiveReadarrBlock::BookDetails, ActiveReadarrBlock::BookHistory, diff --git a/src/models/servarr_data/readarr/readarr_data_tests.rs b/src/models/servarr_data/readarr/readarr_data_tests.rs index 548059f8..679dc605 100644 --- a/src/models/servarr_data/readarr/readarr_data_tests.rs +++ b/src/models/servarr_data/readarr/readarr_data_tests.rs @@ -11,13 +11,14 @@ mod tests { use crate::models::readarr_models::{Book, ReadarrHistoryItem, ReadarrRelease}; use crate::models::servarr_data::readarr::readarr_data::{ ADD_AUTHOR_BLOCKS, ADD_AUTHOR_SELECTION_BLOCKS, ADD_ROOT_FOLDER_BLOCKS, - ADD_ROOT_FOLDER_SELECTION_BLOCKS, AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, BLOCKLIST_BLOCKS, - BOOK_DETAILS_BLOCKS, DELETE_AUTHOR_BLOCKS, DELETE_AUTHOR_SELECTION_BLOCKS, DELETE_BOOK_BLOCKS, - DELETE_BOOK_SELECTION_BLOCKS, DOWNLOADS_BLOCKS, EDIT_AUTHOR_BLOCKS, - EDIT_AUTHOR_SELECTION_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_NZB_SELECTION_BLOCKS, - EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, EDITION_DETAILS_BLOCKS, HISTORY_BLOCKS, - INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, LIBRARY_BLOCKS, - ROOT_FOLDERS_BLOCKS, ReadarrData, SYSTEM_DETAILS_BLOCKS, + ADD_ROOT_FOLDER_SELECTION_BLOCKS, AUTHOR_DETAILS_BLOCKS, AUTHOR_OVERVIEW_BLOCKS, + ActiveReadarrBlock, BLOCKLIST_BLOCKS, BOOK_DETAILS_BLOCKS, DELETE_AUTHOR_BLOCKS, + DELETE_AUTHOR_SELECTION_BLOCKS, DELETE_BOOK_BLOCKS, DELETE_BOOK_SELECTION_BLOCKS, + DOWNLOADS_BLOCKS, EDIT_AUTHOR_BLOCKS, EDIT_AUTHOR_SELECTION_BLOCKS, EDIT_INDEXER_BLOCKS, + EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, + EDITION_DETAILS_BLOCKS, HISTORY_BLOCKS, INDEXER_SETTINGS_BLOCKS, + INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, LIBRARY_BLOCKS, ROOT_FOLDERS_BLOCKS, + ReadarrData, SYSTEM_DETAILS_BLOCKS, }; use crate::models::{BlockSelectionState, Route}; use bimap::BiMap; @@ -152,6 +153,7 @@ mod tests { assert_none!(readarr_data.add_root_folder_modal); assert_none!(readarr_data.add_searched_authors); assert_is_empty!(readarr_data.author_history); + assert_none!(readarr_data.author_overview_modal); assert_is_empty!(readarr_data.author_releases); assert_is_empty!(readarr_data.authors); assert_is_empty!(readarr_data.blocklist); @@ -361,6 +363,17 @@ mod tests { assert!(EDITION_DETAILS_BLOCKS.contains(&ActiveReadarrBlock::BookEditionDetails)); } + #[test] + fn test_author_details_blocks_excludes_author_overview() { + assert!(!AUTHOR_DETAILS_BLOCKS.contains(&ActiveReadarrBlock::AuthorOverview)); + } + + #[test] + fn test_author_overview_blocks_contents() { + assert_eq!(AUTHOR_OVERVIEW_BLOCKS.len(), 1); + assert!(AUTHOR_OVERVIEW_BLOCKS.contains(&ActiveReadarrBlock::AuthorOverview)); + } + #[test] fn test_blocklist_blocks_contents() { assert_eq!(BLOCKLIST_BLOCKS.len(), 5); diff --git a/src/ui/readarr_ui/library/author_details_ui.rs b/src/ui/readarr_ui/library/author_details_ui.rs index f93fd8aa..4bf12992 100644 --- a/src/ui/readarr_ui/library/author_details_ui.rs +++ b/src/ui/readarr_ui/library/author_details_ui.rs @@ -13,6 +13,7 @@ use crate::models::readarr_models::{Book, ReadarrHistoryItem, ReadarrRelease}; use crate::models::servarr_data::readarr::readarr_data::{ AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, }; +use crate::ui::readarr_ui::library::author_overview_ui::AuthorOverviewUi; use crate::ui::readarr_ui::library::book_details_ui::BookDetailsUi; use crate::ui::readarr_ui::library::delete_book_ui::DeleteBookUi; use crate::ui::readarr_ui::readarr_ui_utils::create_history_event_details; @@ -45,6 +46,7 @@ impl DrawUi for AuthorDetailsUi { }; BookDetailsUi::accepts(route) || DeleteBookUi::accepts(route) + || AuthorOverviewUi::accepts(route) || AUTHOR_DETAILS_BLOCKS.contains(&active_readarr_block) } @@ -134,6 +136,10 @@ impl DrawUi for AuthorDetailsUi { if BookDetailsUi::accepts(route) { BookDetailsUi::draw(f, app, _area); } + + if AuthorOverviewUi::accepts(route) { + AuthorOverviewUi::draw(f, app, _area); + } } } } diff --git a/src/ui/readarr_ui/library/author_details_ui_tests.rs b/src/ui/readarr_ui/library/author_details_ui_tests.rs index ae1befa3..e288f7a6 100644 --- a/src/ui/readarr_ui/library/author_details_ui_tests.rs +++ b/src/ui/readarr_ui/library/author_details_ui_tests.rs @@ -7,8 +7,8 @@ mod tests { use crate::models::readarr_models::{Book, BookStatistics}; use crate::models::servarr_data::readarr::readarr_data::{ - AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, BOOK_DETAILS_BLOCKS, DELETE_BOOK_BLOCKS, - EDITION_DETAILS_BLOCKS, + AUTHOR_DETAILS_BLOCKS, AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, BOOK_DETAILS_BLOCKS, + DELETE_BOOK_BLOCKS, EDITION_DETAILS_BLOCKS, }; use crate::ui::DrawUi; use crate::ui::readarr_ui::library::author_details_ui::{ @@ -22,6 +22,7 @@ mod tests { author_details_blocks.extend(BOOK_DETAILS_BLOCKS); author_details_blocks.extend(EDITION_DETAILS_BLOCKS); author_details_blocks.extend(DELETE_BOOK_BLOCKS); + author_details_blocks.extend(AUTHOR_OVERVIEW_BLOCKS); ActiveReadarrBlock::iter().for_each(|active_readarr_block| { if author_details_blocks.contains(&active_readarr_block) { @@ -149,6 +150,7 @@ mod tests { } mod snapshot_tests { + use pretty_assertions::assert_str_eq; use rstest::rstest; use crate::app::App; @@ -337,6 +339,46 @@ mod tests { insta::assert_snapshot!(output); } + #[test] + fn test_author_details_ui_renders_author_overview_over_author_details() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_scrolling_the_author_overview_does_not_scroll_the_author_details_background() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorDetails.into()); + let before = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorDetailsUi::draw(f, app, f.area()); + }); + + app + .data + .readarr_data + .author_overview_modal + .as_mut() + .unwrap() + .overview + .offset = 3; + + let after = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorDetailsUi::draw(f, app, f.area()); + }); + assert_str_eq!(before, after); + assert_contains!( + before, + "Overview: some interesting description of the author" + ); + } + #[test] fn test_author_details_ui_renders_delete_book_over_author_details() { let mut app = App::test_default_fully_populated(); diff --git a/src/ui/readarr_ui/library/author_overview_ui.rs b/src/ui/readarr_ui/library/author_overview_ui.rs new file mode 100644 index 00000000..bafb3c9a --- /dev/null +++ b/src/ui/readarr_ui/library/author_overview_ui.rs @@ -0,0 +1,87 @@ +use crate::app::App; +use crate::models::Route; +use crate::models::readarr_models::Author; +use crate::models::servarr_data::readarr::readarr_data::AUTHOR_OVERVIEW_BLOCKS; +use crate::ui::styles::{primary_style, unmonitored_style}; +use crate::ui::utils::title_block_centered; +use crate::ui::widgets::loading_block::LoadingBlock; +use crate::ui::widgets::popup::Size; +use crate::ui::{DrawUi, draw_popup}; +use ratatui::Frame; +use ratatui::layout::Rect; +use ratatui::style::Style; +use ratatui::text::{Line, Span, Text}; +use ratatui::widgets::{Paragraph, Wrap}; + +#[cfg(test)] +#[path = "author_overview_ui_tests.rs"] +mod author_overview_ui_tests; + +pub(super) struct AuthorOverviewUi; + +impl DrawUi for AuthorOverviewUi { + fn accepts(route: Route) -> bool { + let Route::Readarr(active_readarr_block, _) = route else { + return false; + }; + AUTHOR_OVERVIEW_BLOCKS.contains(&active_readarr_block) + } + + fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { + if app.data.readarr_data.author_overview_modal.is_some() { + let draw_author_overview_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| { + draw_author_overview(f, app, popup_area); + }; + + draw_popup(f, app, draw_author_overview_popup, Size::Large); + } + } +} + +fn draw_author_overview(f: &mut Frame<'_>, app: &App<'_>, area: Rect) { + let block = title_block_centered("Overview"); + + match app.data.readarr_data.author_overview_modal.as_ref() { + Some(author_overview_modal) if !app.is_loading => { + let style = if app.data.readarr_data.authors.is_empty() { + primary_style() + } else { + style_from_author(app.data.readarr_data.authors.current_selection()) + }; + let overview = &author_overview_modal.overview; + let text = Text::from( + overview + .items + .iter() + .map(|line| overview_line(line, style)) + .collect::>>(), + ); + + let paragraph = Paragraph::new(text) + .block(block) + .wrap(Wrap { trim: false }) + .scroll((overview.offset, 0)); + + f.render_widget(paragraph, area); + } + _ => f.render_widget( + LoadingBlock::new( + app.is_loading || app.data.readarr_data.author_overview_modal.is_none(), + block, + ), + area, + ), + } +} + +fn style_from_author(author: &Author) -> Style { + if !author.monitored { + return unmonitored_style(); + } + + primary_style() +} + +fn overview_line(line: &str, style: Style) -> Line<'static> { + Line::from(Span::styled(line.trim_end().to_owned(), style)) +} diff --git a/src/ui/readarr_ui/library/author_overview_ui_tests.rs b/src/ui/readarr_ui/library/author_overview_ui_tests.rs new file mode 100644 index 00000000..c87bd4e2 --- /dev/null +++ b/src/ui/readarr_ui/library/author_overview_ui_tests.rs @@ -0,0 +1,205 @@ +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + use ratatui::style::Modifier; + use ratatui::text::Line; + use strum::IntoEnumIterator; + + use crate::app::App; + use crate::models::readarr_models::Author; + use crate::models::servarr_data::readarr::readarr_data::{ + AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, + }; + use crate::ui::DrawUi; + use crate::ui::readarr_ui::library::author_overview_ui::{ + AuthorOverviewUi, overview_line, style_from_author, + }; + use crate::ui::styles::{primary_style, unmonitored_style}; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; + + #[test] + fn test_author_overview_ui_accepts() { + ActiveReadarrBlock::iter().for_each(|active_readarr_block| { + if AUTHOR_OVERVIEW_BLOCKS.contains(&active_readarr_block) { + assert!(AuthorOverviewUi::accepts(active_readarr_block.into())); + } else { + assert!(!AuthorOverviewUi::accepts(active_readarr_block.into())); + } + }); + } + + #[test] + fn test_style_from_author_monitored() { + let author = Author { + monitored: true, + ..Author::default() + }; + + let style = style_from_author(&author); + + assert_eq!(style, primary_style()); + } + + #[test] + fn test_style_from_author_unmonitored() { + let author = Author { + monitored: false, + ..Author::default() + }; + + let style = style_from_author(&author); + + assert_eq!(style, unmonitored_style()); + } + + #[test] + fn test_overview_line_does_not_split_a_label_from_a_colon_in_the_prose() { + let line = overview_line( + "He was born in Madison, Wisconsin: a city he has never really left.", + primary_style(), + ); + + assert_eq!( + span_contents(&line), + vec!["He was born in Madison, Wisconsin: a city he has never really left."] + ); + } + + #[test] + fn test_overview_line_renders_the_prose_without_bolding_it() { + let line = overview_line("Overview: a prose line", primary_style()); + + assert_eq!(line.spans.len(), 1); + assert!(!line.spans[0].style.add_modifier.contains(Modifier::BOLD)); + } + + #[test] + fn test_overview_line_applies_the_given_style() { + let line = overview_line("an unmonitored author", unmonitored_style()); + + assert_eq!(line.spans[0].style.fg, unmonitored_style().fg); + } + + #[test] + fn test_overview_line_trims_a_trailing_carriage_return() { + let line = overview_line( + "His first novel took him seven years to finish.\r", + primary_style(), + ); + + assert_eq!( + span_contents(&line), + vec!["His first novel took him seven years to finish."] + ); + } + + #[test] + fn test_overview_line_renders_a_carriage_return_only_line_as_blank() { + let line = overview_line("\r", primary_style()); + + assert_eq!(span_contents(&line), vec![""]); + } + + fn span_contents(line: &Line<'_>) -> Vec { + line + .spans + .iter() + .map(|span| span.content.to_string()) + .collect() + } + + mod snapshot_tests { + use crate::models::ScrollableText; + use crate::models::servarr_data::readarr::modals::AuthorOverviewModal; + use crate::models::stateful_table::StatefulTable; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + use super::*; + + #[test] + fn test_author_overview_ui_renders() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorOverviewUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_author_overview_ui_renders_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorOverviewUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_author_overview_ui_renders_scrolled() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + app + .data + .readarr_data + .author_overview_modal + .as_mut() + .unwrap() + .overview + .offset = 2; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorOverviewUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_author_overview_ui_renders_an_author_with_no_overview() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + app.data.readarr_data.author_overview_modal = Some(AuthorOverviewModal { + overview: ScrollableText::with_string(String::new()), + }); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorOverviewUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_author_overview_ui_renders_nothing_when_the_author_overview_modal_is_undefined() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + app.data.readarr_data.author_overview_modal = None; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorOverviewUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_author_overview_ui_renders_with_zero_authors() { + let mut app = App::test_default_fully_populated(); + app.data.readarr_data.authors = StatefulTable::default(); + app.push_navigation_stack(ActiveReadarrBlock::AuthorOverview.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AuthorOverviewUi::draw(f, app, f.area()); + }); + + assert_contains!(output, "some interesting description of the author"); + } + } +} diff --git a/src/ui/readarr_ui/library/library_ui_tests.rs b/src/ui/readarr_ui/library/library_ui_tests.rs index 1d0b4406..f491ca53 100644 --- a/src/ui/readarr_ui/library/library_ui_tests.rs +++ b/src/ui/readarr_ui/library/library_ui_tests.rs @@ -4,9 +4,9 @@ mod tests { use crate::models::readarr_models::{Author, AuthorStatistics, AuthorStatus}; use crate::models::servarr_data::readarr::readarr_data::{ - ADD_AUTHOR_BLOCKS, AUTHOR_DETAILS_BLOCKS, ActiveReadarrBlock, BOOK_DETAILS_BLOCKS, - DELETE_AUTHOR_BLOCKS, DELETE_BOOK_BLOCKS, EDIT_AUTHOR_BLOCKS, EDITION_DETAILS_BLOCKS, - LIBRARY_BLOCKS, + ADD_AUTHOR_BLOCKS, AUTHOR_DETAILS_BLOCKS, AUTHOR_OVERVIEW_BLOCKS, ActiveReadarrBlock, + BOOK_DETAILS_BLOCKS, DELETE_AUTHOR_BLOCKS, DELETE_BOOK_BLOCKS, EDIT_AUTHOR_BLOCKS, + EDITION_DETAILS_BLOCKS, LIBRARY_BLOCKS, }; use crate::ui::DrawUi; use crate::ui::readarr_ui::library::{LibraryUi, decorate_author_row_with_style}; @@ -18,6 +18,7 @@ mod tests { fn test_library_ui_accepts() { let mut blocks = LIBRARY_BLOCKS.to_vec(); blocks.extend(AUTHOR_DETAILS_BLOCKS); + blocks.extend(AUTHOR_OVERVIEW_BLOCKS); blocks.extend(BOOK_DETAILS_BLOCKS); blocks.extend(EDITION_DETAILS_BLOCKS); blocks.extend(ADD_AUTHOR_BLOCKS); diff --git a/src/ui/readarr_ui/library/mod.rs b/src/ui/readarr_ui/library/mod.rs index 2467a643..2f6a3655 100644 --- a/src/ui/readarr_ui/library/mod.rs +++ b/src/ui/readarr_ui/library/mod.rs @@ -30,6 +30,7 @@ use crate::{ mod add_author_ui; mod author_details_ui; +mod author_overview_ui; mod book_details_ui; mod delete_author_ui; mod delete_book_ui; diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorDetails_0.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorDetails_0.snap index bf512d36..42cd616f 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorDetails_0.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorDetails_0.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistoryDetails_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistoryDetails_1.snap index 00dd5514..894486a6 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistoryDetails_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistoryDetails_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ─────────────╭─────────────────────────────────── Details ───────────────────────────────────╮───────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistorySortPrompt_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistorySortPrompt_1.snap index 7e6599c4..9c5a6818 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistorySortPrompt_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistorySortPrompt_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistory_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistory_1.snap index 941f5dcc..8a4b2a62 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistory_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AuthorHistory_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_0.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_0.snap index 937cd23e..b511dc00 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_0.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_0.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────── Automatic Author Search ────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_1.snap index da4145de..79d6d417 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────── Automatic Author Search ────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_2.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_2.snap index 84092693..5b2ea803 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_2.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_AutomaticallySearchAuthorPrompt_2.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────── Automatic Author Search ────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistoryError_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistoryError_1.snap index bfd24b55..d45da62e 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistoryError_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistoryError_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistory_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistory_1.snap index 5915ff9f..19a84629 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistory_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_FilterAuthorHistory_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchConfirmPrompt_2.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchConfirmPrompt_2.snap index f52c05a8..49b8043e 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchConfirmPrompt_2.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchConfirmPrompt_2.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ ╭───────────────── Download Rejected Release ──────────────────╮ │ │╭ Author Details ──────────────────────│ Do you really want to download the rejected release: Test │───────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchSortPrompt_2.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchSortPrompt_2.snap index 6655add5..af676b20 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchSortPrompt_2.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearchSortPrompt_2.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearch_2.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearch_2.snap index 2de5af4d..9613ce4f 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearch_2.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ManualAuthorSearch_2.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistoryError_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistoryError_1.snap index 2d943a33..0a17a013 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistoryError_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistoryError_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistory_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistory_1.snap index b81bc8bb..fd17c74d 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistory_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchAuthorHistory_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooksError_0.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooksError_0.snap index cebdff92..68f27a1c 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooksError_0.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooksError_0.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooks_0.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooks_0.snap index e3a9fdbb..3ef32721 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooks_0.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_SearchBooks_0.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_0.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_0.snap index 8cec0e85..0c096c2f 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_0.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_0.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────────── Update and Scan ────────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_1.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_1.snap index 4315396b..71d50e3a 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_1.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_1.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────────── Update and Scan ────────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_2.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_2.snap index 13882a49..4aa3a45d 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_2.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_UpdateAndScanAuthorPrompt_2.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────────── Update and Scan ────────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_author_overview_over_author_details.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_author_overview_over_author_details.snap new file mode 100644 index 00000000..e9623818 --- /dev/null +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_author_overview_over_author_details.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/readarr_ui/library/author_details_ui_tests.rs +expression: output +--- + + + + ╭ Test Author ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Author: Test Author │ + │Status: Continuing │ + │Genres: sci╭─────────────────────────────────────────────────────── Overview ───────────────────────────────────────────────────────╮ │ + │Rating: N/A│some interesting description of the author │ │ + │Path: /nfs/│ │ │ + │Quality Pro│He was born in Madison, Wisconsin: a city he has never really left. │ │ + │Metadata Pr│ │ │ + │Monitored: │His first novel took him seven years to finish. │ │ + │Overview: s│ │took him │ + │seven years│ │ │ + │ │ │ │ + │ │ │ │ + │╭ Author D│ │───────────╮│ + ││ Books │ H│ │ ││ + ││──────────│ │───────────││ + ││ Monitor│ │ ││ + ││=> 🏷 │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_automatic_search_prompt_over_author_details.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_automatic_search_prompt_over_author_details.snap index 937cd23e..b511dc00 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_automatic_search_prompt_over_author_details.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_automatic_search_prompt_over_author_details.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────── Automatic Author Search ────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_book_details_over_author_details.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_book_details_over_author_details.snap index b681ef93..36b06222 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_book_details_over_author_details.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_book_details_over_author_details.snap @@ -14,8 +14,8 @@ expression: output │Qual│ │ │ │Meta│ │ │ │Moni│ │ │ - │Over│ │ │ - │ │ │ │ + │Over│ │im │ + │seve│ │ │ │ │ │ │ │ │ │ │ │╭ A│ │─────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_delete_book_over_author_details.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_delete_book_over_author_details.snap index 6a98fe7d..ec5d4151 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_delete_book_over_author_details.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_delete_book_over_author_details.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭────────────────────── Delete Book ──────────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_statistics.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_statistics.snap index 82d57a62..4c3bf601 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_statistics.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_statistics.snap @@ -17,7 +17,7 @@ expression: output │Books: 3 │ │Files: 2/3 │ │Size on Disk: 3.30 GB │ - │Overview: some interesting description of the author │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ ││ Books │ History │ Author Search ││ ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_update_and_scan_prompt_over_author_details.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_update_and_scan_prompt_over_author_details.snap index 8cec0e85..0c096c2f 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_update_and_scan_prompt_over_author_details.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__author_details_ui_renders_update_and_scan_prompt_over_author_details.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────╭──────────────────── Update and Scan ────────────────────╮───────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorDetails.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorDetails.snap index 5ffdc770..e81cb685 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorDetails.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorDetails.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistory.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistory.snap index 5ffdc770..e81cb685 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistory.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistory.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistoryDetails.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistoryDetails.snap index 420df740..90609ffe 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistoryDetails.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_AuthorHistoryDetails.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ─────────────╭─────────────────────────────────── Details ───────────────────────────────────╮───────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_ManualAuthorSearch.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_ManualAuthorSearch.snap index 7f1eb28e..85109ff3 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_ManualAuthorSearch.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__empty_author_details_ManualAuthorSearch.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorDetails.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorDetails.snap index 7f1eb28e..85109ff3 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorDetails.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorDetails.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorHistory.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorHistory.snap index 7f1eb28e..85109ff3 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorHistory.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_AuthorHistory.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_ManualAuthorSearch.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_ManualAuthorSearch.snap index 7f1eb28e..85109ff3 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_ManualAuthorSearch.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_details_ui__author_details_ui_tests__tests__snapshot_tests__loading_author_details_ManualAuthorSearch.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders.snap new file mode 100644 index 00000000..75be124b --- /dev/null +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/readarr_ui/library/author_overview_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────────────── Overview ───────────────────────────────────────────────────────╮ + │some interesting description of the author │ + │ │ + │He was born in Madison, Wisconsin: a city he has never really left. │ + │ │ + │His first novel took him seven years to finish. │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_an_author_with_no_overview.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_an_author_with_no_overview.snap new file mode 100644 index 00000000..d4a877ae --- /dev/null +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_an_author_with_no_overview.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/readarr_ui/library/author_overview_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────────────── Overview ───────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_loading.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_loading.snap new file mode 100644 index 00000000..a8a3c9e0 --- /dev/null +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_loading.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/readarr_ui/library/author_overview_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────────────── Overview ───────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_nothing_when_the_author_overview_modal_is_undefined.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_nothing_when_the_author_overview_modal_is_undefined.snap new file mode 100644 index 00000000..b080be01 --- /dev/null +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_nothing_when_the_author_overview_modal_is_undefined.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/readarr_ui/library/author_overview_ui_tests.rs +expression: output +--- + diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_scrolled.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_scrolled.snap new file mode 100644 index 00000000..4eb9e128 --- /dev/null +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__author_overview_ui__author_overview_ui_tests__tests__snapshot_tests__author_overview_ui_renders_scrolled.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/readarr_ui/library/author_overview_ui_tests.rs +expression: output +--- + + + + + + + ╭─────────────────────────────────────────────────────── Overview ───────────────────────────────────────────────────────╮ + │He was born in Madison, Wisconsin: a city he has never really left. │ + │ │ + │His first novel took him seven years to finish. │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__edit_author_ui__edit_author_ui_tests__tests__snapshot_tests__edit_author_ui_renders_over_author_details.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__edit_author_ui__edit_author_ui_tests__tests__snapshot_tests__edit_author_ui_renders_over_author_details.snap index 63e608f7..53654aca 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__edit_author_ui__edit_author_ui_tests__tests__snapshot_tests__edit_author_ui_renders_over_author_details.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__edit_author_ui__edit_author_ui_tests__tests__snapshot_tests__edit_author_ui_renders_over_author_details.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: St│ │ │ │Metadata Profile: S│ │ │ │Monitored: Yes │ │ │ - │Overview: some inte│ │ │ - │ │ │ │ + │Overview: some inte│ │st novel took him │ + │seven years to fini│ │ │ │ │ │ │ │ │ ╭───╮ │ │ │╭ Author Details │ Monitored: │ ✔ │ │────────────────────╮│ diff --git a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_author_details_over_library.snap b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_author_details_over_library.snap index cc7cd2a4..5a645d25 100644 --- a/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_author_details_over_library.snap +++ b/src/ui/readarr_ui/library/snapshots/managarr__ui__readarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_author_details_over_library.snap @@ -14,8 +14,8 @@ expression: output │Quality Profile: Standard │ │Metadata Profile: Standard │ │Monitored: Yes │ - │Overview: some interesting description of the author │ - │ │ + │Overview: some interesting description of the authorHe was born in Madison, Wisconsin: a city he has never really left.His first novel took him │ + │seven years to finish. │ │ │ │ │ │╭ Author Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│