fix(sonarr): Pass the episode file ID alongside all DeleteEpisodeFile events when publishing to the networking channel

This commit is contained in:
2024-12-17 22:33:10 -07:00
parent 6c5a73f78f
commit aece20af47
6 changed files with 86 additions and 84 deletions
+1 -1
View File
@@ -108,7 +108,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrDeleteCommand> for SonarrDeleteComm
SonarrDeleteCommand::EpisodeFile { episode_file_id } => {
let resp = self
.network
.handle_network_event(SonarrEvent::DeleteEpisodeFile(Some(episode_file_id)).into())
.handle_network_event(SonarrEvent::DeleteEpisodeFile(episode_file_id).into())
.await?;
serde_json::to_string_pretty(&resp)?
}
@@ -351,6 +351,37 @@ mod tests {
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handle_delete_episode_file_command() {
let expected_episode_file_id = 1;
let mut mock_network = MockNetworkTrait::new();
mock_network
.expect_handle_network_event()
.with(eq::<NetworkEvent>(
SonarrEvent::DeleteEpisodeFile(expected_episode_file_id).into(),
))
.times(1)
.returning(|_| {
Ok(Serdeable::Sonarr(SonarrSerdeable::Value(
json!({"testResponse": "response"}),
)))
});
let app_arc = Arc::new(Mutex::new(App::default()));
let delete_episode_file_command = SonarrDeleteCommand::EpisodeFile {
episode_file_id: 1,
};
let result = SonarrDeleteCommandHandler::with(
&app_arc,
delete_episode_file_command,
&mut mock_network,
)
.handle()
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_handle_delete_indexer_command() {
let expected_indexer_id = 1;
@@ -65,6 +65,19 @@ impl<'a, 'b> SeasonDetailsHandler<'a, 'b> {
.season_releases,
SonarrRelease
);
fn extract_episode_file_id(&self) -> i64 {
self
.app
.data
.sonarr_data
.season_details_modal
.as_ref()
.expect("Season details have not been loaded")
.episodes
.current_selection()
.episode_file_id
}
}
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler<'a, 'b> {
@@ -234,7 +247,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
ActiveSonarrBlock::DeleteEpisodeFilePrompt => {
if self.app.data.sonarr_data.prompt_confirm {
self.app.data.sonarr_data.prompt_confirm_action =
Some(SonarrEvent::DeleteEpisodeFile(None));
Some(SonarrEvent::DeleteEpisodeFile(self.extract_episode_file_id()));
}
self.app.pop_navigation_stack();
@@ -374,7 +387,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
ActiveSonarrBlock::DeleteEpisodeFilePrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
self.app.data.sonarr_data.prompt_confirm = true;
self.app.data.sonarr_data.prompt_confirm_action =
Some(SonarrEvent::DeleteEpisodeFile(None));
Some(SonarrEvent::DeleteEpisodeFile(self.extract_episode_file_id()));
self.app.pop_navigation_stack();
}
@@ -14,7 +14,7 @@ mod tests {
use crate::models::servarr_models::{Language, Quality, QualityWrapper};
use crate::models::sonarr_models::{SonarrRelease, SonarrReleaseDownloadBody};
use crate::models::HorizontallyScrollableText;
use pretty_assertions::assert_str_eq;
use pretty_assertions::{assert_str_eq, assert_eq};
use rstest::rstest;
use serde_json::Number;
use std::cmp::Ordering;
@@ -279,7 +279,7 @@ mod tests {
)]
#[case(
ActiveSonarrBlock::DeleteEpisodeFilePrompt,
SonarrEvent::DeleteEpisodeFile(None)
SonarrEvent::DeleteEpisodeFile(0)
)]
fn test_season_details_prompt_confirm_submit(
#[case] prompt_block: ActiveSonarrBlock,
@@ -708,7 +708,7 @@ mod tests {
)]
#[case(
ActiveSonarrBlock::DeleteEpisodeFilePrompt,
SonarrEvent::DeleteEpisodeFile(None)
SonarrEvent::DeleteEpisodeFile(0)
)]
fn test_season_details_prompt_confirm_confirm_key(
#[case] prompt_block: ActiveSonarrBlock,
@@ -783,6 +783,34 @@ mod tests {
});
}
#[test]
fn test_extract_episode_file_id() {
let mut app = App::default();
app.data.sonarr_data = create_test_sonarr_data();
let episode_file_id = SeasonDetailsHandler::with(
DEFAULT_KEYBINDINGS.esc.key,
&mut app,
ActiveSonarrBlock::SeasonDetails,
None,
).extract_episode_file_id();
assert_eq!(episode_file_id, 0);
}
#[test]
#[should_panic(expected = "Season details have not been loaded")]
fn test_extract_episode_file_id_empty_season_details_modal_panics() {
let mut app = App::default();
let episode_file_id = SeasonDetailsHandler::with(
DEFAULT_KEYBINDINGS.esc.key,
&mut app,
ActiveSonarrBlock::SeasonDetails,
None,
).extract_episode_file_id();
}
#[test]
fn test_season_details_handler_is_not_ready_when_loading() {
let mut app = App::default();
+5 -22
View File
@@ -44,7 +44,7 @@ pub enum SonarrEvent {
ClearBlocklist,
DeleteBlocklistItem(i64),
DeleteDownload(i64),
DeleteEpisodeFile(Option<i64>),
DeleteEpisodeFile(i64),
DeleteIndexer(Option<i64>),
DeleteRootFolder(Option<i64>),
DeleteSeries(Option<DeleteSeriesParams>),
@@ -478,33 +478,16 @@ impl<'a, 'b> Network<'a, 'b> {
.await
}
async fn delete_sonarr_episode_file(&mut self, episode_file_id: Option<i64>) -> Result<()> {
let event = SonarrEvent::DeleteEpisodeFile(None);
let id = if let Some(ep_id) = episode_file_id {
ep_id
} else {
self
.app
.lock()
.await
.data
.sonarr_data
.season_details_modal
.as_ref()
.expect("Season details have not been loaded")
.episodes
.current_selection()
.episode_file_id
};
info!("Deleting Sonarr episode file for episode file with id: {id}");
async fn delete_sonarr_episode_file(&mut self, episode_file_id: i64) -> Result<()> {
let event = SonarrEvent::DeleteEpisodeFile(episode_file_id);
info!("Deleting Sonarr episode file for episode file with id: {episode_file_id}");
let request_props = self
.request_props_from(
event,
RequestMethod::Delete,
None::<()>,
Some(format!("/{id}")),
Some(format!("/{episode_file_id}")),
None,
)
.await;
+3 -56
View File
@@ -272,7 +272,7 @@ mod test {
fn test_resource_episode_file(
#[values(
SonarrEvent::GetEpisodeFiles(None),
SonarrEvent::DeleteEpisodeFile(None)
SonarrEvent::DeleteEpisodeFile(0)
)]
event: SonarrEvent,
) {
@@ -569,76 +569,23 @@ mod test {
None,
None,
None,
SonarrEvent::DeleteEpisodeFile(None),
SonarrEvent::DeleteEpisodeFile(1),
Some("/1"),
None,
)
.await;
app_arc.lock().await.data.sonarr_data.season_details_modal =
Some(SeasonDetailsModal::default());
app_arc
.lock()
.await
.data
.sonarr_data
.season_details_modal
.as_mut()
.unwrap()
.episodes
.set_items(vec![episode()]);
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
assert!(network
.handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(None))
.handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(1))
.await
.is_ok());
async_server.assert_async().await;
}
#[tokio::test]
async fn test_handle_delete_sonarr_episode_file_event_uses_provided_id() {
let (async_server, app_arc, _server) = mock_servarr_api(
RequestMethod::Delete,
None,
None,
None,
SonarrEvent::DeleteEpisodeFile(None),
Some("/1"),
None,
)
.await;
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
assert!(network
.handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(Some(1)))
.await
.is_ok());
async_server.assert_async().await;
}
#[tokio::test]
#[should_panic(expected = "Season details have not been loaded")]
async fn test_handle_delete_sonarr_episode_file_event_empty_season_details_modal_panics() {
let (_async_server, app_arc, _server) = mock_servarr_api(
RequestMethod::Delete,
None,
None,
None,
SonarrEvent::DeleteEpisodeFile(None),
Some("/1"),
None,
)
.await;
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
network
.handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(None))
.await
.unwrap();
}
#[tokio::test]
async fn test_handle_delete_sonarr_download_event() {
let (async_server, app_arc, _server) = mock_servarr_api(