feat: CLI support for deleting an album from Lidarr
This commit is contained in:
@@ -7,7 +7,7 @@ use tokio::sync::Mutex;
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::App,
|
||||||
cli::{CliCommandHandler, Command},
|
cli::{CliCommandHandler, Command},
|
||||||
models::lidarr_models::DeleteArtistParams,
|
models::lidarr_models::DeleteParams,
|
||||||
network::{NetworkTrait, lidarr_network::LidarrEvent},
|
network::{NetworkTrait, lidarr_network::LidarrEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,6 +19,15 @@ mod delete_command_handler_tests;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Subcommand)]
|
#[derive(Debug, Clone, PartialEq, Eq, Subcommand)]
|
||||||
pub enum LidarrDeleteCommand {
|
pub enum LidarrDeleteCommand {
|
||||||
|
#[command(about = "Delete an album from your Lidarr library")]
|
||||||
|
Album {
|
||||||
|
#[arg(long, help = "The ID of the album to delete", required = true)]
|
||||||
|
album_id: i64,
|
||||||
|
#[arg(long, help = "Delete the album files from disk as well")]
|
||||||
|
delete_files_from_disk: bool,
|
||||||
|
#[arg(long, help = "Add a list exclusion for this album")]
|
||||||
|
add_list_exclusion: bool,
|
||||||
|
},
|
||||||
#[command(about = "Delete an artist from your Lidarr library")]
|
#[command(about = "Delete an artist from your Lidarr library")]
|
||||||
Artist {
|
Artist {
|
||||||
#[arg(long, help = "The ID of the artist to delete", required = true)]
|
#[arg(long, help = "The ID of the artist to delete", required = true)]
|
||||||
@@ -62,12 +71,28 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, LidarrDeleteCommand> for LidarrDeleteComm
|
|||||||
|
|
||||||
async fn handle(self) -> Result<String> {
|
async fn handle(self) -> Result<String> {
|
||||||
let result = match self.command {
|
let result = match self.command {
|
||||||
|
LidarrDeleteCommand::Album {
|
||||||
|
album_id,
|
||||||
|
delete_files_from_disk,
|
||||||
|
add_list_exclusion,
|
||||||
|
} => {
|
||||||
|
let delete_album_params = DeleteParams {
|
||||||
|
id: album_id,
|
||||||
|
delete_files: delete_files_from_disk,
|
||||||
|
add_import_list_exclusion: add_list_exclusion,
|
||||||
|
};
|
||||||
|
let resp = self
|
||||||
|
.network
|
||||||
|
.handle_network_event(LidarrEvent::DeleteAlbum(delete_album_params).into())
|
||||||
|
.await?;
|
||||||
|
serde_json::to_string_pretty(&resp)?
|
||||||
|
}
|
||||||
LidarrDeleteCommand::Artist {
|
LidarrDeleteCommand::Artist {
|
||||||
artist_id,
|
artist_id,
|
||||||
delete_files_from_disk,
|
delete_files_from_disk,
|
||||||
add_list_exclusion,
|
add_list_exclusion,
|
||||||
} => {
|
} => {
|
||||||
let delete_artist_params = DeleteArtistParams {
|
let delete_artist_params = DeleteParams {
|
||||||
id: artist_id,
|
id: artist_id,
|
||||||
delete_files: delete_files_from_disk,
|
delete_files: delete_files_from_disk,
|
||||||
add_import_list_exclusion: add_list_exclusion,
|
add_import_list_exclusion: add_list_exclusion,
|
||||||
|
|||||||
@@ -27,6 +27,65 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_requires_arguments() {
|
||||||
|
let result = Cli::command().try_get_matches_from(["managarr", "lidarr", "delete", "album"]);
|
||||||
|
|
||||||
|
assert_err!(&result);
|
||||||
|
assert_eq!(
|
||||||
|
result.unwrap_err().kind(),
|
||||||
|
ErrorKind::MissingRequiredArgument
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_defaults() {
|
||||||
|
let expected_args = LidarrDeleteCommand::Album {
|
||||||
|
album_id: 1,
|
||||||
|
delete_files_from_disk: false,
|
||||||
|
add_list_exclusion: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result =
|
||||||
|
Cli::try_parse_from(["managarr", "lidarr", "delete", "album", "--album-id", "1"]);
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
|
||||||
|
let Some(Command::Lidarr(LidarrCommand::Delete(delete_command))) = result.unwrap().command
|
||||||
|
else {
|
||||||
|
panic!("Unexpected command type");
|
||||||
|
};
|
||||||
|
assert_eq!(delete_command, expected_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_album_all_args_defined() {
|
||||||
|
let expected_args = LidarrDeleteCommand::Album {
|
||||||
|
album_id: 1,
|
||||||
|
delete_files_from_disk: true,
|
||||||
|
add_list_exclusion: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = Cli::try_parse_from([
|
||||||
|
"managarr",
|
||||||
|
"lidarr",
|
||||||
|
"delete",
|
||||||
|
"album",
|
||||||
|
"--album-id",
|
||||||
|
"1",
|
||||||
|
"--delete-files-from-disk",
|
||||||
|
"--add-list-exclusion",
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
|
||||||
|
let Some(Command::Lidarr(LidarrCommand::Delete(delete_command))) = result.unwrap().command
|
||||||
|
else {
|
||||||
|
panic!("Unexpected command type");
|
||||||
|
};
|
||||||
|
assert_eq!(delete_command, expected_args);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_artist_requires_arguments() {
|
fn test_delete_artist_requires_arguments() {
|
||||||
let result = Cli::command().try_get_matches_from(["managarr", "lidarr", "delete", "artist"]);
|
let result = Cli::command().try_get_matches_from(["managarr", "lidarr", "delete", "artist"]);
|
||||||
@@ -128,14 +187,48 @@ mod tests {
|
|||||||
},
|
},
|
||||||
models::{
|
models::{
|
||||||
Serdeable,
|
Serdeable,
|
||||||
lidarr_models::{DeleteArtistParams, LidarrSerdeable},
|
lidarr_models::{DeleteParams, LidarrSerdeable},
|
||||||
},
|
},
|
||||||
network::{MockNetworkTrait, NetworkEvent, lidarr_network::LidarrEvent},
|
network::{MockNetworkTrait, NetworkEvent, lidarr_network::LidarrEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_delete_album_command() {
|
||||||
|
let expected_delete_album_params = DeleteParams {
|
||||||
|
id: 1,
|
||||||
|
delete_files: true,
|
||||||
|
add_import_list_exclusion: true,
|
||||||
|
};
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
LidarrEvent::DeleteAlbum(expected_delete_album_params).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Lidarr(LidarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let delete_album_command = LidarrDeleteCommand::Album {
|
||||||
|
album_id: 1,
|
||||||
|
delete_files_from_disk: true,
|
||||||
|
add_list_exclusion: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result =
|
||||||
|
LidarrDeleteCommandHandler::with(&app_arc, delete_album_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert_ok!(&result);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_delete_artist_command() {
|
async fn test_handle_delete_artist_command() {
|
||||||
let expected_delete_artist_params = DeleteArtistParams {
|
let expected_delete_artist_params = DeleteParams {
|
||||||
id: 1,
|
id: 1,
|
||||||
delete_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
models::{
|
models::{
|
||||||
Serdeable,
|
Serdeable,
|
||||||
lidarr_models::{Artist, DeleteArtistParams, LidarrSerdeable},
|
lidarr_models::{Artist, DeleteParams, LidarrSerdeable},
|
||||||
},
|
},
|
||||||
network::{MockNetworkTrait, NetworkEvent, lidarr_network::LidarrEvent},
|
network::{MockNetworkTrait, NetworkEvent, lidarr_network::LidarrEvent},
|
||||||
};
|
};
|
||||||
@@ -203,7 +203,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_lidarr_cli_handler_delegates_delete_commands_to_the_delete_command_handler() {
|
async fn test_lidarr_cli_handler_delegates_delete_commands_to_the_delete_command_handler() {
|
||||||
let expected_delete_artist_params = DeleteArtistParams {
|
let expected_delete_artist_params = DeleteParams {
|
||||||
id: 1,
|
id: 1,
|
||||||
delete_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ mod tests {
|
|||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
ActiveLidarrBlock, ARTIST_DETAILS_BLOCKS,
|
ARTIST_DETAILS_BLOCKS, ActiveLidarrBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod test_handle_left_right_action {
|
mod test_handle_left_right_action {
|
||||||
@@ -17,64 +17,59 @@ mod tests {
|
|||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_left_right_prompt_toggle(
|
fn test_left_right_prompt_toggle(
|
||||||
#[values(
|
#[values(
|
||||||
ActiveLidarrBlock::UpdateAndScanArtistPrompt,
|
ActiveLidarrBlock::UpdateAndScanArtistPrompt,
|
||||||
ActiveLidarrBlock::AutomaticallySearchArtistPrompt,
|
ActiveLidarrBlock::AutomaticallySearchArtistPrompt
|
||||||
)] active_lidarr_block: ActiveLidarrBlock,
|
)]
|
||||||
|
active_lidarr_block: ActiveLidarrBlock,
|
||||||
#[values(Key::Left, Key::Right)] key: Key,
|
#[values(Key::Left, Key::Right)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
app.push_navigation_stack(active_lidarr_block.into());
|
app.push_navigation_stack(active_lidarr_block.into());
|
||||||
|
|
||||||
ArtistDetailsHandler::new(
|
ArtistDetailsHandler::new(key, &mut app, active_lidarr_block, None).handle();
|
||||||
key,
|
|
||||||
&mut app,
|
|
||||||
active_lidarr_block,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.handle();
|
|
||||||
|
|
||||||
assert!(app.data.lidarr_data.prompt_confirm);
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
|
|
||||||
ArtistDetailsHandler::new(
|
ArtistDetailsHandler::new(key, &mut app, active_lidarr_block, None).handle();
|
||||||
key,
|
|
||||||
&mut app,
|
|
||||||
active_lidarr_block,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.handle();
|
|
||||||
|
|
||||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_submit {
|
mod test_handle_submit {
|
||||||
use rstest::rstest;
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
use crate::assert_navigation_popped;
|
use crate::assert_navigation_popped;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||||
use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::artist;
|
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
|
use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::artist;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
|
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case(ActiveLidarrBlock::AutomaticallySearchArtistPrompt, LidarrEvent::TriggerAutomaticArtistSearch(1))]
|
#[case(
|
||||||
#[case(ActiveLidarrBlock::UpdateAndScanArtistPrompt, LidarrEvent::UpdateAndScanArtist(1))]
|
ActiveLidarrBlock::AutomaticallySearchArtistPrompt,
|
||||||
|
LidarrEvent::TriggerAutomaticArtistSearch(1)
|
||||||
|
)]
|
||||||
|
#[case(
|
||||||
|
ActiveLidarrBlock::UpdateAndScanArtistPrompt,
|
||||||
|
LidarrEvent::UpdateAndScanArtist(1)
|
||||||
|
)]
|
||||||
fn test_artist_details_prompt_confirm_submit(
|
fn test_artist_details_prompt_confirm_submit(
|
||||||
#[case] prompt_block: ActiveLidarrBlock,
|
#[case] prompt_block: ActiveLidarrBlock,
|
||||||
#[case] expected_action: LidarrEvent
|
#[case] expected_action: LidarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.lidarr_data.prompt_confirm = true;
|
app.data.lidarr_data.prompt_confirm = true;
|
||||||
@@ -82,13 +77,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
ArtistDetailsHandler::new(
|
ArtistDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
SUBMIT_KEY,
|
|
||||||
&mut app,
|
|
||||||
prompt_block,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.handle();
|
|
||||||
|
|
||||||
assert!(app.data.lidarr_data.prompt_confirm);
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
||||||
@@ -101,21 +90,16 @@ mod tests {
|
|||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_prompt_decline_submit(
|
fn test_artist_details_prompt_decline_submit(
|
||||||
#[values(
|
#[values(
|
||||||
ActiveLidarrBlock::AutomaticallySearchArtistPrompt,
|
ActiveLidarrBlock::AutomaticallySearchArtistPrompt,
|
||||||
ActiveLidarrBlock::UpdateAndScanArtistPrompt,
|
ActiveLidarrBlock::UpdateAndScanArtistPrompt
|
||||||
)] prompt_block: ActiveLidarrBlock
|
)]
|
||||||
|
prompt_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
ArtistDetailsHandler::new(
|
ArtistDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
SUBMIT_KEY,
|
|
||||||
&mut app,
|
|
||||||
prompt_block,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.handle();
|
|
||||||
|
|
||||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
assert_navigation_popped!(app, ActiveLidarrBlock::ArtistDetails.into());
|
||||||
@@ -124,14 +108,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_esc {
|
mod test_handle_esc {
|
||||||
use rstest::rstest;
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
use crate::assert_navigation_popped;
|
use crate::assert_navigation_popped;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
||||||
|
|
||||||
@@ -140,8 +124,9 @@ mod tests {
|
|||||||
#[values(
|
#[values(
|
||||||
ActiveLidarrBlock::AutomaticallySearchArtistPrompt,
|
ActiveLidarrBlock::AutomaticallySearchArtistPrompt,
|
||||||
ActiveLidarrBlock::UpdateAndScanArtistPrompt
|
ActiveLidarrBlock::UpdateAndScanArtistPrompt
|
||||||
)] prompt_block: ActiveLidarrBlock,
|
)]
|
||||||
#[values(true, false)] is_ready: bool
|
prompt_block: ActiveLidarrBlock,
|
||||||
|
#[values(true, false)] is_ready: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
@@ -157,21 +142,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_char_key_event {
|
mod test_handle_char_key_event {
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
|
use crate::assert_navigation_pushed;
|
||||||
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
||||||
|
use crate::models::lidarr_models::Artist;
|
||||||
|
use crate::models::servarr_data::lidarr::lidarr_data::{
|
||||||
|
ActiveLidarrBlock, EDIT_ARTIST_SELECTION_BLOCKS,
|
||||||
|
};
|
||||||
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
|
use crate::{assert_modal_absent, assert_modal_present, assert_navigation_popped};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
|
||||||
use crate::{assert_modal_absent, assert_modal_present, assert_navigation_popped};
|
|
||||||
use crate::assert_navigation_pushed;
|
|
||||||
use crate::handlers::lidarr_handlers::library::artist_details_handler::ArtistDetailsHandler;
|
|
||||||
use crate::handlers::KeyEventHandler;
|
|
||||||
use crate::models::lidarr_models::{Artist};
|
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, EDIT_ARTIST_SELECTION_BLOCKS};
|
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_edit_key(
|
fn test_artist_details_edit_key(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
app.push_navigation_stack(ActiveLidarrBlock::ArtistDetails.into());
|
||||||
@@ -183,7 +170,7 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_navigation_pushed!(
|
assert_navigation_pushed!(
|
||||||
app,
|
app,
|
||||||
@@ -203,7 +190,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_edit_key_no_op_when_not_ready(
|
fn test_artist_details_edit_key_no_op_when_not_ready(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
@@ -216,7 +203,7 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
||||||
assert_modal_absent!(app.data.lidarr_data.edit_artist_modal);
|
assert_modal_absent!(app.data.lidarr_data.edit_artist_modal);
|
||||||
@@ -235,9 +222,12 @@ mod tests {
|
|||||||
ActiveLidarrBlock::ArtistDetails,
|
ActiveLidarrBlock::ArtistDetails,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveLidarrBlock::ArtistDetails.into());
|
assert_eq!(
|
||||||
|
app.get_current_route(),
|
||||||
|
ActiveLidarrBlock::ArtistDetails.into()
|
||||||
|
);
|
||||||
assert!(app.data.lidarr_data.prompt_confirm);
|
assert!(app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(app.is_routing);
|
assert!(app.is_routing);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -259,9 +249,12 @@ mod tests {
|
|||||||
ActiveLidarrBlock::ArtistDetails,
|
ActiveLidarrBlock::ArtistDetails,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveLidarrBlock::ArtistDetails.into());
|
assert_eq!(
|
||||||
|
app.get_current_route(),
|
||||||
|
ActiveLidarrBlock::ArtistDetails.into()
|
||||||
|
);
|
||||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
assert_none!(app.data.lidarr_data.prompt_confirm_action);
|
||||||
}
|
}
|
||||||
@@ -281,7 +274,7 @@ mod tests {
|
|||||||
ActiveLidarrBlock::ArtistDetails,
|
ActiveLidarrBlock::ArtistDetails,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.data.lidarr_data.prompt_confirm);
|
assert!(!app.data.lidarr_data.prompt_confirm);
|
||||||
assert!(app.data.lidarr_data.prompt_confirm_action.is_none());
|
assert!(app.data.lidarr_data.prompt_confirm_action.is_none());
|
||||||
@@ -289,7 +282,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_auto_search_key(
|
fn test_artist_details_auto_search_key(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.push_navigation_stack(active_lidarr_block.into());
|
app.push_navigation_stack(active_lidarr_block.into());
|
||||||
@@ -300,7 +293,7 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_navigation_pushed!(
|
assert_navigation_pushed!(
|
||||||
app,
|
app,
|
||||||
@@ -310,7 +303,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_auto_search_key_no_op_when_not_ready(
|
fn test_artist_details_auto_search_key_no_op_when_not_ready(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
@@ -322,14 +315,14 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_update_key(
|
fn test_artist_details_update_key(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.push_navigation_stack(active_lidarr_block.into());
|
app.push_navigation_stack(active_lidarr_block.into());
|
||||||
@@ -340,14 +333,14 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_navigation_pushed!(app, ActiveLidarrBlock::UpdateAndScanArtistPrompt.into());
|
assert_navigation_pushed!(app, ActiveLidarrBlock::UpdateAndScanArtistPrompt.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_update_key_no_op_when_not_ready(
|
fn test_artist_details_update_key_no_op_when_not_ready(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
@@ -359,14 +352,14 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_refresh_key(
|
fn test_artist_details_refresh_key(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.is_routing = false;
|
app.is_routing = false;
|
||||||
@@ -381,16 +374,13 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_navigation_pushed!(
|
assert_navigation_pushed!(app, active_lidarr_block.into());
|
||||||
app,
|
|
||||||
active_lidarr_block.into()
|
|
||||||
);
|
|
||||||
assert!(app.is_routing);
|
assert!(app.is_routing);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_artist_details_refresh_key_no_op_when_not_ready(
|
fn test_artist_details_refresh_key_no_op_when_not_ready(
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
@@ -403,12 +393,9 @@ mod tests {
|
|||||||
active_lidarr_block,
|
active_lidarr_block,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(app.get_current_route(), active_lidarr_block.into());
|
||||||
app.get_current_route(),
|
|
||||||
active_lidarr_block.into()
|
|
||||||
);
|
|
||||||
assert!(!app.is_routing);
|
assert!(!app.is_routing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,8 +411,7 @@ mod tests {
|
|||||||
fn test_artist_details_prompt_confirm_key(
|
fn test_artist_details_prompt_confirm_key(
|
||||||
#[case] prompt_block: ActiveLidarrBlock,
|
#[case] prompt_block: ActiveLidarrBlock,
|
||||||
#[case] expected_action: LidarrEvent,
|
#[case] expected_action: LidarrEvent,
|
||||||
#[values(ActiveLidarrBlock::ArtistDetails)]
|
#[values(ActiveLidarrBlock::ArtistDetails)] active_lidarr_block: ActiveLidarrBlock,
|
||||||
active_lidarr_block: ActiveLidarrBlock,
|
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
app.push_navigation_stack(active_lidarr_block.into());
|
app.push_navigation_stack(active_lidarr_block.into());
|
||||||
@@ -463,8 +449,13 @@ mod tests {
|
|||||||
fn test_extract_artist_id() {
|
fn test_extract_artist_id() {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
|
|
||||||
let artist_id = ArtistDetailsHandler::new(DEFAULT_KEYBINDINGS.esc.key,
|
let artist_id = ArtistDetailsHandler::new(
|
||||||
&mut app, ActiveLidarrBlock::ArtistDetails, None).extract_artist_id();
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::ArtistDetails,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.extract_artist_id();
|
||||||
|
|
||||||
assert_eq!(artist_id, 1);
|
assert_eq!(artist_id, 1);
|
||||||
}
|
}
|
||||||
@@ -473,8 +464,13 @@ mod tests {
|
|||||||
fn test_extract_album_id() {
|
fn test_extract_album_id() {
|
||||||
let mut app = App::test_default_fully_populated();
|
let mut app = App::test_default_fully_populated();
|
||||||
|
|
||||||
let album_id = ArtistDetailsHandler::new(DEFAULT_KEYBINDINGS.esc.key,
|
let album_id = ArtistDetailsHandler::new(
|
||||||
&mut app, ActiveLidarrBlock::ArtistDetails, None).extract_album_id();
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveLidarrBlock::ArtistDetails,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.extract_album_id();
|
||||||
|
|
||||||
assert_eq!(album_id, 1);
|
assert_eq!(album_id, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::models::lidarr_models::DeleteArtistParams;
|
use crate::models::lidarr_models::DeleteParams;
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::App,
|
||||||
@@ -21,13 +21,13 @@ pub(in crate::handlers::lidarr_handlers) struct DeleteArtistHandler<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DeleteArtistHandler<'_, '_> {
|
impl DeleteArtistHandler<'_, '_> {
|
||||||
fn build_delete_artist_params(&mut self) -> DeleteArtistParams {
|
fn build_delete_artist_params(&mut self) -> DeleteParams {
|
||||||
let id = self.app.data.lidarr_data.artists.current_selection().id;
|
let id = self.app.data.lidarr_data.artists.current_selection().id;
|
||||||
let delete_files = self.app.data.lidarr_data.delete_artist_files;
|
let delete_files = self.app.data.lidarr_data.delete_artist_files;
|
||||||
let add_import_list_exclusion = self.app.data.lidarr_data.add_import_list_exclusion;
|
let add_import_list_exclusion = self.app.data.lidarr_data.add_import_list_exclusion;
|
||||||
self.app.data.lidarr_data.reset_delete_artist_preferences();
|
self.app.data.lidarr_data.reset_delete_artist_preferences();
|
||||||
|
|
||||||
DeleteArtistParams {
|
DeleteParams {
|
||||||
id,
|
id,
|
||||||
delete_files,
|
delete_files,
|
||||||
add_import_list_exclusion,
|
add_import_list_exclusion,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ mod tests {
|
|||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::handlers::lidarr_handlers::library::delete_artist_handler::DeleteArtistHandler;
|
use crate::handlers::lidarr_handlers::library::delete_artist_handler::DeleteArtistHandler;
|
||||||
use crate::models::lidarr_models::{Artist, DeleteArtistParams};
|
use crate::models::lidarr_models::{Artist, DeleteParams};
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, DELETE_ARTIST_BLOCKS};
|
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, DELETE_ARTIST_BLOCKS};
|
||||||
|
|
||||||
mod test_handle_scroll_up_and_down {
|
mod test_handle_scroll_up_and_down {
|
||||||
@@ -137,7 +137,7 @@ mod tests {
|
|||||||
.lidarr_data
|
.lidarr_data
|
||||||
.artists
|
.artists
|
||||||
.set_items(vec![Artist::default()]);
|
.set_items(vec![Artist::default()]);
|
||||||
let expected_delete_artist_params = DeleteArtistParams {
|
let expected_delete_artist_params = DeleteParams {
|
||||||
id: 0,
|
id: 0,
|
||||||
delete_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
@@ -286,7 +286,7 @@ mod tests {
|
|||||||
.lidarr_data
|
.lidarr_data
|
||||||
.artists
|
.artists
|
||||||
.set_items(vec![Artist::default()]);
|
.set_items(vec![Artist::default()]);
|
||||||
let expected_delete_artist_params = DeleteArtistParams {
|
let expected_delete_artist_params = DeleteParams {
|
||||||
id: 0,
|
id: 0,
|
||||||
delete_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
@@ -359,7 +359,7 @@ mod tests {
|
|||||||
.set_items(vec![Artist::default()]);
|
.set_items(vec![Artist::default()]);
|
||||||
app.data.lidarr_data.delete_artist_files = true;
|
app.data.lidarr_data.delete_artist_files = true;
|
||||||
app.data.lidarr_data.add_import_list_exclusion = true;
|
app.data.lidarr_data.add_import_list_exclusion = true;
|
||||||
let expected_delete_artist_params = DeleteArtistParams {
|
let expected_delete_artist_params = DeleteParams {
|
||||||
id: 0,
|
id: 0,
|
||||||
delete_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ pub struct LidarrCommandBody {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub struct DeleteArtistParams {
|
pub struct DeleteParams {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub delete_files: bool,
|
pub delete_files: bool,
|
||||||
pub add_import_list_exclusion: bool,
|
pub add_import_list_exclusion: bool,
|
||||||
|
|||||||
@@ -1,106 +1,131 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use mockito::Matcher;
|
use crate::models::lidarr_models::{Album, DeleteParams, LidarrSerdeable};
|
||||||
use pretty_assertions::assert_eq;
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
use serde_json::{json, Value};
|
use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::ALBUM_JSON;
|
||||||
use crate::models::lidarr_models::{Album, LidarrSerdeable};
|
use crate::network::network_tests::test_utils::{MockServarrApi, test_network};
|
||||||
use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::{ALBUM_JSON};
|
use mockito::Matcher;
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
use pretty_assertions::assert_eq;
|
||||||
use crate::network::network_tests::test_utils::{test_network, MockServarrApi};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_albums_event() {
|
async fn test_handle_get_albums_event() {
|
||||||
let albums_json = json!([{
|
let albums_json = json!([{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"title": "Test Album",
|
"title": "Test Album",
|
||||||
"foreignAlbumId": "test-foreign-album-id",
|
"foreignAlbumId": "test-foreign-album-id",
|
||||||
"monitored": true,
|
"monitored": true,
|
||||||
"anyReleaseOk": true,
|
"anyReleaseOk": true,
|
||||||
"profileId": 1,
|
"profileId": 1,
|
||||||
"duration": 180,
|
"duration": 180,
|
||||||
"albumType": "Album",
|
"albumType": "Album",
|
||||||
"genres": ["Classical"],
|
"genres": ["Classical"],
|
||||||
"ratings": {"votes": 15, "value": 8.4},
|
"ratings": {"votes": 15, "value": 8.4},
|
||||||
"releaseDate": "2023-01-01T00:00:00Z",
|
"releaseDate": "2023-01-01T00:00:00Z",
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"trackFileCount": 10,
|
"trackFileCount": 10,
|
||||||
"trackCount": 10,
|
"trackCount": 10,
|
||||||
"totalTrackCount": 10,
|
"totalTrackCount": 10,
|
||||||
"sizeOnDisk": 1024,
|
"sizeOnDisk": 1024,
|
||||||
"percentOfTracks": 99.9
|
"percentOfTracks": 99.9
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
let response: Vec<Album> = serde_json::from_value(albums_json.clone()).unwrap();
|
let response: Vec<Album> = serde_json::from_value(albums_json.clone()).unwrap();
|
||||||
let (mock, app, _server) = MockServarrApi::get()
|
let (mock, app, _server) = MockServarrApi::get()
|
||||||
.returns(albums_json)
|
.returns(albums_json)
|
||||||
.query("artistId=1")
|
.query("artistId=1")
|
||||||
.build_for(LidarrEvent::GetAlbums(1))
|
.build_for(LidarrEvent::GetAlbums(1))
|
||||||
.await;
|
.await;
|
||||||
app.lock().await.server_tabs.set_index(2);
|
app.lock().await.server_tabs.set_index(2);
|
||||||
let mut network = test_network(&app);
|
let mut network = test_network(&app);
|
||||||
|
|
||||||
let result = network.handle_lidarr_event(LidarrEvent::GetAlbums(1)).await;
|
let result = network.handle_lidarr_event(LidarrEvent::GetAlbums(1)).await;
|
||||||
|
|
||||||
mock.assert_async().await;
|
mock.assert_async().await;
|
||||||
|
|
||||||
let LidarrSerdeable::Albums(albums) = result.unwrap() else {
|
let LidarrSerdeable::Albums(albums) = result.unwrap() else {
|
||||||
panic!("Expected Albums");
|
panic!("Expected Albums");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(albums, response);
|
assert_eq!(albums, response);
|
||||||
assert!(!app.lock().await.data.lidarr_data.albums.is_empty());
|
assert!(!app.lock().await.data.lidarr_data.albums.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_toggle_album_monitoring_event() {
|
async fn test_handle_delete_album_event() {
|
||||||
let mut expected_body: Value = serde_json::from_str(ALBUM_JSON).unwrap();
|
let delete_album_params = DeleteParams {
|
||||||
*expected_body.get_mut("monitored").unwrap() = json!(false);
|
id: 1,
|
||||||
let (get_mock, app, mut server) = MockServarrApi::get()
|
delete_files: true,
|
||||||
.returns(serde_json::from_str(ALBUM_JSON).unwrap())
|
add_import_list_exclusion: true,
|
||||||
.path("/1")
|
};
|
||||||
.build_for(LidarrEvent::GetAlbums(1))
|
let (async_server, app, _server) = MockServarrApi::delete()
|
||||||
.await;
|
.path("/1")
|
||||||
let put_mock = server
|
.query("deleteFiles=true&addImportListExclusion=true")
|
||||||
.mock("PUT", "/api/v1/album/1")
|
.build_for(LidarrEvent::DeleteAlbum(delete_album_params.clone()))
|
||||||
.match_body(Matcher::Json(expected_body))
|
.await;
|
||||||
.match_header("X-Api-Key", "test1234")
|
app.lock().await.server_tabs.set_index(2);
|
||||||
.with_status(202)
|
let mut network = test_network(&app);
|
||||||
.create_async()
|
|
||||||
.await;
|
|
||||||
app.lock().await.server_tabs.set_index(2);
|
|
||||||
let mut network = test_network(&app);
|
|
||||||
|
|
||||||
assert_ok!(
|
assert!(
|
||||||
network
|
network
|
||||||
.handle_lidarr_event(LidarrEvent::ToggleAlbumMonitoring(1))
|
.handle_lidarr_event(LidarrEvent::DeleteAlbum(delete_album_params))
|
||||||
.await
|
.await
|
||||||
);
|
.is_ok()
|
||||||
|
);
|
||||||
|
|
||||||
get_mock.assert_async().await;
|
async_server.assert_async().await;
|
||||||
put_mock.assert_async().await;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_album_details_event() {
|
async fn test_handle_toggle_album_monitoring_event() {
|
||||||
let expected_album: Album = serde_json::from_str(ALBUM_JSON).unwrap();
|
let mut expected_body: Value = serde_json::from_str(ALBUM_JSON).unwrap();
|
||||||
let (mock, app, _server) = MockServarrApi::get()
|
*expected_body.get_mut("monitored").unwrap() = json!(false);
|
||||||
.returns(serde_json::from_str(ALBUM_JSON).unwrap())
|
let (get_mock, app, mut server) = MockServarrApi::get()
|
||||||
.path("/1")
|
.returns(serde_json::from_str(ALBUM_JSON).unwrap())
|
||||||
.build_for(LidarrEvent::GetAlbumDetails(1))
|
.path("/1")
|
||||||
.await;
|
.build_for(LidarrEvent::GetAlbums(1))
|
||||||
app.lock().await.server_tabs.set_index(2);
|
.await;
|
||||||
let mut network = test_network(&app);
|
let put_mock = server
|
||||||
|
.mock("PUT", "/api/v1/album/1")
|
||||||
|
.match_body(Matcher::Json(expected_body))
|
||||||
|
.match_header("X-Api-Key", "test1234")
|
||||||
|
.with_status(202)
|
||||||
|
.create_async()
|
||||||
|
.await;
|
||||||
|
app.lock().await.server_tabs.set_index(2);
|
||||||
|
let mut network = test_network(&app);
|
||||||
|
|
||||||
let result = network
|
assert_ok!(
|
||||||
.handle_lidarr_event(LidarrEvent::GetAlbumDetails(1))
|
network
|
||||||
.await;
|
.handle_lidarr_event(LidarrEvent::ToggleAlbumMonitoring(1))
|
||||||
|
.await
|
||||||
|
);
|
||||||
|
|
||||||
mock.assert_async().await;
|
get_mock.assert_async().await;
|
||||||
|
put_mock.assert_async().await;
|
||||||
|
}
|
||||||
|
|
||||||
let LidarrSerdeable::Album(album) = result.unwrap() else {
|
#[tokio::test]
|
||||||
panic!("Expected Album");
|
async fn test_handle_get_album_details_event() {
|
||||||
};
|
let expected_album: Album = serde_json::from_str(ALBUM_JSON).unwrap();
|
||||||
|
let (mock, app, _server) = MockServarrApi::get()
|
||||||
|
.returns(serde_json::from_str(ALBUM_JSON).unwrap())
|
||||||
|
.path("/1")
|
||||||
|
.build_for(LidarrEvent::GetAlbumDetails(1))
|
||||||
|
.await;
|
||||||
|
app.lock().await.server_tabs.set_index(2);
|
||||||
|
let mut network = test_network(&app);
|
||||||
|
|
||||||
assert_eq!(album, expected_album);
|
let result = network
|
||||||
}
|
.handle_lidarr_event(LidarrEvent::GetAlbumDetails(1))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
mock.assert_async().await;
|
||||||
|
|
||||||
|
let LidarrSerdeable::Album(album) = result.unwrap() else {
|
||||||
|
panic!("Expected Album");
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(album, expected_album);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::models::lidarr_models::{Album};
|
use crate::models::lidarr_models::{Album, DeleteParams};
|
||||||
use crate::network::lidarr_network::LidarrEvent;
|
use crate::network::lidarr_network::LidarrEvent;
|
||||||
use crate::network::{Network, RequestMethod};
|
use crate::network::{Network, RequestMethod};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
@@ -57,6 +57,38 @@ impl Network<'_, '_> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(in crate::network::lidarr_network) async fn delete_album(
|
||||||
|
&mut self,
|
||||||
|
delete_album_params: DeleteParams,
|
||||||
|
) -> Result<()> {
|
||||||
|
let event = LidarrEvent::DeleteAlbum(DeleteParams::default());
|
||||||
|
let DeleteParams {
|
||||||
|
id,
|
||||||
|
delete_files,
|
||||||
|
add_import_list_exclusion,
|
||||||
|
} = delete_album_params;
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Deleting Lidarr album with ID: {id} with deleteFiles={delete_files} and addImportListExclusion={add_import_list_exclusion}"
|
||||||
|
);
|
||||||
|
|
||||||
|
let request_props = self
|
||||||
|
.request_props_from(
|
||||||
|
event,
|
||||||
|
RequestMethod::Delete,
|
||||||
|
None::<()>,
|
||||||
|
Some(format!("/{id}")),
|
||||||
|
Some(format!(
|
||||||
|
"deleteFiles={delete_files}&addImportListExclusion={add_import_list_exclusion}"
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self
|
||||||
|
.handle_request::<(), ()>(request_props, |_, _| ())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub(in crate::network::lidarr_network) async fn toggle_album_monitoring(
|
pub(in crate::network::lidarr_network) async fn toggle_album_monitoring(
|
||||||
&mut self,
|
&mut self,
|
||||||
album_id: i64,
|
album_id: i64,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::models::lidarr_models::{
|
use crate::models::lidarr_models::{
|
||||||
AddArtistBody, AddArtistOptions, AddArtistSearchResult, Artist, DeleteArtistParams,
|
AddArtistBody, AddArtistOptions, AddArtistSearchResult, Artist, DeleteParams, EditArtistParams,
|
||||||
EditArtistParams, LidarrSerdeable, MonitorType, NewItemMonitorType,
|
LidarrSerdeable, MonitorType, NewItemMonitorType,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||||
use crate::network::NetworkResource;
|
use crate::network::NetworkResource;
|
||||||
@@ -54,7 +54,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_delete_artist_event() {
|
async fn test_handle_delete_artist_event() {
|
||||||
let delete_artist_params = DeleteArtistParams {
|
let delete_artist_params = DeleteParams {
|
||||||
id: 1,
|
id: 1,
|
||||||
delete_files: true,
|
delete_files: true,
|
||||||
add_import_list_exclusion: true,
|
add_import_list_exclusion: true,
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ use serde_json::{Value, json};
|
|||||||
|
|
||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::models::lidarr_models::{
|
use crate::models::lidarr_models::{
|
||||||
AddArtistBody, AddArtistSearchResult, Artist, DeleteArtistParams, EditArtistParams,
|
AddArtistBody, AddArtistSearchResult, Artist, DeleteParams, EditArtistParams, LidarrCommandBody,
|
||||||
LidarrCommandBody,
|
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
@@ -20,10 +19,10 @@ mod lidarr_artists_network_tests;
|
|||||||
impl Network<'_, '_> {
|
impl Network<'_, '_> {
|
||||||
pub(in crate::network::lidarr_network) async fn delete_artist(
|
pub(in crate::network::lidarr_network) async fn delete_artist(
|
||||||
&mut self,
|
&mut self,
|
||||||
delete_artist_params: DeleteArtistParams,
|
delete_artist_params: DeleteParams,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let event = LidarrEvent::DeleteArtist(DeleteArtistParams::default());
|
let event = LidarrEvent::DeleteArtist(DeleteParams::default());
|
||||||
let DeleteArtistParams {
|
let DeleteParams {
|
||||||
id,
|
id,
|
||||||
delete_files,
|
delete_files,
|
||||||
add_import_list_exclusion,
|
add_import_list_exclusion,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub mod test_utils {
|
|||||||
"percentOfTracks": 99.9
|
"percentOfTracks": 99.9
|
||||||
}
|
}
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
pub const ALBUM_JSON: &str = r#"{
|
pub const ALBUM_JSON: &str = r#"{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"title": "Test Album",
|
"title": "Test Album",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::models::lidarr_models::{AddArtistBody, LidarrSerdeable, MetadataProfile};
|
use crate::models::lidarr_models::{
|
||||||
|
AddArtistBody, DeleteParams, EditArtistParams, LidarrSerdeable, MetadataProfile,
|
||||||
|
};
|
||||||
use crate::models::servarr_data::lidarr::modals::EditArtistModal;
|
use crate::models::servarr_data::lidarr::modals::EditArtistModal;
|
||||||
use crate::models::servarr_models::{QualityProfile, Tag};
|
use crate::models::servarr_models::{QualityProfile, Tag};
|
||||||
use crate::network::network_tests::test_utils::{MockServarrApi, test_network};
|
use crate::network::network_tests::test_utils::{MockServarrApi, test_network};
|
||||||
@@ -19,7 +21,9 @@ mod tests {
|
|||||||
LidarrEvent::GetArtistDetails(0),
|
LidarrEvent::GetArtistDetails(0),
|
||||||
LidarrEvent::ListArtists,
|
LidarrEvent::ListArtists,
|
||||||
LidarrEvent::AddArtist(AddArtistBody::default()),
|
LidarrEvent::AddArtist(AddArtistBody::default()),
|
||||||
LidarrEvent::ToggleArtistMonitoring(0)
|
LidarrEvent::ToggleArtistMonitoring(0),
|
||||||
|
LidarrEvent::DeleteArtist(DeleteParams::default()),
|
||||||
|
LidarrEvent::EditArtist(EditArtistParams::default())
|
||||||
)]
|
)]
|
||||||
event: LidarrEvent,
|
event: LidarrEvent,
|
||||||
) {
|
) {
|
||||||
@@ -58,8 +62,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_resource_albums(
|
fn test_resource_album(
|
||||||
#[values(LidarrEvent::GetAlbums(0), LidarrEvent::ToggleAlbumMonitoring(0), LidarrEvent::GetAlbumDetails(0))] event: LidarrEvent,
|
#[values(
|
||||||
|
LidarrEvent::GetAlbums(0),
|
||||||
|
LidarrEvent::ToggleAlbumMonitoring(0),
|
||||||
|
LidarrEvent::GetAlbumDetails(0),
|
||||||
|
LidarrEvent::DeleteAlbum(DeleteParams::default())
|
||||||
|
)]
|
||||||
|
event: LidarrEvent,
|
||||||
) {
|
) {
|
||||||
assert_str_eq!(event.resource(), "/album");
|
assert_str_eq!(event.resource(), "/album");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use log::info;
|
|||||||
|
|
||||||
use super::{NetworkEvent, NetworkResource};
|
use super::{NetworkEvent, NetworkResource};
|
||||||
use crate::models::lidarr_models::{
|
use crate::models::lidarr_models::{
|
||||||
AddArtistBody, DeleteArtistParams, EditArtistParams, LidarrSerdeable, MetadataProfile,
|
AddArtistBody, DeleteParams, EditArtistParams, LidarrSerdeable, MetadataProfile,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_models::{QualityProfile, Tag};
|
use crate::models::servarr_models::{QualityProfile, Tag};
|
||||||
use crate::network::{Network, RequestMethod};
|
use crate::network::{Network, RequestMethod};
|
||||||
@@ -25,7 +25,8 @@ pub mod lidarr_network_test_utils;
|
|||||||
pub enum LidarrEvent {
|
pub enum LidarrEvent {
|
||||||
AddArtist(AddArtistBody),
|
AddArtist(AddArtistBody),
|
||||||
AddTag(String),
|
AddTag(String),
|
||||||
DeleteArtist(DeleteArtistParams),
|
DeleteAlbum(DeleteParams),
|
||||||
|
DeleteArtist(DeleteParams),
|
||||||
DeleteTag(i64),
|
DeleteTag(i64),
|
||||||
EditArtist(EditArtistParams),
|
EditArtist(EditArtistParams),
|
||||||
GetAlbums(i64),
|
GetAlbums(i64),
|
||||||
@@ -60,7 +61,10 @@ impl NetworkResource for LidarrEvent {
|
|||||||
| LidarrEvent::ListArtists
|
| LidarrEvent::ListArtists
|
||||||
| LidarrEvent::AddArtist(_)
|
| LidarrEvent::AddArtist(_)
|
||||||
| LidarrEvent::ToggleArtistMonitoring(_) => "/artist",
|
| LidarrEvent::ToggleArtistMonitoring(_) => "/artist",
|
||||||
LidarrEvent::GetAlbums(_) | LidarrEvent::ToggleAlbumMonitoring(_) | LidarrEvent::GetAlbumDetails(_) => "/album",
|
LidarrEvent::GetAlbums(_)
|
||||||
|
| LidarrEvent::ToggleAlbumMonitoring(_)
|
||||||
|
| LidarrEvent::GetAlbumDetails(_)
|
||||||
|
| LidarrEvent::DeleteAlbum(_) => "/album",
|
||||||
LidarrEvent::GetDiskSpace => "/diskspace",
|
LidarrEvent::GetDiskSpace => "/diskspace",
|
||||||
LidarrEvent::GetDownloads(_) => "/queue",
|
LidarrEvent::GetDownloads(_) => "/queue",
|
||||||
LidarrEvent::GetHostConfig | LidarrEvent::GetSecurityConfig => "/config/host",
|
LidarrEvent::GetHostConfig | LidarrEvent::GetSecurityConfig => "/config/host",
|
||||||
@@ -90,6 +94,9 @@ impl Network<'_, '_> {
|
|||||||
) -> Result<LidarrSerdeable> {
|
) -> Result<LidarrSerdeable> {
|
||||||
match lidarr_event {
|
match lidarr_event {
|
||||||
LidarrEvent::AddTag(tag) => self.add_lidarr_tag(tag).await.map(LidarrSerdeable::from),
|
LidarrEvent::AddTag(tag) => self.add_lidarr_tag(tag).await.map(LidarrSerdeable::from),
|
||||||
|
LidarrEvent::DeleteAlbum(params) => {
|
||||||
|
self.delete_album(params).await.map(LidarrSerdeable::from)
|
||||||
|
}
|
||||||
LidarrEvent::DeleteArtist(params) => {
|
LidarrEvent::DeleteArtist(params) => {
|
||||||
self.delete_artist(params).await.map(LidarrSerdeable::from)
|
self.delete_artist(params).await.map(LidarrSerdeable::from)
|
||||||
}
|
}
|
||||||
@@ -104,7 +111,10 @@ impl Network<'_, '_> {
|
|||||||
.get_artist_details(artist_id)
|
.get_artist_details(artist_id)
|
||||||
.await
|
.await
|
||||||
.map(LidarrSerdeable::from),
|
.map(LidarrSerdeable::from),
|
||||||
LidarrEvent::GetAlbumDetails(album_id) => self.get_album_details(album_id).await.map(LidarrSerdeable::from),
|
LidarrEvent::GetAlbumDetails(album_id) => self
|
||||||
|
.get_album_details(album_id)
|
||||||
|
.await
|
||||||
|
.map(LidarrSerdeable::from),
|
||||||
LidarrEvent::GetDiskSpace => self.get_lidarr_diskspace().await.map(LidarrSerdeable::from),
|
LidarrEvent::GetDiskSpace => self.get_lidarr_diskspace().await.map(LidarrSerdeable::from),
|
||||||
LidarrEvent::GetDownloads(count) => self
|
LidarrEvent::GetDownloads(count) => self
|
||||||
.get_lidarr_downloads(count)
|
.get_lidarr_downloads(count)
|
||||||
|
|||||||
Reference in New Issue
Block a user