feat: Support for updating all Lidarr artists in both the CLI and TUI
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::models::Route;
|
||||
#[path = "lidarr_context_clues_tests.rs"]
|
||||
mod lidarr_context_clues_tests;
|
||||
|
||||
pub static ARTISTS_CONTEXT_CLUES: [ContextClue; 7] = [
|
||||
pub static ARTISTS_CONTEXT_CLUES: [ContextClue; 8] = [
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
||||
DEFAULT_KEYBINDINGS.toggle_monitoring.desc,
|
||||
@@ -20,6 +20,7 @@ pub static ARTISTS_CONTEXT_CLUES: [ContextClue; 7] = [
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.update, "update all"),
|
||||
(DEFAULT_KEYBINDINGS.esc, "cancel filter"),
|
||||
];
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ mod tests {
|
||||
DEFAULT_KEYBINDINGS.refresh.desc
|
||||
)
|
||||
);
|
||||
assert_some_eq_x!(
|
||||
artists_context_clues_iter.next(),
|
||||
&(DEFAULT_KEYBINDINGS.update, "update all")
|
||||
);
|
||||
assert_some_eq_x!(
|
||||
artists_context_clues_iter.next(),
|
||||
&(DEFAULT_KEYBINDINGS.esc, "cancel filter")
|
||||
|
||||
@@ -77,6 +77,7 @@ mod tests {
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::cli::lidarr::get_command_handler::LidarrGetCommand;
|
||||
use crate::cli::lidarr::refresh_command_handler::LidarrRefreshCommand;
|
||||
use crate::{
|
||||
app::App,
|
||||
cli::{
|
||||
@@ -170,6 +171,28 @@ mod tests {
|
||||
assert_ok!(&result);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_lidarr_cli_handler_delegates_refresh_commands_to_the_refresh_command_handler() {
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(LidarrEvent::UpdateAllArtists.into()))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
Ok(Serdeable::Lidarr(LidarrSerdeable::Value(
|
||||
json!({"testResponse": "response"}),
|
||||
)))
|
||||
});
|
||||
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||
let refresh_series_command = LidarrCommand::Refresh(LidarrRefreshCommand::AllArtists);
|
||||
|
||||
let result = LidarrCliHandler::with(&app_arc, refresh_series_command, &mut mock_network)
|
||||
.handle()
|
||||
.await;
|
||||
|
||||
assert_ok!(&result);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_toggle_artist_monitoring_command() {
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
|
||||
@@ -5,6 +5,7 @@ use clap::{Subcommand, arg};
|
||||
use delete_command_handler::{LidarrDeleteCommand, LidarrDeleteCommandHandler};
|
||||
use get_command_handler::{LidarrGetCommand, LidarrGetCommandHandler};
|
||||
use list_command_handler::{LidarrListCommand, LidarrListCommandHandler};
|
||||
use refresh_command_handler::{LidarrRefreshCommand, LidarrRefreshCommandHandler};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::network::lidarr_network::LidarrEvent;
|
||||
@@ -15,6 +16,7 @@ use super::{CliCommandHandler, Command};
|
||||
mod delete_command_handler;
|
||||
mod get_command_handler;
|
||||
mod list_command_handler;
|
||||
mod refresh_command_handler;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "lidarr_command_tests.rs"]
|
||||
@@ -37,6 +39,11 @@ pub enum LidarrCommand {
|
||||
about = "Commands to list attributes from your Lidarr instance"
|
||||
)]
|
||||
List(LidarrListCommand),
|
||||
#[command(
|
||||
subcommand,
|
||||
about = "Commands to refresh the data in your Lidarr instance"
|
||||
)]
|
||||
Refresh(LidarrRefreshCommand),
|
||||
#[command(
|
||||
about = "Toggle monitoring for the specified artist corresponding to the given artist ID"
|
||||
)]
|
||||
@@ -92,6 +99,11 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, LidarrCommand> for LidarrCliHandler<'a, '
|
||||
.handle()
|
||||
.await?
|
||||
}
|
||||
LidarrCommand::Refresh(refresh_command) => {
|
||||
LidarrRefreshCommandHandler::with(self.app, refresh_command, self.network)
|
||||
.handle()
|
||||
.await?
|
||||
}
|
||||
LidarrCommand::ToggleArtistMonitoring { artist_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use clap::Subcommand;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
app::App,
|
||||
cli::{CliCommandHandler, Command},
|
||||
network::{NetworkTrait, lidarr_network::LidarrEvent},
|
||||
};
|
||||
|
||||
use super::LidarrCommand;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "refresh_command_handler_tests.rs"]
|
||||
mod refresh_command_handler_tests;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Subcommand)]
|
||||
pub enum LidarrRefreshCommand {
|
||||
#[command(about = "Refresh all artist data for all artists in your Lidarr library")]
|
||||
AllArtists,
|
||||
}
|
||||
|
||||
impl From<LidarrRefreshCommand> for Command {
|
||||
fn from(value: LidarrRefreshCommand) -> Self {
|
||||
Command::Lidarr(LidarrCommand::Refresh(value))
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct LidarrRefreshCommandHandler<'a, 'b> {
|
||||
_app: &'a Arc<Mutex<App<'b>>>,
|
||||
command: LidarrRefreshCommand,
|
||||
network: &'a mut dyn NetworkTrait,
|
||||
}
|
||||
|
||||
impl<'a, 'b> CliCommandHandler<'a, 'b, LidarrRefreshCommand>
|
||||
for LidarrRefreshCommandHandler<'a, 'b>
|
||||
{
|
||||
fn with(
|
||||
_app: &'a Arc<Mutex<App<'b>>>,
|
||||
command: LidarrRefreshCommand,
|
||||
network: &'a mut dyn NetworkTrait,
|
||||
) -> Self {
|
||||
LidarrRefreshCommandHandler {
|
||||
_app,
|
||||
command,
|
||||
network,
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(self) -> anyhow::Result<String> {
|
||||
let result = match self.command {
|
||||
LidarrRefreshCommand::AllArtists => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(LidarrEvent::UpdateAllArtists.into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::Cli;
|
||||
use crate::cli::{
|
||||
Command,
|
||||
lidarr::{LidarrCommand, refresh_command_handler::LidarrRefreshCommand},
|
||||
};
|
||||
use clap::CommandFactory;
|
||||
|
||||
#[test]
|
||||
fn test_lidarr_refresh_command_from() {
|
||||
let command = LidarrRefreshCommand::AllArtists;
|
||||
|
||||
let result = Command::from(command.clone());
|
||||
|
||||
assert_eq!(result, Command::Lidarr(LidarrCommand::Refresh(command)));
|
||||
}
|
||||
|
||||
mod cli {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_refresh_all_artists_has_no_arg_requirements() {
|
||||
let result =
|
||||
Cli::command().try_get_matches_from(["managarr", "lidarr", "refresh", "all-artists"]);
|
||||
|
||||
assert_ok!(&result);
|
||||
}
|
||||
}
|
||||
|
||||
mod handler {
|
||||
use std::sync::Arc;
|
||||
|
||||
use mockall::predicate::eq;
|
||||
use serde_json::json;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{app::App, cli::lidarr::refresh_command_handler::LidarrRefreshCommandHandler};
|
||||
use crate::{
|
||||
cli::{CliCommandHandler, lidarr::refresh_command_handler::LidarrRefreshCommand},
|
||||
network::lidarr_network::LidarrEvent,
|
||||
};
|
||||
use crate::{
|
||||
models::{Serdeable, lidarr_models::LidarrSerdeable},
|
||||
network::{MockNetworkTrait, NetworkEvent},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_refresh_all_artists_command() {
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(LidarrEvent::UpdateAllArtists.into()))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
Ok(Serdeable::Lidarr(LidarrSerdeable::Value(
|
||||
json!({"testResponse": "response"}),
|
||||
)))
|
||||
});
|
||||
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||
let refresh_command = LidarrRefreshCommand::AllArtists;
|
||||
|
||||
let result = LidarrRefreshCommandHandler::with(&app_arc, refresh_command, &mut mock_network)
|
||||
.handle()
|
||||
.await;
|
||||
|
||||
assert_ok!(&result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,18 @@
|
||||
mod tests {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use serde_json::Number;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::App;
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::assert_modal_absent;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::handlers::lidarr_handlers::library::{LibraryHandler, artists_sorting_options};
|
||||
use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus};
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, LIBRARY_BLOCKS};
|
||||
use crate::network::lidarr_network::LidarrEvent;
|
||||
use crate::{assert_modal_absent, assert_navigation_popped, assert_navigation_pushed};
|
||||
|
||||
#[test]
|
||||
fn test_library_handler_accepts() {
|
||||
@@ -267,6 +267,173 @@ mod tests {
|
||||
assert!(!app.is_routing);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_key() {
|
||||
let mut app = App::test_default();
|
||||
app
|
||||
.data
|
||||
.lidarr_data
|
||||
.artists
|
||||
.set_items(vec![Artist::default()]);
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.update.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::Artists,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_navigation_pushed!(app, ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_key_no_op_when_not_ready() {
|
||||
let mut app = App::test_default();
|
||||
app.is_loading = true;
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app
|
||||
.data
|
||||
.lidarr_data
|
||||
.artists
|
||||
.set_items(vec![Artist::default()]);
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.update.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::Artists,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveLidarrBlock::Artists.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_prompt_confirm_submit() {
|
||||
let mut app = App::test_default();
|
||||
app
|
||||
.data
|
||||
.lidarr_data
|
||||
.artists
|
||||
.set_items(vec![Artist::default()]);
|
||||
app.data.lidarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.submit.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert!(app.data.lidarr_data.prompt_confirm);
|
||||
assert_some_eq_x!(
|
||||
&app.data.lidarr_data.prompt_confirm_action,
|
||||
&LidarrEvent::UpdateAllArtists
|
||||
);
|
||||
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_prompt_decline_submit() {
|
||||
let mut app = App::test_default();
|
||||
app
|
||||
.data
|
||||
.lidarr_data
|
||||
.artists
|
||||
.set_items(vec![Artist::default()]);
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.submit.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
||||
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_prompt_esc() {
|
||||
let mut app = App::test_default();
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
app.data.lidarr_data.prompt_confirm = true;
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_prompt_left_right() {
|
||||
let mut app = App::test_default();
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.left.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert!(app.data.lidarr_data.prompt_confirm);
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.right.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_all_artists_prompt_confirm_key() {
|
||||
let mut app = App::test_default();
|
||||
app
|
||||
.data
|
||||
.lidarr_data
|
||||
.artists
|
||||
.set_items(vec![Artist::default()]);
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
|
||||
LibraryHandler::new(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
&mut app,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert!(app.data.lidarr_data.prompt_confirm);
|
||||
assert_some_eq_x!(
|
||||
&app.data.lidarr_data.prompt_confirm_action,
|
||||
&LidarrEvent::UpdateAllArtists
|
||||
);
|
||||
assert_navigation_popped!(app, ActiveLidarrBlock::Artists.into());
|
||||
}
|
||||
|
||||
fn artists_vec() -> Vec<Artist> {
|
||||
vec![
|
||||
Artist {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
app::App,
|
||||
event::Key,
|
||||
handlers::{KeyEventHandler, handle_clear_errors},
|
||||
handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle},
|
||||
matches_key,
|
||||
models::{
|
||||
BlockSelectionState,
|
||||
@@ -108,21 +108,39 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for LibraryHandler<'a, '
|
||||
}
|
||||
|
||||
fn handle_left_right_action(&mut self) {
|
||||
if self.active_lidarr_block == ActiveLidarrBlock::Artists {
|
||||
handle_change_tab_left_right_keys(self.app, self.key);
|
||||
match self.active_lidarr_block {
|
||||
ActiveLidarrBlock::Artists => handle_change_tab_left_right_keys(self.app, self.key),
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt => handle_prompt_toggle(self.app, self.key),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_submit(&mut self) {}
|
||||
fn handle_submit(&mut self) {
|
||||
if self.active_lidarr_block == ActiveLidarrBlock::UpdateAllArtistsPrompt {
|
||||
if self.app.data.lidarr_data.prompt_confirm {
|
||||
self.app.data.lidarr_data.prompt_confirm_action = Some(LidarrEvent::UpdateAllArtists);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_esc(&mut self) {
|
||||
handle_clear_errors(self.app);
|
||||
match self.active_lidarr_block {
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt => {
|
||||
self.app.pop_navigation_stack();
|
||||
self.app.data.lidarr_data.prompt_confirm = false;
|
||||
}
|
||||
_ => {
|
||||
handle_clear_errors(self.app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_char_key_event(&mut self) {
|
||||
let key = self.key;
|
||||
if self.active_lidarr_block == ActiveLidarrBlock::Artists {
|
||||
match key {
|
||||
match self.active_lidarr_block {
|
||||
ActiveLidarrBlock::Artists => match key {
|
||||
_ if matches_key!(toggle_monitoring, key) => {
|
||||
self.app.data.lidarr_data.prompt_confirm = true;
|
||||
self.app.data.lidarr_data.prompt_confirm_action = Some(
|
||||
@@ -133,11 +151,25 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for LibraryHandler<'a, '
|
||||
.app
|
||||
.pop_and_push_navigation_stack(self.active_lidarr_block.into());
|
||||
}
|
||||
_ if matches_key!(update, key) => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
}
|
||||
_ if matches_key!(refresh, key) => {
|
||||
self.app.should_refresh = true;
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt => {
|
||||
if matches_key!(confirm, key) {
|
||||
self.app.data.lidarr_data.prompt_confirm = true;
|
||||
self.app.data.lidarr_data.prompt_confirm_action = Some(LidarrEvent::UpdateAllArtists);
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ impl<'a> Default for LidarrData<'a> {
|
||||
quality_profile_map: BiMap::new(),
|
||||
root_folders: StatefulTable::default(),
|
||||
selected_block: BlockSelectionState::default(),
|
||||
start_time: Utc::now(),
|
||||
start_time: DateTime::default(),
|
||||
tags_map: BiMap::new(),
|
||||
version: String::new(),
|
||||
main_tabs: TabState::new(vec![TabRoute {
|
||||
@@ -112,19 +112,21 @@ pub enum ActiveLidarrBlock {
|
||||
DeleteArtistConfirmPrompt,
|
||||
DeleteArtistToggleDeleteFile,
|
||||
DeleteArtistToggleAddListExclusion,
|
||||
SearchArtists,
|
||||
SearchArtistsError,
|
||||
FilterArtists,
|
||||
FilterArtistsError,
|
||||
SearchArtists,
|
||||
SearchArtistsError,
|
||||
UpdateAllArtistsPrompt,
|
||||
}
|
||||
|
||||
pub static LIBRARY_BLOCKS: [ActiveLidarrBlock; 6] = [
|
||||
pub static LIBRARY_BLOCKS: [ActiveLidarrBlock; 7] = [
|
||||
ActiveLidarrBlock::Artists,
|
||||
ActiveLidarrBlock::ArtistsSortPrompt,
|
||||
ActiveLidarrBlock::SearchArtists,
|
||||
ActiveLidarrBlock::SearchArtistsError,
|
||||
ActiveLidarrBlock::FilterArtists,
|
||||
ActiveLidarrBlock::FilterArtistsError,
|
||||
ActiveLidarrBlock::SearchArtists,
|
||||
ActiveLidarrBlock::SearchArtistsError,
|
||||
ActiveLidarrBlock::UpdateAllArtistsPrompt,
|
||||
];
|
||||
|
||||
pub static DELETE_ARTIST_BLOCKS: [ActiveLidarrBlock; 4] = [
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::models::{
|
||||
Route,
|
||||
servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, LidarrData},
|
||||
use crate::app::lidarr::lidarr_context_clues::ARTISTS_CONTEXT_CLUES;
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||
DELETE_ARTIST_BLOCKS, DELETE_ARTIST_SELECTION_BLOCKS,
|
||||
};
|
||||
use crate::models::{
|
||||
BlockSelectionState, Route,
|
||||
servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, LIBRARY_BLOCKS, LidarrData},
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
|
||||
#[test]
|
||||
fn test_from_active_lidarr_block_to_route() {
|
||||
@@ -36,4 +40,77 @@ mod tests {
|
||||
assert!(!lidarr_data.delete_artist_files);
|
||||
assert!(!lidarr_data.add_import_list_exclusion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lidarr_data_default() {
|
||||
let lidarr_data = LidarrData::default();
|
||||
|
||||
assert!(!lidarr_data.add_import_list_exclusion);
|
||||
assert_is_empty!(lidarr_data.artists);
|
||||
assert!(!lidarr_data.delete_artist_files);
|
||||
assert_is_empty!(lidarr_data.disk_space_vec);
|
||||
assert_is_empty!(lidarr_data.downloads);
|
||||
assert_is_empty!(lidarr_data.metadata_profile_map);
|
||||
assert!(!lidarr_data.prompt_confirm);
|
||||
assert_none!(lidarr_data.prompt_confirm_action);
|
||||
assert_is_empty!(lidarr_data.quality_profile_map);
|
||||
assert_is_empty!(lidarr_data.root_folders);
|
||||
assert_eq!(lidarr_data.selected_block, BlockSelectionState::default());
|
||||
assert_eq!(lidarr_data.start_time, <DateTime<Utc>>::default());
|
||||
assert_is_empty!(lidarr_data.tags_map);
|
||||
assert_is_empty!(lidarr_data.version);
|
||||
|
||||
assert_eq!(lidarr_data.main_tabs.tabs.len(), 1);
|
||||
|
||||
assert_str_eq!(lidarr_data.main_tabs.tabs[0].title, "Library");
|
||||
assert_eq!(
|
||||
lidarr_data.main_tabs.tabs[0].route,
|
||||
ActiveLidarrBlock::Artists.into()
|
||||
);
|
||||
assert_some_eq_x!(
|
||||
&lidarr_data.main_tabs.tabs[0].contextual_help,
|
||||
&ARTISTS_CONTEXT_CLUES
|
||||
);
|
||||
assert_none!(lidarr_data.main_tabs.tabs[0].config);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_library_blocks_contains_expected_blocks() {
|
||||
assert_eq!(LIBRARY_BLOCKS.len(), 7);
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::Artists));
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::ArtistsSortPrompt));
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::SearchArtists));
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::SearchArtistsError));
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::FilterArtists));
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::FilterArtistsError));
|
||||
assert!(LIBRARY_BLOCKS.contains(&ActiveLidarrBlock::UpdateAllArtistsPrompt));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_artist_blocks_contents() {
|
||||
assert_eq!(DELETE_ARTIST_BLOCKS.len(), 4);
|
||||
assert!(DELETE_ARTIST_BLOCKS.contains(&ActiveLidarrBlock::DeleteArtistPrompt));
|
||||
assert!(DELETE_ARTIST_BLOCKS.contains(&ActiveLidarrBlock::DeleteArtistConfirmPrompt));
|
||||
assert!(DELETE_ARTIST_BLOCKS.contains(&ActiveLidarrBlock::DeleteArtistToggleDeleteFile));
|
||||
assert!(DELETE_ARTIST_BLOCKS.contains(&ActiveLidarrBlock::DeleteArtistToggleAddListExclusion));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_artist_selection_blocks_ordering() {
|
||||
let mut delete_artist_block_iter = DELETE_ARTIST_SELECTION_BLOCKS.iter();
|
||||
|
||||
assert_eq!(
|
||||
delete_artist_block_iter.next().unwrap(),
|
||||
&[ActiveLidarrBlock::DeleteArtistToggleDeleteFile]
|
||||
);
|
||||
assert_eq!(
|
||||
delete_artist_block_iter.next().unwrap(),
|
||||
&[ActiveLidarrBlock::DeleteArtistToggleAddListExclusion]
|
||||
);
|
||||
assert_eq!(
|
||||
delete_artist_block_iter.next().unwrap(),
|
||||
&[ActiveLidarrBlock::DeleteArtistConfirmPrompt]
|
||||
);
|
||||
assert_none!(delete_artist_block_iter.next());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ use crate::{
|
||||
mod modals_tests;
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct AddSeriesModal {
|
||||
pub root_folder_list: StatefulList<RootFolder>,
|
||||
pub monitor_list: StatefulList<SeriesMonitor>,
|
||||
@@ -130,6 +131,7 @@ impl From<&SonarrData<'_>> for EditIndexerModal {
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct EditSeriesModal {
|
||||
pub series_type_list: StatefulList<SeriesType>,
|
||||
pub quality_profile_list: StatefulList<String>,
|
||||
@@ -260,6 +262,7 @@ impl Default for EpisodeDetailsModal {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(Debug))]
|
||||
pub struct SeasonDetailsModal {
|
||||
pub episodes: StatefulTable<Episode>,
|
||||
pub episode_files: StatefulTable<EpisodeFile>,
|
||||
|
||||
@@ -82,39 +82,39 @@ mod tests {
|
||||
let sonarr_data = SonarrData::default();
|
||||
|
||||
assert!(!sonarr_data.add_list_exclusion);
|
||||
assert!(sonarr_data.add_searched_series.is_none());
|
||||
assert!(sonarr_data.add_series_search.is_none());
|
||||
assert!(sonarr_data.add_series_modal.is_none());
|
||||
assert!(sonarr_data.blocklist.is_empty());
|
||||
assert_none!(sonarr_data.add_searched_series);
|
||||
assert_none!(sonarr_data.add_series_search);
|
||||
assert_none!(sonarr_data.add_series_modal);
|
||||
assert_is_empty!(sonarr_data.blocklist);
|
||||
assert!(!sonarr_data.delete_series_files);
|
||||
assert!(sonarr_data.downloads.is_empty());
|
||||
assert!(sonarr_data.disk_space_vec.is_empty());
|
||||
assert!(sonarr_data.edit_indexer_modal.is_none());
|
||||
assert!(sonarr_data.edit_root_folder.is_none());
|
||||
assert!(sonarr_data.edit_series_modal.is_none());
|
||||
assert!(sonarr_data.history.is_empty());
|
||||
assert!(sonarr_data.indexers.is_empty());
|
||||
assert!(sonarr_data.indexer_settings.is_none());
|
||||
assert!(sonarr_data.indexer_test_errors.is_none());
|
||||
assert!(sonarr_data.indexer_test_all_results.is_none());
|
||||
assert!(sonarr_data.language_profiles_map.is_empty());
|
||||
assert!(sonarr_data.logs.is_empty());
|
||||
assert!(sonarr_data.log_details.is_empty());
|
||||
assert_is_empty!(sonarr_data.downloads);
|
||||
assert_is_empty!(sonarr_data.disk_space_vec);
|
||||
assert_none!(sonarr_data.edit_indexer_modal);
|
||||
assert_none!(sonarr_data.edit_root_folder);
|
||||
assert_none!(sonarr_data.edit_series_modal);
|
||||
assert_is_empty!(sonarr_data.history);
|
||||
assert_is_empty!(sonarr_data.indexers);
|
||||
assert_none!(sonarr_data.indexer_settings);
|
||||
assert_none!(sonarr_data.indexer_test_errors);
|
||||
assert_none!(sonarr_data.indexer_test_all_results);
|
||||
assert_is_empty!(sonarr_data.language_profiles_map);
|
||||
assert_is_empty!(sonarr_data.logs);
|
||||
assert_is_empty!(sonarr_data.log_details);
|
||||
assert!(!sonarr_data.prompt_confirm);
|
||||
assert!(sonarr_data.prompt_confirm_action.is_none());
|
||||
assert!(sonarr_data.quality_profile_map.is_empty());
|
||||
assert!(sonarr_data.queued_events.is_empty());
|
||||
assert!(sonarr_data.root_folders.is_empty());
|
||||
assert!(sonarr_data.seasons.is_empty());
|
||||
assert!(sonarr_data.season_details_modal.is_none());
|
||||
assert_none!(sonarr_data.prompt_confirm_action);
|
||||
assert_is_empty!(sonarr_data.quality_profile_map);
|
||||
assert_is_empty!(sonarr_data.queued_events);
|
||||
assert_is_empty!(sonarr_data.root_folders);
|
||||
assert_is_empty!(sonarr_data.seasons);
|
||||
assert_none!(sonarr_data.season_details_modal);
|
||||
assert_eq!(sonarr_data.selected_block, BlockSelectionState::default());
|
||||
assert!(sonarr_data.series.is_empty());
|
||||
assert!(sonarr_data.series_history.is_none());
|
||||
assert_is_empty!(sonarr_data.series);
|
||||
assert_none!(sonarr_data.series_history);
|
||||
assert_eq!(sonarr_data.start_time, <DateTime<Utc>>::default());
|
||||
assert!(sonarr_data.tags_map.is_empty());
|
||||
assert!(sonarr_data.tasks.is_empty());
|
||||
assert!(sonarr_data.updates.is_empty());
|
||||
assert!(sonarr_data.version.is_empty());
|
||||
assert_is_empty!(sonarr_data.tags_map);
|
||||
assert_is_empty!(sonarr_data.tasks);
|
||||
assert_is_empty!(sonarr_data.updates);
|
||||
assert_is_empty!(sonarr_data.version);
|
||||
|
||||
assert_eq!(sonarr_data.main_tabs.tabs.len(), 7);
|
||||
|
||||
@@ -123,84 +123,77 @@ mod tests {
|
||||
sonarr_data.main_tabs.tabs[0].route,
|
||||
ActiveSonarrBlock::Series.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[0].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[0].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[0].contextual_help,
|
||||
&SERIES_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[0].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[0].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.main_tabs.tabs[1].title, "Downloads");
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[1].route,
|
||||
ActiveSonarrBlock::Downloads.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[1].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[1].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[1].contextual_help,
|
||||
&DOWNLOADS_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[1].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[1].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.main_tabs.tabs[2].title, "Blocklist");
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[2].route,
|
||||
ActiveSonarrBlock::Blocklist.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[2].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[2].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[2].contextual_help,
|
||||
&BLOCKLIST_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[2].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[2].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.main_tabs.tabs[3].title, "History");
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[3].route,
|
||||
ActiveSonarrBlock::History.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[3].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[3].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[3].contextual_help,
|
||||
&HISTORY_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[3].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[3].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.main_tabs.tabs[4].title, "Root Folders");
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[4].route,
|
||||
ActiveSonarrBlock::RootFolders.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[4].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[4].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[4].contextual_help,
|
||||
&ROOT_FOLDERS_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[4].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[4].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.main_tabs.tabs[5].title, "Indexers");
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[5].route,
|
||||
ActiveSonarrBlock::Indexers.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[5].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[5].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[5].contextual_help,
|
||||
&INDEXERS_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[5].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[5].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.main_tabs.tabs[6].title, "System");
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[6].route,
|
||||
ActiveSonarrBlock::System.into()
|
||||
);
|
||||
assert!(sonarr_data.main_tabs.tabs[6].contextual_help.is_some());
|
||||
assert_eq!(
|
||||
sonarr_data.main_tabs.tabs[6].contextual_help.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.main_tabs.tabs[6].contextual_help,
|
||||
&SYSTEM_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.main_tabs.tabs[6].config, None);
|
||||
assert_none!(sonarr_data.main_tabs.tabs[6].config);
|
||||
|
||||
assert_eq!(sonarr_data.series_info_tabs.tabs.len(), 2);
|
||||
|
||||
@@ -209,36 +202,22 @@ mod tests {
|
||||
sonarr_data.series_info_tabs.tabs[0].route,
|
||||
ActiveSonarrBlock::SeriesDetails.into()
|
||||
);
|
||||
assert!(
|
||||
sonarr_data.series_info_tabs.tabs[0]
|
||||
.contextual_help
|
||||
.is_some()
|
||||
);
|
||||
assert_eq!(
|
||||
sonarr_data.series_info_tabs.tabs[0]
|
||||
.contextual_help
|
||||
.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.series_info_tabs.tabs[0].contextual_help,
|
||||
&SERIES_DETAILS_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.series_info_tabs.tabs[0].config, None);
|
||||
assert_none!(sonarr_data.series_info_tabs.tabs[0].config);
|
||||
|
||||
assert_str_eq!(sonarr_data.series_info_tabs.tabs[1].title, "History");
|
||||
assert_eq!(
|
||||
sonarr_data.series_info_tabs.tabs[1].route,
|
||||
ActiveSonarrBlock::SeriesHistory.into()
|
||||
);
|
||||
assert!(
|
||||
sonarr_data.series_info_tabs.tabs[1]
|
||||
.contextual_help
|
||||
.is_some()
|
||||
);
|
||||
assert_eq!(
|
||||
sonarr_data.series_info_tabs.tabs[1]
|
||||
.contextual_help
|
||||
.unwrap(),
|
||||
assert_some_eq_x!(
|
||||
&sonarr_data.series_info_tabs.tabs[1].contextual_help,
|
||||
&SERIES_HISTORY_CONTEXT_CLUES
|
||||
);
|
||||
assert_eq!(sonarr_data.series_info_tabs.tabs[1].config, None);
|
||||
assert_none!(sonarr_data.series_info_tabs.tabs[1].config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,4 +162,26 @@ mod tests {
|
||||
get_mock.assert_async().await;
|
||||
put_mock.assert_async().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_update_all_artists_event() {
|
||||
let (mock, app, _server) = MockServarrApi::post()
|
||||
.with_request_body(json!({
|
||||
"name": "RefreshArtist"
|
||||
}))
|
||||
.returns(json!({}))
|
||||
.build_for(LidarrEvent::UpdateAllArtists)
|
||||
.await;
|
||||
app.lock().await.server_tabs.set_index(2);
|
||||
let mut network = test_network(&app);
|
||||
|
||||
assert!(
|
||||
network
|
||||
.handle_lidarr_event(LidarrEvent::UpdateAllArtists)
|
||||
.await
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
mock.assert_async().await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use serde_json::{Value, json};
|
||||
use crate::models::Route;
|
||||
use crate::models::lidarr_models::{Artist, DeleteArtistParams};
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||
use crate::models::servarr_models::CommandBody;
|
||||
use crate::network::lidarr_network::LidarrEvent;
|
||||
use crate::network::{Network, RequestMethod};
|
||||
|
||||
@@ -151,4 +152,20 @@ impl Network<'_, '_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::network::lidarr_network) async fn update_all_artists(&mut self) -> Result<Value> {
|
||||
info!("Updating all artists");
|
||||
let event = LidarrEvent::UpdateAllArtists;
|
||||
let body = CommandBody {
|
||||
name: "RefreshArtist".to_owned(),
|
||||
};
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(event, RequestMethod::Post, Some(body), None, None)
|
||||
.await;
|
||||
|
||||
self
|
||||
.handle_request::<CommandBody, Value>(request_props, |_, _| ())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,11 @@ mod tests {
|
||||
assert_str_eq!(event.resource(), "/config/host");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_resource_command(#[values(LidarrEvent::UpdateAllArtists)] event: LidarrEvent) {
|
||||
assert_str_eq!(event.resource(), "/command");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case(LidarrEvent::GetDiskSpace, "/diskspace")]
|
||||
#[case(LidarrEvent::GetDownloads(500), "/queue")]
|
||||
|
||||
@@ -31,6 +31,7 @@ pub enum LidarrEvent {
|
||||
HealthCheck,
|
||||
ListArtists,
|
||||
ToggleArtistMonitoring(i64),
|
||||
UpdateAllArtists,
|
||||
}
|
||||
|
||||
impl NetworkResource for LidarrEvent {
|
||||
@@ -43,6 +44,7 @@ impl NetworkResource for LidarrEvent {
|
||||
LidarrEvent::GetDiskSpace => "/diskspace",
|
||||
LidarrEvent::GetDownloads(_) => "/queue",
|
||||
LidarrEvent::GetHostConfig | LidarrEvent::GetSecurityConfig => "/config/host",
|
||||
LidarrEvent::UpdateAllArtists => "/command",
|
||||
LidarrEvent::GetMetadataProfiles => "/metadataprofile",
|
||||
LidarrEvent::GetQualityProfiles => "/qualityprofile",
|
||||
LidarrEvent::GetRootFolders => "/rootfolder",
|
||||
@@ -108,6 +110,7 @@ impl Network<'_, '_> {
|
||||
.toggle_artist_monitoring(artist_id)
|
||||
.await
|
||||
.map(LidarrSerdeable::from),
|
||||
LidarrEvent::UpdateAllArtists => self.update_all_artists().await.map(LidarrSerdeable::from),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -247,5 +247,18 @@ mod tests {
|
||||
|
||||
insta::assert_snapshot!(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_library_ui_renders_update_all_artists_prompt() {
|
||||
let mut app = App::test_default_fully_populated();
|
||||
app.push_navigation_stack(ActiveLidarrBlock::Artists.into());
|
||||
app.push_navigation_stack(ActiveLidarrBlock::UpdateAllArtistsPrompt.into());
|
||||
|
||||
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||
LibraryUi::draw(f, app, f.area());
|
||||
});
|
||||
|
||||
insta::assert_snapshot!(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ use ratatui::{
|
||||
};
|
||||
|
||||
use crate::ui::widgets::managarr_table::ManagarrTable;
|
||||
use crate::ui::widgets::{
|
||||
confirmation_prompt::ConfirmationPrompt,
|
||||
popup::{Popup, Size},
|
||||
};
|
||||
use crate::utils::convert_to_gb;
|
||||
use crate::{
|
||||
app::App,
|
||||
@@ -42,8 +46,20 @@ impl DrawUi for LibraryUi {
|
||||
let route = app.get_current_route();
|
||||
draw_library(f, app, area);
|
||||
|
||||
if DeleteArtistUi::accepts(route) {
|
||||
DeleteArtistUi::draw(f, app, area);
|
||||
match route {
|
||||
_ if DeleteArtistUi::accepts(route) => DeleteArtistUi::draw(f, app, area),
|
||||
Route::Lidarr(ActiveLidarrBlock::UpdateAllArtistsPrompt, _) => {
|
||||
let confirmation_prompt = ConfirmationPrompt::new()
|
||||
.title("Update All Artists")
|
||||
.prompt("Do you want to update info and scan your disks for all of your artists?")
|
||||
.yes_no_value(app.data.lidarr_data.prompt_confirm);
|
||||
|
||||
f.render_widget(
|
||||
Popup::new(confirmation_prompt).size(Size::MediumPrompt),
|
||||
f.area(),
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
---
|
||||
source: src/ui/lidarr_ui/library/library_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
Name ▼ Type Status Quality Profile Metadata Profile Albums Tracks Size Monitored Tags
|
||||
=> Continuing 0 0.00 GB
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭────────────────── Update All Artists ───────────────────╮
|
||||
│ Do you want to update info and scan your disks for all of │
|
||||
│ your artists? │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│╭────────────────────────────╮╭───────────────────────────╮│
|
||||
││ Yes ││ No ││
|
||||
│╰────────────────────────────╯╰───────────────────────────╯│
|
||||
╰───────────────────────────────────────────────────────────╯
|
||||
@@ -382,5 +382,18 @@ mod tests {
|
||||
|
||||
insta::assert_snapshot!(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_library_ui_renders_update_all_series_prompt() {
|
||||
let mut app = App::test_default_fully_populated();
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::UpdateAllSeriesPrompt.into());
|
||||
|
||||
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
|
||||
LibraryUi::draw(f, app, f.area());
|
||||
});
|
||||
|
||||
insta::assert_snapshot!(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
---
|
||||
source: src/ui/sonarr_ui/library/library_ui_tests.rs
|
||||
expression: output
|
||||
---
|
||||
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags
|
||||
=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╭─────────────────── Update All Series ───────────────────╮
|
||||
│ Do you want to update info and scan your disks for all of │
|
||||
│ your series? │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│╭────────────────────────────╮╭───────────────────────────╮│
|
||||
││ Yes ││ No ││
|
||||
│╰────────────────────────────╯╰───────────────────────────╯│
|
||||
╰───────────────────────────────────────────────────────────╯
|
||||
Reference in New Issue
Block a user