Merge pull request #27 from Dark-Alex-17/race-condition-refactor
Race condition refactor
This commit is contained in:
@@ -4,6 +4,9 @@ set -e
|
||||
|
||||
echo "Running pre-push hook:"
|
||||
|
||||
echo "Executing: cargo fmt"
|
||||
cargo fmt
|
||||
|
||||
echo "Executing: make lint"
|
||||
make lint
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ set -e
|
||||
|
||||
echo "Running pre-push hook:"
|
||||
|
||||
echo "Executing: cargo fmt --check"
|
||||
cargo fmt --check
|
||||
|
||||
echo "Executing: make lint"
|
||||
make lint
|
||||
|
||||
|
||||
+42
-7
@@ -77,7 +77,9 @@ impl<'a> App<'a> {
|
||||
}
|
||||
ActiveRadarrBlock::TestIndexer => {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::TestIndexer(None).into())
|
||||
.dispatch_network_event(
|
||||
RadarrEvent::TestIndexer(self.extract_radarr_indexer_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveRadarrBlock::TestAllIndexers => {
|
||||
@@ -93,7 +95,7 @@ impl<'a> App<'a> {
|
||||
.dispatch_network_event(RadarrEvent::GetQueuedEvents.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetLogs(None).into())
|
||||
.dispatch_network_event(RadarrEvent::GetLogs(500).into())
|
||||
.await;
|
||||
}
|
||||
ActiveRadarrBlock::SystemUpdates => {
|
||||
@@ -103,17 +105,23 @@ impl<'a> App<'a> {
|
||||
}
|
||||
ActiveRadarrBlock::AddMovieSearchResults => {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::SearchNewMovie(None).into())
|
||||
.dispatch_network_event(
|
||||
RadarrEvent::SearchNewMovie(self.extract_movie_search_query().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveRadarrBlock::MovieDetails | ActiveRadarrBlock::FileInfo => {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetMovieDetails(None).into())
|
||||
.dispatch_network_event(
|
||||
RadarrEvent::GetMovieDetails(self.extract_movie_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveRadarrBlock::MovieHistory => {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetMovieHistory(None).into())
|
||||
.dispatch_network_event(
|
||||
RadarrEvent::GetMovieHistory(self.extract_movie_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveRadarrBlock::Cast | ActiveRadarrBlock::Crew => {
|
||||
@@ -123,7 +131,9 @@ impl<'a> App<'a> {
|
||||
|| movie_details_modal.movie_crew.items.is_empty() =>
|
||||
{
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetMovieCredits(None).into())
|
||||
.dispatch_network_event(
|
||||
RadarrEvent::GetMovieCredits(self.extract_movie_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
_ => (),
|
||||
@@ -132,7 +142,7 @@ impl<'a> App<'a> {
|
||||
ActiveRadarrBlock::ManualSearch => match self.data.radarr_data.movie_details_modal.as_ref() {
|
||||
Some(movie_details_modal) if movie_details_modal.movie_releases.items.is_empty() => {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetReleases(None).into())
|
||||
.dispatch_network_event(RadarrEvent::GetReleases(self.extract_movie_id().await).into())
|
||||
.await;
|
||||
}
|
||||
_ => (),
|
||||
@@ -219,4 +229,29 @@ impl<'a> App<'a> {
|
||||
.collection_movies
|
||||
.set_items(collection_movies);
|
||||
}
|
||||
|
||||
async fn extract_movie_id(&self) -> i64 {
|
||||
self.data.radarr_data.movies.current_selection().clone().id
|
||||
}
|
||||
|
||||
async fn extract_movie_search_query(&self) -> String {
|
||||
self
|
||||
.data
|
||||
.radarr_data
|
||||
.add_movie_search
|
||||
.as_ref()
|
||||
.expect("Add movie search is empty")
|
||||
.text
|
||||
.clone()
|
||||
}
|
||||
|
||||
async fn extract_radarr_indexer_id(&self) -> i64 {
|
||||
self
|
||||
.data
|
||||
.radarr_data
|
||||
.indexers
|
||||
.current_selection()
|
||||
.clone()
|
||||
.id
|
||||
}
|
||||
}
|
||||
|
||||
+781
-711
File diff suppressed because it is too large
Load Diff
+78
-14
@@ -38,30 +38,42 @@ impl<'a> App<'a> {
|
||||
}
|
||||
ActiveSonarrBlock::SeriesHistory => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetSeriesHistory(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetSeriesHistory(self.extract_series_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::SeasonDetails => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodes(None).into())
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodes(self.extract_series_id().await).into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeFiles(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetEpisodeFiles(self.extract_series_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::SeasonHistory => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetSeasonHistory(None).into())
|
||||
.await;
|
||||
if !self.data.sonarr_data.seasons.is_empty() {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetSeasonHistory(self.extract_series_id_season_number_tuple().await)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
ActiveSonarrBlock::ManualSeasonSearch => {
|
||||
match self.data.sonarr_data.season_details_modal.as_ref() {
|
||||
Some(season_details_modal) if season_details_modal.season_releases.is_empty() => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetSeasonReleases(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetSeasonReleases(self.extract_series_id_season_number_tuple().await)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
_ => (),
|
||||
@@ -69,12 +81,16 @@ impl<'a> App<'a> {
|
||||
}
|
||||
ActiveSonarrBlock::EpisodeDetails | ActiveSonarrBlock::EpisodeFile => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeDetails(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetEpisodeDetails(self.extract_episode_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::EpisodeHistory => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeHistory(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetEpisodeHistory(self.extract_episode_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::ManualEpisodeSearch => {
|
||||
@@ -82,7 +98,9 @@ impl<'a> App<'a> {
|
||||
if let Some(episode_details_modal) = season_details_modal.episode_details_modal.as_ref() {
|
||||
if episode_details_modal.episode_releases.is_empty() {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeReleases(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::GetEpisodeReleases(self.extract_episode_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +121,7 @@ impl<'a> App<'a> {
|
||||
}
|
||||
ActiveSonarrBlock::History => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetHistory(None).into())
|
||||
.dispatch_network_event(SonarrEvent::GetHistory(500).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::RootFolders => {
|
||||
@@ -126,7 +144,9 @@ impl<'a> App<'a> {
|
||||
}
|
||||
ActiveSonarrBlock::TestIndexer => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::TestIndexer(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::TestIndexer(self.extract_sonarr_indexer_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::TestAllIndexers => {
|
||||
@@ -142,12 +162,14 @@ impl<'a> App<'a> {
|
||||
.dispatch_network_event(SonarrEvent::GetQueuedEvents.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetLogs(None).into())
|
||||
.dispatch_network_event(SonarrEvent::GetLogs(500).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::AddSeriesSearchResults => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::SearchNewSeries(None).into())
|
||||
.dispatch_network_event(
|
||||
SonarrEvent::SearchNewSeries(self.extract_add_new_series_search_query().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::SystemUpdates => {
|
||||
@@ -242,4 +264,46 @@ impl<'a> App<'a> {
|
||||
.collect();
|
||||
self.data.sonarr_data.seasons.set_items(seasons);
|
||||
}
|
||||
|
||||
async fn extract_episode_id(&self) -> i64 {
|
||||
self
|
||||
.data
|
||||
.sonarr_data
|
||||
.season_details_modal
|
||||
.as_ref()
|
||||
.expect("Season details have not been loaded")
|
||||
.episodes
|
||||
.current_selection()
|
||||
.id
|
||||
}
|
||||
|
||||
async fn extract_series_id(&self) -> i64 {
|
||||
self.data.sonarr_data.series.current_selection().id
|
||||
}
|
||||
|
||||
async fn extract_series_id_season_number_tuple(&self) -> (i64, i64) {
|
||||
let series_id = self.data.sonarr_data.series.current_selection().id;
|
||||
let season_number = self
|
||||
.data
|
||||
.sonarr_data
|
||||
.seasons
|
||||
.current_selection()
|
||||
.season_number;
|
||||
(series_id, season_number)
|
||||
}
|
||||
|
||||
async fn extract_add_new_series_search_query(&self) -> String {
|
||||
self
|
||||
.data
|
||||
.sonarr_data
|
||||
.add_series_search
|
||||
.as_ref()
|
||||
.expect("Add series search is empty")
|
||||
.text
|
||||
.clone()
|
||||
}
|
||||
|
||||
async fn extract_sonarr_indexer_id(&self) -> i64 {
|
||||
self.data.sonarr_data.indexers.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
+152
-14
@@ -4,6 +4,9 @@ mod tests {
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data;
|
||||
use crate::models::servarr_models::Indexer;
|
||||
use crate::models::sonarr_models::Episode;
|
||||
use crate::{
|
||||
app::App,
|
||||
models::{
|
||||
@@ -40,6 +43,10 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_series_history_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeriesHistory)
|
||||
@@ -48,7 +55,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetSeriesHistory(None).into()
|
||||
SonarrEvent::GetSeriesHistory(1).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -80,6 +87,10 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_season_details_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeasonDetails)
|
||||
@@ -88,11 +99,11 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodes(None).into()
|
||||
SonarrEvent::GetEpisodes(1).into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeFiles(None).into()
|
||||
SonarrEvent::GetEpisodeFiles(1).into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -105,6 +116,14 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_season_history_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
app.data.sonarr_data.seasons.set_items(vec![Season {
|
||||
season_number: 1,
|
||||
..Season::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeasonHistory)
|
||||
@@ -113,16 +132,41 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetSeasonHistory(None).into()
|
||||
SonarrEvent::GetSeasonHistory((1, 1)).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_season_history_block_no_op_when_seasons_table_is_empty() {
|
||||
let (mut app, _) = construct_app_unit();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeasonHistory)
|
||||
.await;
|
||||
|
||||
assert!(!app.is_loading);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_season_search_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default());
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
app.data.sonarr_data.seasons.set_items(vec![Season {
|
||||
season_number: 1,
|
||||
..Season::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::ManualSeasonSearch)
|
||||
@@ -131,7 +175,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetSeasonReleases(None).into()
|
||||
SonarrEvent::GetSeasonReleases((1, 1)).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -174,6 +218,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_episode_details_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data = create_test_sonarr_data();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::EpisodeDetails)
|
||||
@@ -182,7 +227,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeDetails(None).into()
|
||||
SonarrEvent::GetEpisodeDetails(0).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -191,6 +236,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_episode_file_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data = create_test_sonarr_data();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::EpisodeFile)
|
||||
@@ -199,7 +245,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeDetails(None).into()
|
||||
SonarrEvent::GetEpisodeDetails(0).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -208,6 +254,12 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_episode_history_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
let mut season_details_modal = SeasonDetailsModal::default();
|
||||
season_details_modal.episodes.set_items(vec![Episode {
|
||||
id: 1,
|
||||
..Episode::default()
|
||||
}]);
|
||||
app.data.sonarr_data.season_details_modal = Some(season_details_modal);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::EpisodeHistory)
|
||||
@@ -216,7 +268,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeHistory(None).into()
|
||||
SonarrEvent::GetEpisodeHistory(1).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -225,10 +277,14 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_episode_search_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
let season_details_modal = SeasonDetailsModal {
|
||||
let mut season_details_modal = SeasonDetailsModal {
|
||||
episode_details_modal: Some(EpisodeDetailsModal::default()),
|
||||
..SeasonDetailsModal::default()
|
||||
};
|
||||
season_details_modal.episodes.set_items(vec![Episode {
|
||||
id: 1,
|
||||
..Episode::default()
|
||||
}]);
|
||||
app.data.sonarr_data.season_details_modal = Some(season_details_modal);
|
||||
|
||||
app
|
||||
@@ -238,7 +294,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeReleases(None).into()
|
||||
SonarrEvent::GetEpisodeReleases(1).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -293,7 +349,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetHistory(None).into()
|
||||
SonarrEvent::GetHistory(500).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -403,6 +459,10 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_test_indexer_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.indexers.set_items(vec![Indexer {
|
||||
id: 1,
|
||||
..Indexer::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::TestIndexer)
|
||||
@@ -411,7 +471,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::TestIndexer(None).into()
|
||||
SonarrEvent::TestIndexer(1).into()
|
||||
);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
@@ -451,7 +511,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetLogs(None).into()
|
||||
SonarrEvent::GetLogs(500).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -477,6 +537,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_add_series_search_results_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.add_series_search = Some("test search".into());
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::AddSeriesSearchResults)
|
||||
@@ -485,7 +546,7 @@ mod tests {
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::SearchNewSeries(None).into()
|
||||
SonarrEvent::SearchNewSeries("test search".into()).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
@@ -727,6 +788,83 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_episode_id() {
|
||||
let mut app = App::default();
|
||||
let mut season_details_modal = SeasonDetailsModal::default();
|
||||
season_details_modal.episodes.set_items(vec![Episode {
|
||||
id: 1,
|
||||
..Episode::default()
|
||||
}]);
|
||||
app.data.sonarr_data.season_details_modal = Some(season_details_modal);
|
||||
|
||||
assert_eq!(app.extract_episode_id().await, 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic(expected = "Season details have not been loaded")]
|
||||
async fn test_extract_episode_id_requires_season_details_modal_to_be_some() {
|
||||
let app = App::default();
|
||||
|
||||
assert_eq!(app.extract_episode_id().await, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_series_id() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
assert_eq!(app.extract_series_id().await, 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_series_id_season_number_tuple() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
id: 1,
|
||||
..Series::default()
|
||||
}]);
|
||||
app.data.sonarr_data.seasons.set_items(vec![Season {
|
||||
season_number: 1,
|
||||
..Season::default()
|
||||
}]);
|
||||
|
||||
assert_eq!(app.extract_series_id_season_number_tuple().await, (1, 1));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_add_new_series_search_query() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.add_series_search = Some("test search".into());
|
||||
|
||||
assert_str_eq!(
|
||||
app.extract_add_new_series_search_query().await,
|
||||
"test search"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic(expected = "Add series search is empty")]
|
||||
async fn test_extract_add_new_series_search_query_panics_when_the_query_is_not_set() {
|
||||
let app = App::default();
|
||||
|
||||
app.extract_add_new_series_search_query().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_sonarr_indexer_id() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.indexers.set_items(vec![Indexer {
|
||||
id: 1,
|
||||
..Indexer::default()
|
||||
}]);
|
||||
|
||||
assert_eq!(app.extract_sonarr_indexer_id().await, 1);
|
||||
}
|
||||
|
||||
fn construct_app_unit<'a>() -> (App<'a>, mpsc::Receiver<NetworkEvent>) {
|
||||
let (sync_network_tx, sync_network_rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App {
|
||||
|
||||
@@ -4,6 +4,8 @@ use anyhow::Result;
|
||||
use clap::{arg, command, ArgAction, Subcommand};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::RadarrCommand;
|
||||
use crate::models::servarr_models::AddRootFolderBody;
|
||||
use crate::{
|
||||
app::App,
|
||||
cli::{CliCommandHandler, Command},
|
||||
@@ -11,8 +13,6 @@ use crate::{
|
||||
network::{radarr_network::RadarrEvent, NetworkTrait},
|
||||
};
|
||||
|
||||
use super::RadarrCommand;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "add_command_handler_tests.rs"]
|
||||
mod add_command_handler_tests;
|
||||
@@ -125,6 +125,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrAddCommand> for RadarrAddCommandHan
|
||||
minimum_availability: minimum_availability.to_string(),
|
||||
monitored: !disable_monitoring,
|
||||
tags,
|
||||
tag_input_string: None,
|
||||
add_options: AddMovieOptions {
|
||||
monitor: monitor.to_string(),
|
||||
search_for_movie: !no_search_for_movie,
|
||||
@@ -132,14 +133,17 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrAddCommand> for RadarrAddCommandHan
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::AddMovie(Some(body)).into())
|
||||
.handle_network_event(RadarrEvent::AddMovie(body).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrAddCommand::RootFolder { root_folder_path } => {
|
||||
let add_root_folder_body = AddRootFolderBody {
|
||||
path: root_folder_path,
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::AddRootFolder(Some(root_folder_path)).into())
|
||||
.handle_network_event(RadarrEvent::AddRootFolder(add_root_folder_body).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -368,6 +368,7 @@ mod tests {
|
||||
use super::*;
|
||||
use mockall::predicate::eq;
|
||||
|
||||
use crate::models::servarr_models::AddRootFolderBody;
|
||||
use serde_json::json;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
@@ -381,6 +382,7 @@ mod tests {
|
||||
minimum_availability: "released".to_owned(),
|
||||
monitored: false,
|
||||
tags: vec![1, 2],
|
||||
tag_input_string: None,
|
||||
add_options: AddMovieOptions {
|
||||
monitor: "movieAndCollection".to_owned(),
|
||||
search_for_movie: false,
|
||||
@@ -390,7 +392,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::AddMovie(Some(expected_add_movie_body)).into(),
|
||||
RadarrEvent::AddMovie(expected_add_movie_body).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -420,11 +422,14 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_handle_add_root_folder_command() {
|
||||
let expected_root_folder_path = "/nfs/test".to_owned();
|
||||
let expected_add_root_folder_body = AddRootFolderBody {
|
||||
path: expected_root_folder_path.clone(),
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::AddRootFolder(Some(expected_root_folder_path.clone())).into(),
|
||||
RadarrEvent::AddRootFolder(expected_add_root_folder_body).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -89,21 +89,21 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrDeleteCommand> for RadarrDeleteComm
|
||||
RadarrDeleteCommand::BlocklistItem { blocklist_item_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::DeleteBlocklistItem(Some(blocklist_item_id)).into())
|
||||
.handle_network_event(RadarrEvent::DeleteBlocklistItem(blocklist_item_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrDeleteCommand::Download { download_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::DeleteDownload(Some(download_id)).into())
|
||||
.handle_network_event(RadarrEvent::DeleteDownload(download_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrDeleteCommand::Indexer { indexer_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::DeleteIndexer(Some(indexer_id)).into())
|
||||
.handle_network_event(RadarrEvent::DeleteIndexer(indexer_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -119,14 +119,14 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrDeleteCommand> for RadarrDeleteComm
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::DeleteMovie(Some(delete_movie_params)).into())
|
||||
.handle_network_event(RadarrEvent::DeleteMovie(delete_movie_params).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrDeleteCommand::RootFolder { root_folder_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::DeleteRootFolder(Some(root_folder_id)).into())
|
||||
.handle_network_event(RadarrEvent::DeleteRootFolder(root_folder_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DeleteBlocklistItem(Some(expected_blocklist_item_id)).into(),
|
||||
RadarrEvent::DeleteBlocklistItem(expected_blocklist_item_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -299,7 +299,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DeleteDownload(Some(expected_download_id)).into(),
|
||||
RadarrEvent::DeleteDownload(expected_download_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -325,7 +325,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DeleteIndexer(Some(expected_indexer_id)).into(),
|
||||
RadarrEvent::DeleteIndexer(expected_indexer_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -355,7 +355,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DeleteMovie(Some(expected_delete_movie_params)).into(),
|
||||
RadarrEvent::DeleteMovie(expected_delete_movie_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -385,7 +385,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DeleteRootFolder(Some(expected_root_folder_id)).into(),
|
||||
RadarrEvent::DeleteRootFolder(expected_root_folder_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -390,7 +390,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrEditCommand> for RadarrEditCommandH
|
||||
};
|
||||
self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::EditAllIndexerSettings(Some(params)).into())
|
||||
.handle_network_event(RadarrEvent::EditAllIndexerSettings(params).into())
|
||||
.await?;
|
||||
"All indexer settings updated".to_owned()
|
||||
} else {
|
||||
@@ -420,7 +420,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrEditCommand> for RadarrEditCommandH
|
||||
};
|
||||
self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::EditCollection(Some(edit_collection_params)).into())
|
||||
.handle_network_event(RadarrEvent::EditCollection(edit_collection_params).into())
|
||||
.await?;
|
||||
"Collection updated".to_owned()
|
||||
}
|
||||
@@ -455,13 +455,14 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrEditCommand> for RadarrEditCommandH
|
||||
api_key,
|
||||
seed_ratio,
|
||||
tags: tag,
|
||||
tag_input_string: None,
|
||||
priority,
|
||||
clear_tags,
|
||||
};
|
||||
|
||||
self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::EditIndexer(Some(edit_indexer_params)).into())
|
||||
.handle_network_event(RadarrEvent::EditIndexer(edit_indexer_params).into())
|
||||
.await?;
|
||||
"Indexer updated".to_owned()
|
||||
}
|
||||
@@ -483,12 +484,13 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrEditCommand> for RadarrEditCommandH
|
||||
quality_profile_id,
|
||||
root_folder_path,
|
||||
tags: tag,
|
||||
tag_input_string: None,
|
||||
clear_tags,
|
||||
};
|
||||
|
||||
self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::EditMovie(Some(edit_movie_params)).into())
|
||||
.handle_network_event(RadarrEvent::EditMovie(edit_movie_params).into())
|
||||
.await?;
|
||||
"Movie Updated".to_owned()
|
||||
}
|
||||
|
||||
@@ -857,7 +857,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditAllIndexerSettings(Some(expected_edit_all_indexer_settings)).into(),
|
||||
RadarrEvent::EditAllIndexerSettings(expected_edit_all_indexer_settings).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -928,7 +928,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditAllIndexerSettings(Some(expected_edit_all_indexer_settings)).into(),
|
||||
RadarrEvent::EditAllIndexerSettings(expected_edit_all_indexer_settings).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1000,7 +1000,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditAllIndexerSettings(Some(expected_edit_all_indexer_settings)).into(),
|
||||
RadarrEvent::EditAllIndexerSettings(expected_edit_all_indexer_settings).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1047,7 +1047,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditCollection(Some(expected_edit_collection_params)).into(),
|
||||
RadarrEvent::EditCollection(expected_edit_collection_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1089,7 +1089,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditCollection(Some(expected_edit_collection_params)).into(),
|
||||
RadarrEvent::EditCollection(expected_edit_collection_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1131,7 +1131,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditCollection(Some(expected_edit_collection_params)).into(),
|
||||
RadarrEvent::EditCollection(expected_edit_collection_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1171,6 +1171,7 @@ mod tests {
|
||||
api_key: Some("testKey".to_owned()),
|
||||
seed_ratio: Some("1.2".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
priority: Some(25),
|
||||
clear_tags: false,
|
||||
};
|
||||
@@ -1178,7 +1179,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(),
|
||||
RadarrEvent::EditIndexer(expected_edit_indexer_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1224,6 +1225,7 @@ mod tests {
|
||||
api_key: Some("testKey".to_owned()),
|
||||
seed_ratio: Some("1.2".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
priority: Some(25),
|
||||
clear_tags: false,
|
||||
};
|
||||
@@ -1231,7 +1233,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(),
|
||||
RadarrEvent::EditIndexer(expected_edit_indexer_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1277,6 +1279,7 @@ mod tests {
|
||||
api_key: Some("testKey".to_owned()),
|
||||
seed_ratio: Some("1.2".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
priority: Some(25),
|
||||
clear_tags: false,
|
||||
};
|
||||
@@ -1284,7 +1287,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(),
|
||||
RadarrEvent::EditIndexer(expected_edit_indexer_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1327,13 +1330,14 @@ mod tests {
|
||||
quality_profile_id: Some(1),
|
||||
root_folder_path: Some("/nfs/test".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
clear_tags: false,
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditMovie(Some(expected_edit_movie_params)).into(),
|
||||
RadarrEvent::EditMovie(expected_edit_movie_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1369,13 +1373,14 @@ mod tests {
|
||||
quality_profile_id: Some(1),
|
||||
root_folder_path: Some("/nfs/test".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
clear_tags: false,
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditMovie(Some(expected_edit_movie_params)).into(),
|
||||
RadarrEvent::EditMovie(expected_edit_movie_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -1411,13 +1416,14 @@ mod tests {
|
||||
quality_profile_id: Some(1),
|
||||
root_folder_path: Some("/nfs/test".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
clear_tags: false,
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditMovie(Some(expected_edit_movie_params)).into(),
|
||||
RadarrEvent::EditMovie(expected_edit_movie_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -90,14 +90,14 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrGetCommand> for RadarrGetCommandHan
|
||||
RadarrGetCommand::MovieDetails { movie_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::GetMovieDetails(Some(movie_id)).into())
|
||||
.handle_network_event(RadarrEvent::GetMovieDetails(movie_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrGetCommand::MovieHistory { movie_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::GetMovieHistory(Some(movie_id)).into())
|
||||
.handle_network_event(RadarrEvent::GetMovieHistory(movie_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::GetMovieDetails(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::GetMovieDetails(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -208,7 +208,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::GetMovieHistory(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::GetMovieHistory(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -131,7 +131,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrListCommand> for RadarrListCommandH
|
||||
} => {
|
||||
let logs = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::GetLogs(Some(events)).into())
|
||||
.handle_network_event(RadarrEvent::GetLogs(events).into())
|
||||
.await?;
|
||||
|
||||
if output_in_log_format {
|
||||
@@ -152,7 +152,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrListCommand> for RadarrListCommandH
|
||||
RadarrListCommand::MovieCredits { movie_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::GetMovieCredits(Some(movie_id)).into())
|
||||
.handle_network_event(RadarrEvent::GetMovieCredits(movie_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::GetMovieCredits(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::GetMovieCredits(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -189,7 +189,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::GetLogs(Some(expected_events)).into(),
|
||||
RadarrEvent::GetLogs(expected_events).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -209,7 +209,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrCommand> for RadarrCliHandler<'a, '
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::DownloadRelease(Some(params)).into())
|
||||
.handle_network_event(RadarrEvent::DownloadRelease(params).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -217,28 +217,28 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrCommand> for RadarrCliHandler<'a, '
|
||||
println!("Searching for releases. This may take a minute...");
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::GetReleases(Some(movie_id)).into())
|
||||
.handle_network_event(RadarrEvent::GetReleases(movie_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrCommand::SearchNewMovie { query } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::SearchNewMovie(Some(query)).into())
|
||||
.handle_network_event(RadarrEvent::SearchNewMovie(query).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrCommand::StartTask { task_name } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::StartTask(Some(task_name)).into())
|
||||
.handle_network_event(RadarrEvent::StartTask(task_name).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
RadarrCommand::TestIndexer { indexer_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::TestIndexer(Some(indexer_id)).into())
|
||||
.handle_network_event(RadarrEvent::TestIndexer(indexer_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -253,7 +253,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrCommand> for RadarrCliHandler<'a, '
|
||||
RadarrCommand::TriggerAutomaticSearch { movie_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::TriggerAutomaticSearch(Some(movie_id)).into())
|
||||
.handle_network_event(RadarrEvent::TriggerAutomaticSearch(movie_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -293,9 +293,9 @@ mod tests {
|
||||
)))
|
||||
});
|
||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
||||
let claer_blocklist_command = RadarrCommand::ClearBlocklist;
|
||||
let clear_blocklist_command = RadarrCommand::ClearBlocklist;
|
||||
|
||||
let result = RadarrCliHandler::with(&app_arc, claer_blocklist_command, &mut mock_network)
|
||||
let result = RadarrCliHandler::with(&app_arc, clear_blocklist_command, &mut mock_network)
|
||||
.handle()
|
||||
.await;
|
||||
|
||||
@@ -313,7 +313,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DownloadRelease(Some(expected_release_download_body)).into(),
|
||||
RadarrEvent::DownloadRelease(expected_release_download_body).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -342,7 +342,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::GetReleases(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::GetReleases(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -367,7 +367,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::SearchNewMovie(Some(expected_search_query)).into(),
|
||||
RadarrEvent::SearchNewMovie(expected_search_query).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -394,7 +394,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::StartTask(Some(expected_task_name)).into(),
|
||||
RadarrEvent::StartTask(expected_task_name).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -421,7 +421,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::TestIndexer(Some(expected_indexer_id)).into(),
|
||||
RadarrEvent::TestIndexer(expected_indexer_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -468,7 +468,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::TriggerAutomaticSearch(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::TriggerAutomaticSearch(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -524,7 +524,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::DeleteBlocklistItem(Some(expected_blocklist_item_id)).into(),
|
||||
RadarrEvent::DeleteBlocklistItem(expected_blocklist_item_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -584,7 +584,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::EditAllIndexerSettings(Some(expected_edit_all_indexer_settings)).into(),
|
||||
RadarrEvent::EditAllIndexerSettings(expected_edit_all_indexer_settings).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -654,7 +654,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::GetMovieCredits(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::GetMovieCredits(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -680,7 +680,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::UpdateAndScan(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::UpdateAndScan(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -88,7 +88,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrRefreshCommand>
|
||||
RadarrRefreshCommand::Movie { movie_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(RadarrEvent::UpdateAndScan(Some(movie_id)).into())
|
||||
.handle_network_event(RadarrEvent::UpdateAndScan(movie_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
RadarrEvent::UpdateAndScan(Some(expected_movie_id)).into(),
|
||||
RadarrEvent::UpdateAndScan(expected_movie_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -4,6 +4,8 @@ use anyhow::Result;
|
||||
use clap::{ArgAction, Subcommand};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::SonarrCommand;
|
||||
use crate::models::servarr_models::AddRootFolderBody;
|
||||
use crate::{
|
||||
app::App,
|
||||
cli::{CliCommandHandler, Command},
|
||||
@@ -11,8 +13,6 @@ use crate::{
|
||||
network::{sonarr_network::SonarrEvent, NetworkTrait},
|
||||
};
|
||||
|
||||
use super::SonarrCommand;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "add_command_handler_tests.rs"]
|
||||
mod add_command_handler_tests;
|
||||
@@ -140,6 +140,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrAddCommand> for SonarrAddCommandHan
|
||||
series_type: series_type.to_string(),
|
||||
season_folder: !disable_season_folders,
|
||||
tags,
|
||||
tag_input_string: None,
|
||||
add_options: AddSeriesOptions {
|
||||
monitor: monitor.to_string(),
|
||||
search_for_cutoff_unmet_episodes: !no_search_for_series,
|
||||
@@ -148,14 +149,17 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrAddCommand> for SonarrAddCommandHan
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::AddSeries(Some(body)).into())
|
||||
.handle_network_event(SonarrEvent::AddSeries(body).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrAddCommand::RootFolder { root_folder_path } => {
|
||||
let add_root_folder_body = AddRootFolderBody {
|
||||
path: root_folder_path,
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::AddRootFolder(Some(root_folder_path)).into())
|
||||
.handle_network_event(SonarrEvent::AddRootFolder(add_root_folder_body).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -469,17 +469,21 @@ mod tests {
|
||||
use super::*;
|
||||
use mockall::predicate::eq;
|
||||
|
||||
use crate::models::servarr_models::AddRootFolderBody;
|
||||
use serde_json::json;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_add_root_folder_command() {
|
||||
let expected_root_folder_path = "/nfs/test".to_owned();
|
||||
let expected_add_root_folder_body = AddRootFolderBody {
|
||||
path: expected_root_folder_path.clone(),
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::AddRootFolder(Some(expected_root_folder_path.clone())).into(),
|
||||
SonarrEvent::AddRootFolder(expected_add_root_folder_body.clone()).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -511,6 +515,7 @@ mod tests {
|
||||
series_type: "anime".to_owned(),
|
||||
monitored: false,
|
||||
tags: vec![1, 2],
|
||||
tag_input_string: None,
|
||||
season_folder: false,
|
||||
add_options: AddSeriesOptions {
|
||||
monitor: "future".to_owned(),
|
||||
@@ -522,7 +527,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::AddSeries(Some(expected_add_series_body)).into(),
|
||||
SonarrEvent::AddSeries(expected_add_series_body).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -94,35 +94,35 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrDeleteCommand> for SonarrDeleteComm
|
||||
SonarrDeleteCommand::BlocklistItem { blocklist_item_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::DeleteBlocklistItem(Some(blocklist_item_id)).into())
|
||||
.handle_network_event(SonarrEvent::DeleteBlocklistItem(blocklist_item_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrDeleteCommand::Download { download_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::DeleteDownload(Some(download_id)).into())
|
||||
.handle_network_event(SonarrEvent::DeleteDownload(download_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
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)?
|
||||
}
|
||||
SonarrDeleteCommand::Indexer { indexer_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::DeleteIndexer(Some(indexer_id)).into())
|
||||
.handle_network_event(SonarrEvent::DeleteIndexer(indexer_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrDeleteCommand::RootFolder { root_folder_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::DeleteRootFolder(Some(root_folder_id)).into())
|
||||
.handle_network_event(SonarrEvent::DeleteRootFolder(root_folder_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -138,7 +138,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrDeleteCommand> for SonarrDeleteComm
|
||||
};
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::DeleteSeries(Some(delete_series_params)).into())
|
||||
.handle_network_event(SonarrEvent::DeleteSeries(delete_series_params).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::DeleteBlocklistItem(Some(expected_blocklist_item_id)).into(),
|
||||
SonarrEvent::DeleteBlocklistItem(expected_blocklist_item_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -332,7 +332,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::DeleteDownload(Some(expected_download_id)).into(),
|
||||
SonarrEvent::DeleteDownload(expected_download_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -351,6 +351,32 @@ 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;
|
||||
@@ -358,7 +384,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::DeleteIndexer(Some(expected_indexer_id)).into(),
|
||||
SonarrEvent::DeleteIndexer(expected_indexer_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -384,7 +410,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::DeleteRootFolder(Some(expected_root_folder_id)).into(),
|
||||
SonarrEvent::DeleteRootFolder(expected_root_folder_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -414,7 +440,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::DeleteSeries(Some(expected_delete_series_params)).into(),
|
||||
SonarrEvent::DeleteSeries(expected_delete_series_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -274,7 +274,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrEditCommand> for SonarrEditCommandH
|
||||
};
|
||||
self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::EditAllIndexerSettings(Some(params)).into())
|
||||
.handle_network_event(SonarrEvent::EditAllIndexerSettings(params).into())
|
||||
.await?;
|
||||
"All indexer settings updated".to_owned()
|
||||
} else {
|
||||
@@ -312,13 +312,14 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrEditCommand> for SonarrEditCommandH
|
||||
api_key,
|
||||
seed_ratio,
|
||||
tags: tag,
|
||||
tag_input_string: None,
|
||||
priority,
|
||||
clear_tags,
|
||||
};
|
||||
|
||||
self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::EditIndexer(Some(edit_indexer_params)).into())
|
||||
.handle_network_event(SonarrEvent::EditIndexer(edit_indexer_params).into())
|
||||
.await?;
|
||||
"Indexer updated".to_owned()
|
||||
}
|
||||
@@ -347,12 +348,13 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrEditCommand> for SonarrEditCommandH
|
||||
language_profile_id,
|
||||
root_folder_path,
|
||||
tags: tag,
|
||||
tag_input_string: None,
|
||||
clear_tags,
|
||||
};
|
||||
|
||||
self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::EditSeries(Some(edit_series_params)).into())
|
||||
.handle_network_event(SonarrEvent::EditSeries(edit_series_params).into())
|
||||
.await?;
|
||||
"Series Updated".to_owned()
|
||||
}
|
||||
|
||||
@@ -650,7 +650,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::EditAllIndexerSettings(Some(expected_edit_all_indexer_settings)).into(),
|
||||
SonarrEvent::EditAllIndexerSettings(expected_edit_all_indexer_settings).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -689,6 +689,7 @@ mod tests {
|
||||
api_key: Some("testKey".to_owned()),
|
||||
seed_ratio: Some("1.2".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
priority: Some(25),
|
||||
clear_tags: false,
|
||||
};
|
||||
@@ -696,7 +697,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(),
|
||||
SonarrEvent::EditIndexer(expected_edit_indexer_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -741,13 +742,14 @@ mod tests {
|
||||
language_profile_id: Some(1),
|
||||
root_folder_path: Some("/nfs/test".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
clear_tags: false,
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::EditSeries(Some(expected_edit_series_params)).into(),
|
||||
SonarrEvent::EditSeries(expected_edit_series_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -788,13 +790,14 @@ mod tests {
|
||||
language_profile_id: Some(1),
|
||||
root_folder_path: Some("/nfs/test".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
clear_tags: false,
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::EditSeries(Some(expected_edit_series_params)).into(),
|
||||
SonarrEvent::EditSeries(expected_edit_series_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -835,13 +838,14 @@ mod tests {
|
||||
language_profile_id: Some(1),
|
||||
root_folder_path: Some("/nfs/test".to_owned()),
|
||||
tags: Some(vec![1, 2]),
|
||||
tag_input_string: None,
|
||||
clear_tags: false,
|
||||
};
|
||||
let mut mock_network = MockNetworkTrait::new();
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::EditSeries(Some(expected_edit_series_params)).into(),
|
||||
SonarrEvent::EditSeries(expected_edit_series_params).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -83,7 +83,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrGetCommand> for SonarrGetCommandHan
|
||||
SonarrGetCommand::EpisodeDetails { episode_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetEpisodeDetails(Some(episode_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetEpisodeDetails(episode_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -104,7 +104,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrGetCommand> for SonarrGetCommandHan
|
||||
SonarrGetCommand::SeriesDetails { series_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetSeriesDetails(Some(series_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetSeriesDetails(series_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetEpisodeDetails(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::GetEpisodeDetails(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -232,7 +232,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetSeriesDetails(Some(expected_series_id)).into(),
|
||||
SonarrEvent::GetSeriesDetails(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -163,28 +163,28 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrListCommand> for SonarrListCommandH
|
||||
SonarrListCommand::Episodes { series_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetEpisodes(Some(series_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetEpisodes(series_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrListCommand::EpisodeFiles { series_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetEpisodeFiles(Some(series_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetEpisodeFiles(series_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrListCommand::EpisodeHistory { episode_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetEpisodeHistory(Some(episode_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetEpisodeHistory(episode_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrListCommand::History { events: items } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetHistory(Some(items)).into())
|
||||
.handle_network_event(SonarrEvent::GetHistory(items).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -208,7 +208,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrListCommand> for SonarrListCommandH
|
||||
} => {
|
||||
let logs = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetLogs(Some(events)).into())
|
||||
.handle_network_event(SonarrEvent::GetLogs(events).into())
|
||||
.await?;
|
||||
|
||||
if output_in_log_format {
|
||||
@@ -246,9 +246,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrListCommand> for SonarrListCommandH
|
||||
} => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(
|
||||
SonarrEvent::GetSeasonHistory(Some((series_id, season_number))).into(),
|
||||
)
|
||||
.handle_network_event(SonarrEvent::GetSeasonHistory((series_id, season_number)).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -262,7 +260,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrListCommand> for SonarrListCommandH
|
||||
SonarrListCommand::SeriesHistory { series_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetSeriesHistory(Some(series_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetSeriesHistory(series_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetEpisodes(Some(expected_series_id)).into(),
|
||||
SonarrEvent::GetEpisodes(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -355,7 +355,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetEpisodeFiles(Some(expected_series_id)).into(),
|
||||
SonarrEvent::GetEpisodeFiles(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -381,7 +381,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetHistory(Some(expected_events)).into(),
|
||||
SonarrEvent::GetHistory(expected_events).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -407,7 +407,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetLogs(Some(expected_events)).into(),
|
||||
SonarrEvent::GetLogs(expected_events).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -435,7 +435,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetSeriesHistory(Some(expected_series_id)).into(),
|
||||
SonarrEvent::GetSeriesHistory(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -461,7 +461,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetEpisodeHistory(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::GetEpisodeHistory(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -488,7 +488,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetSeasonHistory(Some((expected_series_id, expected_season_number))).into(),
|
||||
SonarrEvent::GetSeasonHistory((expected_series_id, expected_season_number)).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -75,7 +75,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrManualSearchCommand>
|
||||
println!("Searching for episode releases. This may take a minute...");
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::GetEpisodeReleases(Some(episode_id)).into())
|
||||
.handle_network_event(SonarrEvent::GetEpisodeReleases(episode_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -86,9 +86,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrManualSearchCommand>
|
||||
println!("Searching for season releases. This may take a minute...");
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(
|
||||
SonarrEvent::GetSeasonReleases(Some((series_id, season_number))).into(),
|
||||
)
|
||||
.handle_network_event(SonarrEvent::GetSeasonReleases((series_id, season_number)).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetEpisodeReleases(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::GetEpisodeReleases(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -160,7 +160,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetSeasonReleases(Some((expected_series_id, expected_season_number))).into(),
|
||||
SonarrEvent::GetSeasonReleases((expected_series_id, expected_season_number)).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -245,21 +245,21 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrCommand> for SonarrCliHandler<'a, '
|
||||
SonarrCommand::SearchNewSeries { query } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::SearchNewSeries(Some(query)).into())
|
||||
.handle_network_event(SonarrEvent::SearchNewSeries(query).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrCommand::StartTask { task_name } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::StartTask(Some(task_name)).into())
|
||||
.handle_network_event(SonarrEvent::StartTask(task_name).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
SonarrCommand::TestIndexer { indexer_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::TestIndexer(Some(indexer_id)).into())
|
||||
.handle_network_event(SonarrEvent::TestIndexer(indexer_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -274,7 +274,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrCommand> for SonarrCliHandler<'a, '
|
||||
SonarrCommand::ToggleEpisodeMonitoring { episode_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::ToggleEpisodeMonitoring(Some(episode_id)).into())
|
||||
.handle_network_event(SonarrEvent::ToggleEpisodeMonitoring(episode_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -285,7 +285,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrCommand> for SonarrCliHandler<'a, '
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(
|
||||
SonarrEvent::ToggleSeasonMonitoring(Some((series_id, season_number))).into(),
|
||||
SonarrEvent::ToggleSeasonMonitoring((series_id, season_number)).into(),
|
||||
)
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
|
||||
@@ -71,7 +71,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrRefreshCommand>
|
||||
SonarrRefreshCommand::Series { series_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::UpdateAndScanSeries(Some(series_id)).into())
|
||||
.handle_network_event(SonarrEvent::UpdateAndScanSeries(series_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::UpdateAndScanSeries(Some(expected_series_id)).into(),
|
||||
SonarrEvent::UpdateAndScanSeries(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -346,7 +346,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::DeleteBlocklistItem(Some(expected_blocklist_item_id)).into(),
|
||||
SonarrEvent::DeleteBlocklistItem(expected_blocklist_item_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -434,7 +434,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::EditAllIndexerSettings(Some(expected_edit_all_indexer_settings)).into(),
|
||||
SonarrEvent::EditAllIndexerSettings(expected_edit_all_indexer_settings).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -470,7 +470,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::GetEpisodeReleases(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::GetEpisodeReleases(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -498,7 +498,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -571,7 +571,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::UpdateAndScanSeries(Some(expected_series_id)).into(),
|
||||
SonarrEvent::UpdateAndScanSeries(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -597,7 +597,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::SearchNewSeries(Some(expected_search_query)).into(),
|
||||
SonarrEvent::SearchNewSeries(expected_search_query).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -624,7 +624,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::StartTask(Some(expected_task_name)).into(),
|
||||
SonarrEvent::StartTask(expected_task_name).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -651,7 +651,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::TestIndexer(Some(expected_indexer_id)).into(),
|
||||
SonarrEvent::TestIndexer(expected_indexer_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -698,7 +698,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::ToggleEpisodeMonitoring(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::ToggleEpisodeMonitoring(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -729,8 +729,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::ToggleSeasonMonitoring(Some((expected_series_id, expected_season_number)))
|
||||
.into(),
|
||||
SonarrEvent::ToggleSeasonMonitoring((expected_series_id, expected_season_number)).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -83,7 +83,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrTriggerAutomaticSearchCommand>
|
||||
SonarrTriggerAutomaticSearchCommand::Series { series_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::TriggerAutomaticSeriesSearch(Some(series_id)).into())
|
||||
.handle_network_event(SonarrEvent::TriggerAutomaticSeriesSearch(series_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
@@ -94,7 +94,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrTriggerAutomaticSearchCommand>
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch(Some((series_id, season_number))).into(),
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch((series_id, season_number)).into(),
|
||||
)
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
@@ -102,7 +102,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrTriggerAutomaticSearchCommand>
|
||||
SonarrTriggerAutomaticSearchCommand::Episode { episode_id } => {
|
||||
let resp = self
|
||||
.network
|
||||
.handle_network_event(SonarrEvent::TriggerAutomaticEpisodeSearch(Some(episode_id)).into())
|
||||
.handle_network_event(SonarrEvent::TriggerAutomaticEpisodeSearch(episode_id).into())
|
||||
.await?;
|
||||
serde_json::to_string_pretty(&resp)?
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(Some(expected_series_id)).into(),
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(expected_series_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -197,11 +197,8 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch(Some((
|
||||
expected_series_id,
|
||||
expected_season_number,
|
||||
)))
|
||||
.into(),
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch((expected_series_id, expected_season_number))
|
||||
.into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
@@ -233,7 +230,7 @@ mod tests {
|
||||
mock_network
|
||||
.expect_handle_network_event()
|
||||
.with(eq::<NetworkEvent>(
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(Some(expected_episode_id)).into(),
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(expected_episode_id).into(),
|
||||
))
|
||||
.times(1)
|
||||
.returning(|_| {
|
||||
|
||||
@@ -160,7 +160,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveRadarrBlock::Blocklist,
|
||||
ActiveRadarrBlock::DeleteBlocklistItemPrompt,
|
||||
RadarrEvent::DeleteBlocklistItem(None)
|
||||
RadarrEvent::DeleteBlocklistItem(3)
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Blocklist,
|
||||
@@ -361,7 +361,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveRadarrBlock::Blocklist,
|
||||
ActiveRadarrBlock::DeleteBlocklistItemPrompt,
|
||||
RadarrEvent::DeleteBlocklistItem(None)
|
||||
RadarrEvent::DeleteBlocklistItem(3)
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Blocklist,
|
||||
@@ -541,6 +541,22 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_blocklist_item_id() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||
|
||||
let blocklist_item_id = BlocklistHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::Blocklist,
|
||||
None,
|
||||
)
|
||||
.extract_blocklist_item_id();
|
||||
|
||||
assert_eq!(blocklist_item_id, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blocklist_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -28,6 +28,10 @@ impl<'a, 'b> BlocklistHandler<'a, 'b> {
|
||||
self.app.data.radarr_data.blocklist,
|
||||
BlocklistItem
|
||||
);
|
||||
|
||||
fn extract_blocklist_item_id(&self) -> i64 {
|
||||
self.app.data.radarr_data.blocklist.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a, 'b> {
|
||||
@@ -98,8 +102,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
||||
match self.active_radarr_block {
|
||||
ActiveRadarrBlock::DeleteBlocklistItemPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteBlocklistItem(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteBlocklistItem(
|
||||
self.extract_blocklist_item_id(),
|
||||
));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -151,8 +156,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
||||
ActiveRadarrBlock::DeleteBlocklistItemPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteBlocklistItem(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteBlocklistItem(
|
||||
self.extract_blocklist_item_id(),
|
||||
));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::EditCollectionParams;
|
||||
use crate::models::servarr_data::radarr::modals::EditCollectionModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS};
|
||||
use crate::models::Scrollable;
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
@@ -18,6 +20,51 @@ pub(super) struct EditCollectionHandler<'a, 'b> {
|
||||
context: Option<ActiveRadarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> EditCollectionHandler<'a, 'b> {
|
||||
fn build_edit_collection_params(&mut self) -> EditCollectionParams {
|
||||
let collection_id = self.app.data.radarr_data.collections.current_selection().id;
|
||||
let EditCollectionModal {
|
||||
path,
|
||||
search_on_add,
|
||||
minimum_availability_list,
|
||||
monitored,
|
||||
quality_profile_list,
|
||||
} = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.edit_collection_modal
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let quality_profile = quality_profile_list.current_selection();
|
||||
let quality_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.quality_profile_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == quality_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let root_folder_path: String = path.text.clone();
|
||||
let monitored = monitored.unwrap_or_default();
|
||||
let search_on_add = search_on_add.unwrap_or_default();
|
||||
let minimum_availability = *minimum_availability_list.current_selection();
|
||||
self.app.data.radarr_data.edit_collection_modal = None;
|
||||
|
||||
EditCollectionParams {
|
||||
collection_id,
|
||||
monitored: Some(monitored),
|
||||
minimum_availability: Some(minimum_availability),
|
||||
quality_profile_id: Some(quality_profile_id),
|
||||
root_folder_path: Some(root_folder_path),
|
||||
search_on_add: Some(search_on_add),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||
EDIT_COLLECTION_BLOCKS.contains(&active_block)
|
||||
@@ -190,8 +237,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
||||
match self.app.data.radarr_data.selected_block.get_active_block() {
|
||||
ActiveRadarrBlock::EditCollectionConfirmPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::EditCollection(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(
|
||||
self.build_edit_collection_params(),
|
||||
));
|
||||
self.app.should_refresh = true;
|
||||
}
|
||||
|
||||
@@ -310,7 +358,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(
|
||||
self.build_edit_collection_params(),
|
||||
));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -7,8 +8,9 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::collections::edit_collection_handler::EditCollectionHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::collection;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::MinimumAvailability;
|
||||
use crate::models::radarr_models::{Collection, EditCollectionParams, MinimumAvailability};
|
||||
use crate::models::servarr_data::radarr::modals::EditCollectionModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS,
|
||||
@@ -519,7 +521,34 @@ mod tests {
|
||||
#[test]
|
||||
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||
let mut edit_collection_modal = EditCollectionModal {
|
||||
path: "/nfs/Test Path".into(),
|
||||
monitored: Some(false),
|
||||
search_on_add: Some(false),
|
||||
..EditCollectionModal::default()
|
||||
};
|
||||
edit_collection_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_collection_modal
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.edit_collection_modal = Some(edit_collection_modal);
|
||||
app.data.radarr_data.collections.set_items(vec![Collection {
|
||||
monitored: false,
|
||||
search_on_add: false,
|
||||
..collection()
|
||||
}]);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
let expected_edit_collection_params = EditCollectionParams {
|
||||
collection_id: 123,
|
||||
monitored: Some(false),
|
||||
minimum_availability: Some(MinimumAvailability::Announced),
|
||||
quality_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
search_on_add: Some(false),
|
||||
};
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
@@ -545,9 +574,10 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditCollection(None))
|
||||
Some(RadarrEvent::EditCollection(expected_edit_collection_params))
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(app.data.radarr_data.edit_collection_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -919,7 +949,34 @@ mod tests {
|
||||
#[test]
|
||||
fn test_edit_collection_confirm_prompt_prompt_confirmation_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||
let mut edit_collection_modal = EditCollectionModal {
|
||||
path: "/nfs/Test Path".into(),
|
||||
monitored: Some(false),
|
||||
search_on_add: Some(false),
|
||||
..EditCollectionModal::default()
|
||||
};
|
||||
edit_collection_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_collection_modal
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.edit_collection_modal = Some(edit_collection_modal);
|
||||
app.data.radarr_data.collections.set_items(vec![Collection {
|
||||
monitored: false,
|
||||
search_on_add: false,
|
||||
..collection()
|
||||
}]);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
let expected_edit_collection_params = EditCollectionParams {
|
||||
collection_id: 123,
|
||||
monitored: Some(false),
|
||||
minimum_availability: Some(MinimumAvailability::Announced),
|
||||
quality_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
search_on_add: Some(false),
|
||||
};
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||
app.data.radarr_data.selected_block =
|
||||
@@ -944,9 +1001,10 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditCollection(None))
|
||||
Some(RadarrEvent::EditCollection(expected_edit_collection_params))
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(app.data.radarr_data.edit_collection_modal.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -961,6 +1019,50 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_collection_params() {
|
||||
let mut app = App::default();
|
||||
let mut edit_collection_modal = EditCollectionModal {
|
||||
path: "/nfs/Test Path".into(),
|
||||
monitored: Some(false),
|
||||
search_on_add: Some(false),
|
||||
..EditCollectionModal::default()
|
||||
};
|
||||
edit_collection_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_collection_modal
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.edit_collection_modal = Some(edit_collection_modal);
|
||||
app.data.radarr_data.collections.set_items(vec![Collection {
|
||||
monitored: false,
|
||||
search_on_add: false,
|
||||
..collection()
|
||||
}]);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
let expected_edit_collection_params = EditCollectionParams {
|
||||
collection_id: 123,
|
||||
monitored: Some(false),
|
||||
minimum_availability: Some(MinimumAvailability::Announced),
|
||||
quality_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
search_on_add: Some(false),
|
||||
};
|
||||
|
||||
let edit_collection_params = EditCollectionHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::EditCollectionPrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_collection_params();
|
||||
|
||||
assert_eq!(edit_collection_params, expected_edit_collection_params);
|
||||
assert!(app.data.radarr_data.edit_collection_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_collection_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::download_record;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::DownloadRecord;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
|
||||
@@ -137,7 +139,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
ActiveRadarrBlock::DeleteDownloadPrompt,
|
||||
RadarrEvent::DeleteDownload(None)
|
||||
RadarrEvent::DeleteDownload(1)
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
@@ -154,7 +156,7 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.downloads
|
||||
.set_items(vec![DownloadRecord::default()]);
|
||||
.set_items(vec![download_record()]);
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(base_route.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
@@ -336,7 +338,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
ActiveRadarrBlock::DeleteDownloadPrompt,
|
||||
RadarrEvent::DeleteDownload(None)
|
||||
RadarrEvent::DeleteDownload(1)
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
@@ -353,7 +355,7 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.downloads
|
||||
.set_items(vec![DownloadRecord::default()]);
|
||||
.set_items(vec![download_record()]);
|
||||
app.push_navigation_stack(base_route.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
|
||||
@@ -385,6 +387,26 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_download_id() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.downloads
|
||||
.set_items(vec![download_record()]);
|
||||
|
||||
let download_id = DownloadsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::Downloads,
|
||||
None,
|
||||
)
|
||||
.extract_download_id();
|
||||
|
||||
assert_eq!(download_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_downloads_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -27,6 +27,10 @@ impl<'a, 'b> DownloadsHandler<'a, 'b> {
|
||||
self.app.data.radarr_data.downloads,
|
||||
DownloadRecord
|
||||
);
|
||||
|
||||
fn extract_download_id(&self) -> i64 {
|
||||
self.app.data.radarr_data.downloads.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a, 'b> {
|
||||
@@ -95,7 +99,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
||||
match self.active_radarr_block {
|
||||
ActiveRadarrBlock::DeleteDownloadPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteDownload(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteDownload(self.extract_download_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -138,7 +143,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
||||
ActiveRadarrBlock::DeleteDownloadPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteDownload(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteDownload(self.extract_download_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
||||
use crate::models::servarr_models::EditIndexerParams;
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
||||
|
||||
@@ -17,6 +19,61 @@ pub(super) struct EditIndexerHandler<'a, 'b> {
|
||||
_context: Option<ActiveRadarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> EditIndexerHandler<'a, 'b> {
|
||||
fn build_edit_indexer_params(&mut self) -> EditIndexerParams {
|
||||
let indexer_id = self.app.data.radarr_data.indexers.current_selection().id;
|
||||
let tags = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.edit_indexer_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
|
||||
let params = {
|
||||
let EditIndexerModal {
|
||||
name,
|
||||
enable_rss,
|
||||
enable_automatic_search,
|
||||
enable_interactive_search,
|
||||
url,
|
||||
api_key,
|
||||
seed_ratio,
|
||||
priority,
|
||||
..
|
||||
} = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.edit_indexer_modal
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
EditIndexerParams {
|
||||
indexer_id,
|
||||
name: Some(name.text.clone()),
|
||||
enable_rss: Some(enable_rss.unwrap_or_default()),
|
||||
enable_automatic_search: Some(enable_automatic_search.unwrap_or_default()),
|
||||
enable_interactive_search: Some(enable_interactive_search.unwrap_or_default()),
|
||||
url: Some(url.text.clone()),
|
||||
api_key: Some(api_key.text.clone()),
|
||||
seed_ratio: Some(seed_ratio.text.clone()),
|
||||
tags: None,
|
||||
tag_input_string: Some(tags),
|
||||
priority: Some(*priority),
|
||||
clear_tags: false,
|
||||
}
|
||||
};
|
||||
|
||||
self.app.data.radarr_data.edit_indexer_modal = None;
|
||||
|
||||
params
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
||||
@@ -297,12 +354,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
||||
let selected_block = self.app.data.radarr_data.selected_block.get_active_block();
|
||||
match selected_block {
|
||||
ActiveRadarrBlock::EditIndexerConfirmPrompt => {
|
||||
let radarr_data = &mut self.app.data.radarr_data;
|
||||
if radarr_data.prompt_confirm {
|
||||
radarr_data.prompt_confirm_action = Some(RadarrEvent::EditIndexer(None));
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::EditIndexer(self.build_edit_indexer_params()));
|
||||
self.app.should_refresh = true;
|
||||
} else {
|
||||
radarr_data.edit_indexer_modal = None;
|
||||
self.app.data.radarr_data.edit_indexer_modal = None;
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -464,7 +521,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditIndexer(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::EditIndexer(self.build_edit_indexer_params()));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -4,9 +4,12 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
||||
use crate::models::servarr_models::EditIndexerParams;
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
@@ -896,7 +899,32 @@ mod tests {
|
||||
.radarr_data
|
||||
.selected_block
|
||||
.set_index(0, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||
let edit_indexer_modal = EditIndexerModal {
|
||||
name: "Test Update".into(),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: "https://localhost:9696/1/".into(),
|
||||
api_key: "test1234".into(),
|
||||
seed_ratio: "1.3".into(),
|
||||
tags: "usenet, testing".into(),
|
||||
priority: 25,
|
||||
};
|
||||
app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||
let expected_edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
name: Some("Test Update".to_owned()),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: Some("https://localhost:9696/1/".to_owned()),
|
||||
api_key: Some("test1234".to_owned()),
|
||||
seed_ratio: Some("1.3".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
priority: Some(25),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
|
||||
EditIndexerHandler::with(
|
||||
@@ -908,11 +936,11 @@ mod tests {
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||
assert!(app.data.radarr_data.edit_indexer_modal.is_some());
|
||||
assert!(app.data.radarr_data.edit_indexer_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditIndexer(None))
|
||||
Some(RadarrEvent::EditIndexer(expected_edit_indexer_params))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1408,7 +1436,7 @@ mod tests {
|
||||
use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS;
|
||||
use crate::models::BlockSelectionState;
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1709,7 +1737,32 @@ mod tests {
|
||||
.radarr_data
|
||||
.selected_block
|
||||
.set_index(0, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||
let edit_indexer_modal = EditIndexerModal {
|
||||
name: "Test Update".into(),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: "https://localhost:9696/1/".into(),
|
||||
api_key: "test1234".into(),
|
||||
seed_ratio: "1.3".into(),
|
||||
tags: "usenet, testing".into(),
|
||||
priority: 25,
|
||||
};
|
||||
app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||
let expected_edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
name: Some("Test Update".to_owned()),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: Some("https://localhost:9696/1/".to_owned()),
|
||||
api_key: Some("test1234".to_owned()),
|
||||
seed_ratio: Some("1.3".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
priority: Some(25),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
EditIndexerHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
@@ -1720,11 +1773,11 @@ mod tests {
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||
assert!(app.data.radarr_data.edit_indexer_modal.is_some());
|
||||
assert!(app.data.radarr_data.edit_indexer_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditIndexer(None))
|
||||
Some(RadarrEvent::EditIndexer(expected_edit_indexer_params))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1740,6 +1793,48 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_indexer_params() {
|
||||
let mut app = App::default();
|
||||
let edit_indexer_modal = EditIndexerModal {
|
||||
name: "Test Update".into(),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: "https://localhost:9696/1/".into(),
|
||||
api_key: "test1234".into(),
|
||||
seed_ratio: "1.3".into(),
|
||||
tags: "usenet, testing".into(),
|
||||
priority: 25,
|
||||
};
|
||||
app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||
let expected_edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
name: Some("Test Update".to_owned()),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: Some("https://localhost:9696/1/".to_owned()),
|
||||
api_key: Some("test1234".to_owned()),
|
||||
seed_ratio: Some("1.3".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
priority: Some(25),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
let edit_indexer_params = EditIndexerHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::EditIndexerPrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_indexer_params();
|
||||
|
||||
assert_eq!(edit_indexer_params, expected_edit_indexer_params);
|
||||
assert!(app.data.radarr_data.edit_indexer_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_indexer_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::IndexerSettings;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
|
||||
};
|
||||
@@ -19,6 +20,14 @@ pub(super) struct IndexerSettingsHandler<'a, 'b> {
|
||||
_context: Option<ActiveRadarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> IndexerSettingsHandler<'a, 'b> {
|
||||
fn build_edit_indexer_settings_body(&mut self) -> IndexerSettings {
|
||||
let indexer_settings = self.app.data.radarr_data.indexer_settings.clone().unwrap();
|
||||
self.app.data.radarr_data.indexer_settings = None;
|
||||
indexer_settings
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
||||
@@ -166,12 +175,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
||||
ActiveRadarrBlock::AllIndexerSettingsPrompt => {
|
||||
match self.app.data.radarr_data.selected_block.get_active_block() {
|
||||
ActiveRadarrBlock::IndexerSettingsConfirmPrompt => {
|
||||
let radarr_data = &mut self.app.data.radarr_data;
|
||||
if radarr_data.prompt_confirm {
|
||||
radarr_data.prompt_confirm_action = Some(RadarrEvent::EditAllIndexerSettings(None));
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(
|
||||
RadarrEvent::EditAllIndexerSettings(self.build_edit_indexer_settings_body()),
|
||||
);
|
||||
self.app.should_refresh = true;
|
||||
} else {
|
||||
radarr_data.indexer_settings = None;
|
||||
self.app.data.radarr_data.indexer_settings = None;
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -258,8 +268,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::EditAllIndexerSettings(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(
|
||||
RadarrEvent::EditAllIndexerSettings(self.build_edit_indexer_settings_body()),
|
||||
);
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer_settings;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::IndexerSettings;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
@@ -472,7 +474,7 @@ mod tests {
|
||||
.radarr_data
|
||||
.selected_block
|
||||
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
|
||||
IndexerSettingsHandler::with(
|
||||
@@ -486,9 +488,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditAllIndexerSettings(None))
|
||||
Some(RadarrEvent::EditAllIndexerSettings(indexer_settings()))
|
||||
);
|
||||
assert!(app.data.radarr_data.indexer_settings.is_some());
|
||||
assert!(app.data.radarr_data.indexer_settings.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
|
||||
@@ -858,7 +860,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_key_char {
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
|
||||
use crate::{
|
||||
models::{
|
||||
@@ -937,7 +939,7 @@ mod tests {
|
||||
.radarr_data
|
||||
.selected_block
|
||||
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
||||
|
||||
IndexerSettingsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
@@ -950,9 +952,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditAllIndexerSettings(None))
|
||||
Some(RadarrEvent::EditAllIndexerSettings(indexer_settings()))
|
||||
);
|
||||
assert!(app.data.radarr_data.indexer_settings.is_some());
|
||||
assert!(app.data.radarr_data.indexer_settings.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
}
|
||||
@@ -968,6 +970,23 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_indexer_settings_body() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
||||
|
||||
let body = IndexerSettingsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_indexer_settings_body();
|
||||
|
||||
assert_eq!(body, indexer_settings());
|
||||
assert!(app.data.radarr_data.indexer_settings.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_indexer_settings_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -7,6 +8,7 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::indexers::IndexersHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ActiveRadarrBlock, EDIT_INDEXER_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS,
|
||||
@@ -123,17 +125,17 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_submit {
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
RadarrData, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS,
|
||||
};
|
||||
use crate::models::servarr_models::{Indexer, IndexerField};
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::{Number, Value};
|
||||
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
|
||||
use super::*;
|
||||
|
||||
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
|
||||
@@ -239,11 +241,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_delete_indexer_prompt_confirm_submit() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.indexers
|
||||
.set_items(vec![Indexer::default()]);
|
||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
||||
@@ -259,7 +257,7 @@ mod tests {
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::DeleteIndexer(None))
|
||||
Some(RadarrEvent::DeleteIndexer(1))
|
||||
);
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||
}
|
||||
@@ -348,13 +346,13 @@ mod tests {
|
||||
mod test_handle_key_char {
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer;
|
||||
use crate::{
|
||||
models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS,
|
||||
network::radarr_network::RadarrEvent,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_refresh_indexers_key() {
|
||||
let mut app = App::default();
|
||||
@@ -542,11 +540,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_delete_indexer_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.indexers
|
||||
.set_items(vec![Indexer::default()]);
|
||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
||||
|
||||
@@ -561,7 +555,7 @@ mod tests {
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::DeleteIndexer(None))
|
||||
Some(RadarrEvent::DeleteIndexer(1))
|
||||
);
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||
}
|
||||
@@ -639,6 +633,22 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_indexer_id() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||
|
||||
let indexer_id = IndexersHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::Indexers,
|
||||
None,
|
||||
)
|
||||
.extract_indexer_id();
|
||||
|
||||
assert_eq!(indexer_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_indexers_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -33,6 +33,10 @@ pub(super) struct IndexersHandler<'a, 'b> {
|
||||
|
||||
impl<'a, 'b> IndexersHandler<'a, 'b> {
|
||||
handle_table_events!(self, indexers, self.app.data.radarr_data.indexers, Indexer);
|
||||
|
||||
fn extract_indexer_id(&self) -> i64 {
|
||||
self.app.data.radarr_data.indexers.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a, 'b> {
|
||||
@@ -115,9 +119,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
||||
fn handle_submit(&mut self) {
|
||||
match self.active_radarr_block {
|
||||
ActiveRadarrBlock::DeleteIndexerPrompt => {
|
||||
let indexer_id = self.extract_indexer_id();
|
||||
let radarr_data = &mut self.app.data.radarr_data;
|
||||
if radarr_data.prompt_confirm {
|
||||
radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteIndexer(None));
|
||||
radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteIndexer(indexer_id));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -189,7 +194,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
||||
ActiveRadarrBlock::DeleteIndexerPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteIndexer(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::handlers::table_handler::TableHandlingConfig;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::AddMovieSearchResult;
|
||||
use crate::models::radarr_models::{
|
||||
AddMovieBody, AddMovieOptions, AddMovieSearchResult, CollectionMovie,
|
||||
};
|
||||
use crate::models::servarr_data::radarr::modals::AddMovieModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ActiveRadarrBlock, ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS,
|
||||
};
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::models::{BlockSelectionState, Scrollable};
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
|
||||
@@ -30,9 +34,95 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
||||
.radarr_data
|
||||
.add_searched_movies
|
||||
.as_mut()
|
||||
.unwrap(),
|
||||
.unwrap_or(&mut StatefulTable::default()),
|
||||
AddMovieSearchResult
|
||||
);
|
||||
|
||||
fn build_add_movie_body(&mut self) -> AddMovieBody {
|
||||
let tags = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.add_movie_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
let AddMovieModal {
|
||||
root_folder_list,
|
||||
monitor_list,
|
||||
minimum_availability_list,
|
||||
quality_profile_list,
|
||||
..
|
||||
} = self.app.data.radarr_data.add_movie_modal.as_ref().unwrap();
|
||||
let (tmdb_id, title) = if let Some(context) = self.context {
|
||||
if context == ActiveRadarrBlock::CollectionDetails {
|
||||
let CollectionMovie { tmdb_id, title, .. } = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.collection_movies
|
||||
.current_selection()
|
||||
.clone();
|
||||
(tmdb_id, title.text)
|
||||
} else {
|
||||
let AddMovieSearchResult { tmdb_id, title, .. } = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.add_searched_movies
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.current_selection()
|
||||
.clone();
|
||||
(tmdb_id, title.text)
|
||||
}
|
||||
} else {
|
||||
let AddMovieSearchResult { tmdb_id, title, .. } = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.add_searched_movies
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.current_selection()
|
||||
.clone();
|
||||
(tmdb_id, title.text)
|
||||
};
|
||||
let quality_profile = quality_profile_list.current_selection();
|
||||
let quality_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.quality_profile_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == quality_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let path = root_folder_list.current_selection().path.clone();
|
||||
let monitor = monitor_list.current_selection().to_string();
|
||||
let minimum_availability = minimum_availability_list.current_selection().to_string();
|
||||
|
||||
self.app.data.radarr_data.add_movie_modal = None;
|
||||
|
||||
AddMovieBody {
|
||||
tmdb_id,
|
||||
title,
|
||||
root_folder_path: path,
|
||||
minimum_availability,
|
||||
monitored: true,
|
||||
quality_profile_id,
|
||||
tags: Vec::new(),
|
||||
tag_input_string: Some(tags),
|
||||
add_options: AddMovieOptions {
|
||||
monitor,
|
||||
search_for_movie: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, 'b> {
|
||||
@@ -361,7 +451,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
||||
match self.app.data.radarr_data.selected_block.get_active_block() {
|
||||
ActiveRadarrBlock::AddMovieConfirmPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::AddMovie(self.build_add_movie_body()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -461,7 +552,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::AddMovie(self.build_add_movie_body()));
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::add_movie_search_result;
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use rstest::rstest;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::library::add_movie_handler::AddMovieHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::add_movie_body;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::collection_movie;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::{AddMovieSearchResult, MinimumAvailability, MovieMonitor};
|
||||
use crate::models::servarr_data::radarr::modals::AddMovieModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS};
|
||||
use crate::models::servarr_models::RootFolder;
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use bimap::BiMap;
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -758,6 +765,9 @@ mod tests {
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::{
|
||||
add_movie_body, add_movie_search_result, collection_movie,
|
||||
};
|
||||
use crate::models::radarr_models::Movie;
|
||||
use crate::models::servarr_data::radarr::modals::AddMovieModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS;
|
||||
@@ -969,8 +979,10 @@ mod tests {
|
||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_movie_confirm_prompt_prompt_confirmation_submit() {
|
||||
#[rstest]
|
||||
fn test_add_movie_confirm_prompt_prompt_confirmation_submit(
|
||||
#[values(true, false)] movie_details_context: bool,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||
@@ -982,21 +994,67 @@ mod tests {
|
||||
.radarr_data
|
||||
.selected_block
|
||||
.set_index(0, ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||
let mut add_movie_modal = AddMovieModal {
|
||||
tags: "usenet, testing".into(),
|
||||
..AddMovieModal::default()
|
||||
};
|
||||
add_movie_modal.root_folder_list.set_items(vec![
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
RootFolder {
|
||||
id: 2,
|
||||
path: "/nfs2".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 21990232555520,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
]);
|
||||
add_movie_modal.root_folder_list.state.select(Some(1));
|
||||
add_movie_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["HD - 1080p".to_owned()]);
|
||||
add_movie_modal
|
||||
.monitor_list
|
||||
.set_items(Vec::from_iter(MovieMonitor::iter()));
|
||||
add_movie_modal
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.add_movie_modal = Some(add_movie_modal);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||
let context = if movie_details_context {
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.collection_movies
|
||||
.set_items(vec![collection_movie()]);
|
||||
Some(ActiveRadarrBlock::CollectionDetails)
|
||||
} else {
|
||||
let mut add_searched_movies = StatefulTable::default();
|
||||
add_searched_movies.set_items(vec![add_movie_search_result()]);
|
||||
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
||||
None
|
||||
};
|
||||
|
||||
AddMovieHandler::with(
|
||||
SUBMIT_KEY,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::AddMoviePrompt,
|
||||
None,
|
||||
context,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::AddMovie(None))
|
||||
Some(RadarrEvent::AddMovie(add_movie_body()))
|
||||
);
|
||||
assert!(app.data.radarr_data.add_movie_modal.is_some());
|
||||
assert!(app.data.radarr_data.add_movie_modal.is_none());
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
@@ -1266,10 +1324,18 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_key_char {
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
handlers::radarr_handlers::radarr_handler_test_utils::utils::{
|
||||
add_movie_body, add_movie_search_result, collection_movie,
|
||||
},
|
||||
models::{
|
||||
servarr_data::radarr::{modals::AddMovieModal, radarr_data::ADD_MOVIE_SELECTION_BLOCKS},
|
||||
stateful_table::StatefulTable,
|
||||
BlockSelectionState,
|
||||
},
|
||||
network::radarr_network::RadarrEvent,
|
||||
@@ -1368,8 +1434,10 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_movie_confirm_prompt_prompt_confirmation_confirm() {
|
||||
#[rstest]
|
||||
fn test_add_movie_confirm_prompt_prompt_confirmation_confirm(
|
||||
#[values(true, false)] movie_details_context: bool,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||
@@ -1380,21 +1448,67 @@ mod tests {
|
||||
.radarr_data
|
||||
.selected_block
|
||||
.set_index(0, ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||
let mut add_movie_modal = AddMovieModal {
|
||||
tags: "usenet, testing".into(),
|
||||
..AddMovieModal::default()
|
||||
};
|
||||
add_movie_modal.root_folder_list.set_items(vec![
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
RootFolder {
|
||||
id: 2,
|
||||
path: "/nfs2".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 21990232555520,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
]);
|
||||
add_movie_modal.root_folder_list.state.select(Some(1));
|
||||
add_movie_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["HD - 1080p".to_owned()]);
|
||||
add_movie_modal
|
||||
.monitor_list
|
||||
.set_items(Vec::from_iter(MovieMonitor::iter()));
|
||||
add_movie_modal
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.add_movie_modal = Some(add_movie_modal);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||
let context = if movie_details_context {
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.collection_movies
|
||||
.set_items(vec![collection_movie()]);
|
||||
Some(ActiveRadarrBlock::CollectionDetails)
|
||||
} else {
|
||||
let mut add_searched_movies = StatefulTable::default();
|
||||
add_searched_movies.set_items(vec![add_movie_search_result()]);
|
||||
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
||||
None
|
||||
};
|
||||
|
||||
AddMovieHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::AddMoviePrompt,
|
||||
None,
|
||||
context,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::AddMovie(None))
|
||||
Some(RadarrEvent::AddMovie(add_movie_body()))
|
||||
);
|
||||
assert!(app.data.radarr_data.add_movie_modal.is_some());
|
||||
assert!(app.data.radarr_data.add_movie_modal.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1409,6 +1523,80 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_movie_search_no_panic_on_none_search_result() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.add_searched_movies = None;
|
||||
|
||||
AddMovieHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::AddMovieSearchResults,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_build_add_movie_body(#[values(true, false)] movie_details_context: bool) {
|
||||
let mut app = App::default();
|
||||
let mut add_movie_modal = AddMovieModal {
|
||||
tags: "usenet, testing".into(),
|
||||
..AddMovieModal::default()
|
||||
};
|
||||
add_movie_modal.root_folder_list.set_items(vec![
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
RootFolder {
|
||||
id: 2,
|
||||
path: "/nfs2".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 21990232555520,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
]);
|
||||
add_movie_modal.root_folder_list.state.select(Some(1));
|
||||
add_movie_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["HD - 1080p".to_owned()]);
|
||||
add_movie_modal
|
||||
.monitor_list
|
||||
.set_items(Vec::from_iter(MovieMonitor::iter()));
|
||||
add_movie_modal
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.add_movie_modal = Some(add_movie_modal);
|
||||
app.data.radarr_data.quality_profile_map = BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||
let context = if movie_details_context {
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.collection_movies
|
||||
.set_items(vec![collection_movie()]);
|
||||
Some(ActiveRadarrBlock::CollectionDetails)
|
||||
} else {
|
||||
let mut add_searched_movies = StatefulTable::default();
|
||||
add_searched_movies.set_items(vec![add_movie_search_result()]);
|
||||
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
||||
None
|
||||
};
|
||||
|
||||
let actual_add_movie_body = AddMovieHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::AddMoviePrompt,
|
||||
context,
|
||||
)
|
||||
.build_add_movie_body();
|
||||
|
||||
assert_eq!(actual_add_movie_body, add_movie_body());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_movie_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::DeleteMovieParams;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
|
||||
@@ -16,6 +17,21 @@ pub(super) struct DeleteMovieHandler<'a, 'b> {
|
||||
_context: Option<ActiveRadarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeleteMovieHandler<'a, 'b> {
|
||||
fn build_delete_movie_params(&mut self) -> DeleteMovieParams {
|
||||
let id = self.app.data.radarr_data.movies.current_selection().id;
|
||||
let delete_movie_files = self.app.data.radarr_data.delete_movie_files;
|
||||
let add_list_exclusion = self.app.data.radarr_data.add_list_exclusion;
|
||||
self.app.data.radarr_data.reset_delete_movie_preferences();
|
||||
|
||||
DeleteMovieParams {
|
||||
id,
|
||||
delete_movie_files,
|
||||
add_list_exclusion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||
DELETE_MOVIE_BLOCKS.contains(&active_block)
|
||||
@@ -72,7 +88,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
|
||||
match self.app.data.radarr_data.selected_block.get_active_block() {
|
||||
ActiveRadarrBlock::DeleteMovieConfirmPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteMovie(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteMovie(self.build_delete_movie_params()));
|
||||
self.app.should_refresh = true;
|
||||
} else {
|
||||
self.app.data.radarr_data.reset_delete_movie_preferences();
|
||||
@@ -108,7 +125,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteMovie(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteMovie(self.build_delete_movie_params()));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::library::delete_movie_handler::DeleteMovieHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::DeleteMovieParams;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
@@ -119,8 +122,14 @@ mod tests {
|
||||
#[test]
|
||||
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit() {
|
||||
let mut app = App::default();
|
||||
let expected_delete_movie_params = DeleteMovieParams {
|
||||
id: 1,
|
||||
delete_movie_files: true,
|
||||
add_list_exclusion: true,
|
||||
};
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.data.radarr_data.delete_movie_files = true;
|
||||
app.data.radarr_data.add_list_exclusion = true;
|
||||
@@ -142,12 +151,12 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::DeleteMovie(None))
|
||||
Some(RadarrEvent::DeleteMovie(expected_delete_movie_params))
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert!(app.data.radarr_data.delete_movie_files);
|
||||
assert!(app.data.radarr_data.add_list_exclusion);
|
||||
assert!(!app.data.radarr_data.delete_movie_files);
|
||||
assert!(!app.data.radarr_data.add_list_exclusion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -212,6 +221,7 @@ mod tests {
|
||||
|
||||
mod test_handle_esc {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
||||
@@ -248,14 +258,21 @@ mod tests {
|
||||
},
|
||||
network::radarr_network::RadarrEvent,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_delete_movie_confirm_prompt_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
let expected_delete_movie_params = DeleteMovieParams {
|
||||
id: 1,
|
||||
delete_movie_files: true,
|
||||
add_list_exclusion: true,
|
||||
};
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
app.data.radarr_data.delete_movie_files = true;
|
||||
app.data.radarr_data.add_list_exclusion = true;
|
||||
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
||||
@@ -276,12 +293,12 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::DeleteMovie(None))
|
||||
Some(RadarrEvent::DeleteMovie(expected_delete_movie_params))
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert!(app.data.radarr_data.delete_movie_files);
|
||||
assert!(app.data.radarr_data.add_list_exclusion);
|
||||
assert!(!app.data.radarr_data.delete_movie_files);
|
||||
assert!(!app.data.radarr_data.add_list_exclusion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +313,31 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_delete_movie_params() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
app.data.radarr_data.delete_movie_files = true;
|
||||
app.data.radarr_data.add_list_exclusion = true;
|
||||
let expected_delete_movie_params = DeleteMovieParams {
|
||||
id: 1,
|
||||
delete_movie_files: true,
|
||||
add_list_exclusion: true,
|
||||
};
|
||||
|
||||
let delete_movie_params = DeleteMovieHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||
None,
|
||||
)
|
||||
.build_delete_movie_params();
|
||||
|
||||
assert_eq!(delete_movie_params, expected_delete_movie_params);
|
||||
assert!(!app.data.radarr_data.delete_movie_files);
|
||||
assert!(!app.data.radarr_data.add_list_exclusion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_movie_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -2,6 +2,8 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::EditMovieParams;
|
||||
use crate::models::servarr_data::radarr::modals::EditMovieModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
|
||||
use crate::models::Scrollable;
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
@@ -18,6 +20,57 @@ pub(super) struct EditMovieHandler<'a, 'b> {
|
||||
context: Option<ActiveRadarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> EditMovieHandler<'a, 'b> {
|
||||
fn build_edit_movie_params(&mut self) -> EditMovieParams {
|
||||
let movie_id = self.app.data.radarr_data.movies.current_selection().id;
|
||||
let tags = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.edit_movie_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
let params = {
|
||||
let EditMovieModal {
|
||||
monitored,
|
||||
path,
|
||||
minimum_availability_list,
|
||||
quality_profile_list,
|
||||
..
|
||||
} = self.app.data.radarr_data.edit_movie_modal.as_ref().unwrap();
|
||||
let quality_profile = quality_profile_list.current_selection();
|
||||
let quality_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.quality_profile_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == quality_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
EditMovieParams {
|
||||
movie_id,
|
||||
monitored: *monitored,
|
||||
minimum_availability: Some(*minimum_availability_list.current_selection()),
|
||||
quality_profile_id: Some(quality_profile_id),
|
||||
root_folder_path: Some(path.text.clone()),
|
||||
tags: None,
|
||||
tag_input_string: Some(tags),
|
||||
clear_tags: false,
|
||||
}
|
||||
};
|
||||
|
||||
self.app.data.radarr_data.edit_movie_modal = None;
|
||||
|
||||
params
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||
EDIT_MOVIE_BLOCKS.contains(&active_block)
|
||||
@@ -222,7 +275,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
||||
match self.app.data.radarr_data.selected_block.get_active_block() {
|
||||
ActiveRadarrBlock::EditMovieConfirmPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditMovie(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::EditMovie(self.build_edit_movie_params()));
|
||||
self.app.should_refresh = true;
|
||||
}
|
||||
|
||||
@@ -333,7 +387,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditMovie(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::EditMovie(self.build_edit_movie_params()));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -7,8 +8,9 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::library::edit_movie_handler::EditMovieHandler;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::MinimumAvailability;
|
||||
use crate::models::radarr_models::{EditMovieParams, MinimumAvailability, Movie};
|
||||
use crate::models::servarr_data::radarr::modals::EditMovieModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
|
||||
|
||||
@@ -641,7 +643,34 @@ mod tests {
|
||||
#[test]
|
||||
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||
let mut edit_movie = EditMovieModal {
|
||||
tags: "usenet, testing".to_owned().into(),
|
||||
path: "/nfs/Test Path".to_owned().into(),
|
||||
monitored: Some(false),
|
||||
..EditMovieModal::default()
|
||||
};
|
||||
edit_movie
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_movie
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.edit_movie_modal = Some(edit_movie);
|
||||
app.data.radarr_data.movies.set_items(vec![Movie {
|
||||
monitored: false,
|
||||
..movie()
|
||||
}]);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
let expected_edit_movie_params = EditMovieParams {
|
||||
movie_id: 1,
|
||||
monitored: Some(false),
|
||||
minimum_availability: Some(MinimumAvailability::Announced),
|
||||
quality_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".into()),
|
||||
..EditMovieParams::default()
|
||||
};
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
@@ -663,9 +692,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditMovie(None))
|
||||
Some(RadarrEvent::EditMovie(expected_edit_movie_params))
|
||||
);
|
||||
assert!(app.data.radarr_data.edit_movie_modal.is_some());
|
||||
assert!(app.data.radarr_data.edit_movie_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
|
||||
@@ -1053,7 +1082,34 @@ mod tests {
|
||||
#[test]
|
||||
fn test_edit_movie_confirm_prompt_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||
let mut edit_movie = EditMovieModal {
|
||||
tags: "usenet, testing".to_owned().into(),
|
||||
path: "/nfs/Test Path".to_owned().into(),
|
||||
monitored: Some(false),
|
||||
..EditMovieModal::default()
|
||||
};
|
||||
edit_movie
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_movie
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.edit_movie_modal = Some(edit_movie);
|
||||
app.data.radarr_data.movies.set_items(vec![Movie {
|
||||
monitored: false,
|
||||
..movie()
|
||||
}]);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
let expected_edit_movie_params = EditMovieParams {
|
||||
movie_id: 1,
|
||||
monitored: Some(false),
|
||||
minimum_availability: Some(MinimumAvailability::Announced),
|
||||
quality_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".into()),
|
||||
..EditMovieParams::default()
|
||||
};
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||
@@ -1074,9 +1130,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::EditMovie(None))
|
||||
Some(RadarrEvent::EditMovie(expected_edit_movie_params))
|
||||
);
|
||||
assert!(app.data.radarr_data.edit_movie_modal.is_some());
|
||||
assert!(app.data.radarr_data.edit_movie_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
}
|
||||
@@ -1092,6 +1148,50 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_movie_params() {
|
||||
let mut app = App::default();
|
||||
let mut edit_movie = EditMovieModal {
|
||||
tags: "usenet, testing".to_owned().into(),
|
||||
path: "/nfs/Test Path".to_owned().into(),
|
||||
monitored: Some(false),
|
||||
..EditMovieModal::default()
|
||||
};
|
||||
edit_movie
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_movie
|
||||
.minimum_availability_list
|
||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||
app.data.radarr_data.edit_movie_modal = Some(edit_movie);
|
||||
app.data.radarr_data.movies.set_items(vec![Movie {
|
||||
monitored: false,
|
||||
..movie()
|
||||
}]);
|
||||
app.data.radarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
let expected_edit_movie_params = EditMovieParams {
|
||||
movie_id: 1,
|
||||
monitored: Some(false),
|
||||
minimum_availability: Some(MinimumAvailability::Announced),
|
||||
quality_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".into()),
|
||||
..EditMovieParams::default()
|
||||
};
|
||||
|
||||
let edit_movie_params = EditMovieHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::EditMoviePrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_movie_params();
|
||||
|
||||
assert_eq!(edit_movie_params, expected_edit_movie_params);
|
||||
assert!(app.data.radarr_data.edit_movie_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_movie_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -6,7 +6,9 @@ use crate::event::Key;
|
||||
use crate::handle_table_events;
|
||||
use crate::handlers::table_handler::TableHandlingConfig;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::{Credit, MovieHistoryItem, RadarrRelease};
|
||||
use crate::models::radarr_models::{
|
||||
Credit, MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody,
|
||||
};
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ActiveRadarrBlock, EDIT_MOVIE_SELECTION_BLOCKS, MOVIE_DETAILS_BLOCKS,
|
||||
};
|
||||
@@ -79,6 +81,35 @@ impl<'a, 'b> MovieDetailsHandler<'a, 'b> {
|
||||
.movie_crew,
|
||||
Credit
|
||||
);
|
||||
|
||||
fn build_radarr_release_download_body(&self) -> RadarrReleaseDownloadBody {
|
||||
let movie_id = self.app.data.radarr_data.movies.current_selection().id;
|
||||
let (guid, indexer_id) = {
|
||||
let RadarrRelease {
|
||||
guid, indexer_id, ..
|
||||
} = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.movie_details_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.movie_releases
|
||||
.current_selection();
|
||||
|
||||
(guid.clone(), *indexer_id)
|
||||
};
|
||||
|
||||
RadarrReleaseDownloadBody {
|
||||
guid,
|
||||
indexer_id,
|
||||
movie_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_movie_id(&self) -> i64 {
|
||||
self.app.data.radarr_data.movies.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<'a, 'b> {
|
||||
@@ -240,14 +271,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::TriggerAutomaticSearch(None));
|
||||
Some(RadarrEvent::TriggerAutomaticSearch(self.extract_movie_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAndScan(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::UpdateAndScan(self.extract_movie_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -259,8 +291,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
||||
}
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DownloadRelease(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(
|
||||
self.build_radarr_release_download_body(),
|
||||
));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -333,19 +366,22 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::TriggerAutomaticSearch(None));
|
||||
Some(RadarrEvent::TriggerAutomaticSearch(self.extract_movie_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAndScan(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::UpdateAndScan(self.extract_movie_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(
|
||||
self.build_radarr_release_download_body(),
|
||||
));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
mod tests {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use rstest::rstest;
|
||||
use serde_json::Number;
|
||||
use strum::IntoEnumIterator;
|
||||
@@ -13,9 +13,10 @@ mod tests {
|
||||
use crate::handlers::radarr_handlers::library::movie_details_handler::{
|
||||
releases_sorting_options, MovieDetailsHandler,
|
||||
};
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::{movie, release};
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::RadarrRelease;
|
||||
use crate::models::radarr_models::{Credit, MovieHistoryItem};
|
||||
use crate::models::radarr_models::{RadarrRelease, RadarrReleaseDownloadBody};
|
||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
|
||||
use crate::models::servarr_models::{Language, Quality, QualityWrapper};
|
||||
@@ -130,6 +131,7 @@ mod tests {
|
||||
|
||||
mod test_handle_home_end {
|
||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -359,25 +361,31 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
RadarrEvent::TriggerAutomaticSearch(None)
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
RadarrEvent::UpdateAndScan(None)
|
||||
RadarrEvent::TriggerAutomaticSearch(1)
|
||||
)]
|
||||
#[case(ActiveRadarrBlock::UpdateAndScanPrompt, RadarrEvent::UpdateAndScan(1))]
|
||||
#[case(
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||
RadarrEvent::DownloadRelease(None)
|
||||
RadarrEvent::DownloadRelease(RadarrReleaseDownloadBody {
|
||||
guid: "1234".to_owned(),
|
||||
indexer_id: 2,
|
||||
movie_id: 1,
|
||||
})
|
||||
)]
|
||||
fn test_movie_info_prompt_confirm_submit(
|
||||
#[case] prompt_block: ActiveRadarrBlock,
|
||||
#[case] expected_action: RadarrEvent,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||
let mut movie_details_modal = MovieDetailsModal {
|
||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||
..MovieDetailsModal::default()
|
||||
});
|
||||
};
|
||||
movie_details_modal
|
||||
.movie_releases
|
||||
.set_items(vec![release()]);
|
||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
@@ -771,25 +779,32 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
RadarrEvent::TriggerAutomaticSearch(None)
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
RadarrEvent::UpdateAndScan(None)
|
||||
RadarrEvent::TriggerAutomaticSearch(1)
|
||||
)]
|
||||
#[case(ActiveRadarrBlock::UpdateAndScanPrompt, RadarrEvent::UpdateAndScan(1))]
|
||||
#[case(
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||
RadarrEvent::DownloadRelease(None)
|
||||
RadarrEvent::DownloadRelease(RadarrReleaseDownloadBody {
|
||||
guid: "1234".to_owned(),
|
||||
indexer_id: 2,
|
||||
movie_id: 1,
|
||||
})
|
||||
)]
|
||||
fn test_movie_info_prompt_confirm(
|
||||
#[case] prompt_block: ActiveRadarrBlock,
|
||||
#[case] expected_action: RadarrEvent,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||
let mut movie_details_modal = MovieDetailsModal {
|
||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||
..MovieDetailsModal::default()
|
||||
});
|
||||
};
|
||||
movie_details_modal
|
||||
.movie_releases
|
||||
.set_items(vec![release()]);
|
||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
|
||||
@@ -813,6 +828,48 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_radarr_release_download_body() {
|
||||
let mut app = App::default();
|
||||
let mut movie_details_modal = MovieDetailsModal::default();
|
||||
movie_details_modal
|
||||
.movie_releases
|
||||
.set_items(vec![release()]);
|
||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
let expected_body = RadarrReleaseDownloadBody {
|
||||
guid: "1234".to_owned(),
|
||||
indexer_id: 2,
|
||||
movie_id: 1,
|
||||
};
|
||||
|
||||
let body = MovieDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||
None,
|
||||
)
|
||||
.build_radarr_release_download_body();
|
||||
|
||||
assert_eq!(body, expected_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_movie_id() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||
|
||||
let movie_id = MovieDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
None,
|
||||
)
|
||||
.extract_movie_id();
|
||||
|
||||
assert_eq!(movie_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_releases_sorting_options_source() {
|
||||
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering =
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod utils {
|
||||
pub(in crate::handlers::radarr_handlers) mod utils {
|
||||
use crate::models::radarr_models::{
|
||||
AddMovieBody, AddMovieOptions, AddMovieSearchResult, Collection, CollectionMovie,
|
||||
DownloadRecord, IndexerSettings, MediaInfo, MinimumAvailability, Movie, MovieCollection,
|
||||
MovieFile, RadarrRelease, Rating, RatingsList,
|
||||
};
|
||||
use crate::models::servarr_models::{
|
||||
Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder,
|
||||
};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use chrono::DateTime;
|
||||
use serde_json::{json, Number};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! test_edit_movie_key {
|
||||
($handler:ident, $block:expr, $context:expr) => {
|
||||
@@ -228,4 +240,245 @@ mod utils {
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn language() -> Language {
|
||||
Language {
|
||||
id: 1,
|
||||
name: "English".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genres() -> Vec<String> {
|
||||
vec!["cool".to_owned(), "family".to_owned(), "fun".to_owned()]
|
||||
}
|
||||
|
||||
pub fn rating() -> Rating {
|
||||
Rating {
|
||||
value: Number::from_f64(9.9).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ratings_list() -> RatingsList {
|
||||
RatingsList {
|
||||
imdb: Some(rating()),
|
||||
tmdb: Some(rating()),
|
||||
rotten_tomatoes: Some(rating()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn media_info() -> MediaInfo {
|
||||
MediaInfo {
|
||||
audio_bitrate: 0,
|
||||
audio_channels: Number::from_f64(7.1).unwrap(),
|
||||
audio_codec: Some("AAC".to_owned()),
|
||||
audio_languages: Some("eng".to_owned()),
|
||||
audio_stream_count: 1,
|
||||
video_bit_depth: 10,
|
||||
video_bitrate: 0,
|
||||
video_codec: "x265".to_owned(),
|
||||
video_fps: Number::from_f64(23.976).unwrap(),
|
||||
resolution: "1920x804".to_owned(),
|
||||
run_time: "2:00:00".to_owned(),
|
||||
scan_type: "Progressive".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn movie_file() -> MovieFile {
|
||||
MovieFile {
|
||||
relative_path: "Test.mkv".to_owned(),
|
||||
path: "/nfs/movies/Test.mkv".to_owned(),
|
||||
date_added: DateTime::from(DateTime::parse_from_rfc3339("2022-12-30T07:37:56Z").unwrap()),
|
||||
media_info: Some(media_info()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collection_movie() -> CollectionMovie {
|
||||
CollectionMovie {
|
||||
title: "Test".to_owned().into(),
|
||||
overview: "Collection blah blah blah".to_owned(),
|
||||
year: 2023,
|
||||
runtime: 120,
|
||||
tmdb_id: 1234,
|
||||
genres: genres(),
|
||||
ratings: ratings_list(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collection() -> Collection {
|
||||
Collection {
|
||||
id: 123,
|
||||
title: "Test Collection".to_owned().into(),
|
||||
root_folder_path: Some("/nfs/movies".to_owned()),
|
||||
search_on_add: true,
|
||||
monitored: true,
|
||||
minimum_availability: MinimumAvailability::Released,
|
||||
overview: Some("Collection blah blah blah".to_owned()),
|
||||
quality_profile_id: 2222,
|
||||
movies: Some(vec![collection_movie()]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn movie() -> Movie {
|
||||
Movie {
|
||||
id: 1,
|
||||
title: "Test".to_owned().into(),
|
||||
original_language: language(),
|
||||
size_on_disk: 3543348019,
|
||||
status: "Downloaded".to_owned(),
|
||||
overview: "Blah blah blah".to_owned(),
|
||||
path: "/nfs/movies".to_owned(),
|
||||
studio: "21st Century Alex".to_owned(),
|
||||
genres: genres(),
|
||||
year: 2023,
|
||||
monitored: true,
|
||||
has_file: true,
|
||||
runtime: 120,
|
||||
tmdb_id: 1234,
|
||||
quality_profile_id: 2222,
|
||||
minimum_availability: MinimumAvailability::Announced,
|
||||
certification: Some("R".to_owned()),
|
||||
tags: vec![Number::from(1)],
|
||||
ratings: ratings_list(),
|
||||
movie_file: Some(movie_file()),
|
||||
collection: Some(movie_collection()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn movie_collection() -> MovieCollection {
|
||||
MovieCollection {
|
||||
title: Some("Test Collection".to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rejections() -> Vec<String> {
|
||||
vec![
|
||||
"Unknown quality profile".to_owned(),
|
||||
"Release is already mapped".to_owned(),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn quality() -> Quality {
|
||||
Quality {
|
||||
name: "HD - 1080p".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quality_wrapper() -> QualityWrapper {
|
||||
QualityWrapper { quality: quality() }
|
||||
}
|
||||
|
||||
pub fn release() -> RadarrRelease {
|
||||
RadarrRelease {
|
||||
guid: "1234".to_owned(),
|
||||
protocol: "torrent".to_owned(),
|
||||
age: 1,
|
||||
title: HorizontallyScrollableText::from("Test Release"),
|
||||
indexer: "kickass torrents".to_owned(),
|
||||
indexer_id: 2,
|
||||
size: 1234,
|
||||
rejected: true,
|
||||
rejections: Some(rejections()),
|
||||
seeders: Some(Number::from(2)),
|
||||
leechers: Some(Number::from(1)),
|
||||
languages: Some(vec![language()]),
|
||||
quality: quality_wrapper(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_movie_search_result() -> AddMovieSearchResult {
|
||||
AddMovieSearchResult {
|
||||
tmdb_id: 1234,
|
||||
title: HorizontallyScrollableText::from("Test"),
|
||||
original_language: language(),
|
||||
status: "released".to_owned(),
|
||||
overview: "New movie blah blah blah".to_owned(),
|
||||
genres: genres(),
|
||||
year: 2023,
|
||||
runtime: 120,
|
||||
ratings: ratings_list(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn download_record() -> DownloadRecord {
|
||||
DownloadRecord {
|
||||
title: "Test Download Title".to_owned(),
|
||||
status: "downloading".to_owned(),
|
||||
id: 1,
|
||||
movie_id: 1,
|
||||
size: 3543348019,
|
||||
sizeleft: 1771674009,
|
||||
output_path: Some(HorizontallyScrollableText::from("/nfs/movies/Test")),
|
||||
indexer: "kickass torrents".to_owned(),
|
||||
download_client: "transmission".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_folder() -> RootFolder {
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indexer() -> Indexer {
|
||||
Indexer {
|
||||
enable_rss: true,
|
||||
enable_automatic_search: true,
|
||||
enable_interactive_search: true,
|
||||
supports_rss: true,
|
||||
supports_search: true,
|
||||
protocol: "torrent".to_owned(),
|
||||
priority: 25,
|
||||
download_client_id: 0,
|
||||
name: Some("Test Indexer".to_owned()),
|
||||
implementation_name: Some("Torznab".to_owned()),
|
||||
implementation: Some("Torznab".to_owned()),
|
||||
config_contract: Some("TorznabSettings".to_owned()),
|
||||
tags: vec![Number::from(1)],
|
||||
id: 1,
|
||||
fields: Some(vec![
|
||||
IndexerField {
|
||||
name: Some("baseUrl".to_owned()),
|
||||
value: Some(json!("https://test.com")),
|
||||
},
|
||||
IndexerField {
|
||||
name: Some("apiKey".to_owned()),
|
||||
value: Some(json!("")),
|
||||
},
|
||||
IndexerField {
|
||||
name: Some("seedCriteria.seedRatio".to_owned()),
|
||||
value: Some(json!("1.2")),
|
||||
},
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indexer_settings() -> IndexerSettings {
|
||||
IndexerSettings {
|
||||
rss_sync_interval: 60,
|
||||
allow_hardcoded_subs: true,
|
||||
id: 1,
|
||||
..IndexerSettings::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_movie_body() -> AddMovieBody {
|
||||
AddMovieBody {
|
||||
tmdb_id: 1234,
|
||||
title: "Test".to_owned(),
|
||||
root_folder_path: "/nfs2".to_owned(),
|
||||
minimum_availability: "announced".to_owned(),
|
||||
monitored: true,
|
||||
quality_profile_id: 2222,
|
||||
tags: Vec::new(),
|
||||
tag_input_string: Some("usenet, testing".into()),
|
||||
add_options: AddMovieOptions {
|
||||
monitor: "movieOnly".to_owned(),
|
||||
search_for_movie: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||
use crate::handlers::table_handler::TableHandlingConfig;
|
||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS};
|
||||
use crate::models::servarr_models::RootFolder;
|
||||
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys};
|
||||
@@ -28,6 +28,32 @@ impl<'a, 'b> RootFoldersHandler<'a, 'b> {
|
||||
self.app.data.radarr_data.root_folders,
|
||||
RootFolder
|
||||
);
|
||||
|
||||
fn build_add_root_folder_body(&mut self) -> AddRootFolderBody {
|
||||
let path = self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.edit_root_folder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.text
|
||||
.clone();
|
||||
|
||||
self.app.data.radarr_data.edit_root_folder = None;
|
||||
|
||||
AddRootFolderBody { path }
|
||||
}
|
||||
|
||||
fn extract_root_folder_id(&mut self) -> i64 {
|
||||
self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.root_folders
|
||||
.current_selection()
|
||||
.id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'a, 'b> {
|
||||
@@ -124,7 +150,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
||||
ActiveRadarrBlock::DeleteRootFolderPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteRootFolder(None));
|
||||
Some(RadarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -140,7 +166,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
||||
.text
|
||||
.is_empty() =>
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddRootFolder(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddRootFolder(
|
||||
self.build_add_root_folder_body(),
|
||||
));
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.should_ignore_quit_key = false;
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -192,7 +220,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::DeleteRootFolder(None));
|
||||
Some(RadarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::root_folder;
|
||||
use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS};
|
||||
use crate::models::servarr_models::RootFolder;
|
||||
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
|
||||
mod test_handle_home_end {
|
||||
@@ -250,6 +252,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_add_root_folder_prompt_confirm_submit() {
|
||||
let mut app = App::default();
|
||||
let expected_add_root_folder_body = AddRootFolderBody {
|
||||
path: "Test".to_owned(),
|
||||
};
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
@@ -273,7 +278,7 @@ mod tests {
|
||||
assert!(!app.should_ignore_quit_key);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::AddRootFolder(None))
|
||||
Some(RadarrEvent::AddRootFolder(expected_add_root_folder_body))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -314,7 +319,7 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.root_folders
|
||||
.set_items(vec![RootFolder::default()]);
|
||||
.set_items(vec![root_folder()]);
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteRootFolderPrompt.into());
|
||||
@@ -330,7 +335,7 @@ mod tests {
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::DeleteRootFolder(None))
|
||||
Some(RadarrEvent::DeleteRootFolder(1))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -604,7 +609,7 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.root_folders
|
||||
.set_items(vec![RootFolder::default()]);
|
||||
.set_items(vec![root_folder()]);
|
||||
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteRootFolderPrompt.into());
|
||||
|
||||
@@ -619,7 +624,7 @@ mod tests {
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::DeleteRootFolder(None))
|
||||
Some(RadarrEvent::DeleteRootFolder(1))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -639,6 +644,46 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_add_root_folder_body() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.edit_root_folder = Some("/nfs/test".into());
|
||||
let expected_add_root_folder_body = AddRootFolderBody {
|
||||
path: "/nfs/test".to_owned(),
|
||||
};
|
||||
|
||||
let actual_add_root_folder_body = RootFoldersHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::RootFolders,
|
||||
None,
|
||||
)
|
||||
.build_add_root_folder_body();
|
||||
|
||||
assert_eq!(actual_add_root_folder_body, expected_add_root_folder_body);
|
||||
assert!(app.data.radarr_data.edit_root_folder.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_root_folder_id() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.root_folders
|
||||
.set_items(vec![root_folder()]);
|
||||
|
||||
let root_folder_id = RootFoldersHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::RootFolders,
|
||||
None,
|
||||
)
|
||||
.extract_root_folder_id();
|
||||
|
||||
assert_eq!(root_folder_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root_folders_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::radarr_models::RadarrTaskName;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS};
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
use crate::models::Scrollable;
|
||||
@@ -18,6 +19,18 @@ pub(super) struct SystemDetailsHandler<'a, 'b> {
|
||||
_context: Option<ActiveRadarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> SystemDetailsHandler<'a, 'b> {
|
||||
fn extract_task_name(&self) -> RadarrTaskName {
|
||||
self
|
||||
.app
|
||||
.data
|
||||
.radarr_data
|
||||
.tasks
|
||||
.current_selection()
|
||||
.task_name
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveRadarrBlock) -> bool {
|
||||
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
|
||||
@@ -137,7 +150,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler
|
||||
}
|
||||
ActiveRadarrBlock::SystemTaskStartConfirmPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::StartTask(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::StartTask(self.extract_task_name()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -174,7 +188,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.radarr_data.prompt_confirm = true;
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::StartTask(None));
|
||||
self.app.data.radarr_data.prompt_confirm_action =
|
||||
Some(RadarrEvent::StartTask(self.extract_task_name()));
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
@@ -8,7 +8,7 @@ mod tests {
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::RadarrTask;
|
||||
use crate::models::radarr_models::{RadarrTask, RadarrTaskName};
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS,
|
||||
};
|
||||
@@ -16,6 +16,7 @@ mod tests {
|
||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||
@@ -236,6 +237,7 @@ mod tests {
|
||||
mod test_handle_home_end {
|
||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||
use crate::{extended_stateful_iterable_vec, test_iterable_home_and_end};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -676,6 +678,10 @@ mod tests {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.updates = ScrollableText::with_string("Test".to_owned());
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
app.data.radarr_data.tasks.set_items(vec![RadarrTask {
|
||||
task_name: RadarrTaskName::default(),
|
||||
..RadarrTask::default()
|
||||
}]);
|
||||
app.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::SystemTaskStartConfirmPrompt.into());
|
||||
|
||||
@@ -690,7 +696,7 @@ mod tests {
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::StartTask(None))
|
||||
Some(RadarrEvent::StartTask(RadarrTaskName::default()))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -831,6 +837,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_key_char {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
@@ -894,6 +901,10 @@ mod tests {
|
||||
fn test_system_tasks_start_task_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.updates = ScrollableText::with_string("Test".to_owned());
|
||||
app.data.radarr_data.tasks.set_items(vec![RadarrTask {
|
||||
task_name: RadarrTaskName::default(),
|
||||
..RadarrTask::default()
|
||||
}]);
|
||||
app.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into());
|
||||
app.push_navigation_stack(ActiveRadarrBlock::SystemTaskStartConfirmPrompt.into());
|
||||
|
||||
@@ -908,7 +919,7 @@ mod tests {
|
||||
assert!(app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.radarr_data.prompt_confirm_action,
|
||||
Some(RadarrEvent::StartTask(None))
|
||||
Some(RadarrEvent::StartTask(RadarrTaskName::default()))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -928,6 +939,25 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_task_name() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.tasks.set_items(vec![RadarrTask {
|
||||
task_name: RadarrTaskName::default(),
|
||||
..RadarrTask::default()
|
||||
}]);
|
||||
|
||||
let task_name = SystemDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveRadarrBlock::SystemTasks,
|
||||
None,
|
||||
)
|
||||
.extract_task_name();
|
||||
|
||||
assert_eq!(task_name, RadarrTaskName::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_details_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -161,7 +161,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveSonarrBlock::Blocklist,
|
||||
ActiveSonarrBlock::DeleteBlocklistItemPrompt,
|
||||
SonarrEvent::DeleteBlocklistItem(None)
|
||||
SonarrEvent::DeleteBlocklistItem(3)
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::Blocklist,
|
||||
@@ -361,7 +361,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveSonarrBlock::Blocklist,
|
||||
ActiveSonarrBlock::DeleteBlocklistItemPrompt,
|
||||
SonarrEvent::DeleteBlocklistItem(None)
|
||||
SonarrEvent::DeleteBlocklistItem(3)
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::Blocklist,
|
||||
@@ -513,6 +513,22 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_blocklist_item_id() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.blocklist.set_items(blocklist_vec());
|
||||
|
||||
let blocklist_item_id = BlocklistHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::Blocklist,
|
||||
None,
|
||||
)
|
||||
.extract_blocklist_item_id();
|
||||
|
||||
assert_eq!(blocklist_item_id, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blocklist_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -28,6 +28,10 @@ impl<'a, 'b> BlocklistHandler<'a, 'b> {
|
||||
self.app.data.sonarr_data.blocklist,
|
||||
BlocklistItem
|
||||
);
|
||||
|
||||
fn extract_blocklist_item_id(&self) -> i64 {
|
||||
self.app.data.sonarr_data.blocklist.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a, 'b> {
|
||||
@@ -98,8 +102,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
||||
match self.active_sonarr_block {
|
||||
ActiveSonarrBlock::DeleteBlocklistItemPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteBlocklistItem(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteBlocklistItem(
|
||||
self.extract_blocklist_item_id(),
|
||||
));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -151,8 +156,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
||||
ActiveSonarrBlock::DeleteBlocklistItemPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteBlocklistItem(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteBlocklistItem(
|
||||
self.extract_blocklist_item_id(),
|
||||
));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::downloads::DownloadsHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::download_record;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS};
|
||||
use crate::models::sonarr_models::DownloadRecord;
|
||||
@@ -138,7 +140,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveSonarrBlock::Downloads,
|
||||
ActiveSonarrBlock::DeleteDownloadPrompt,
|
||||
SonarrEvent::DeleteDownload(None)
|
||||
SonarrEvent::DeleteDownload(1)
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::Downloads,
|
||||
@@ -155,7 +157,7 @@ mod tests {
|
||||
.data
|
||||
.sonarr_data
|
||||
.downloads
|
||||
.set_items(vec![DownloadRecord::default()]);
|
||||
.set_items(vec![download_record()]);
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(base_route.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
@@ -338,7 +340,7 @@ mod tests {
|
||||
#[case(
|
||||
ActiveSonarrBlock::Downloads,
|
||||
ActiveSonarrBlock::DeleteDownloadPrompt,
|
||||
SonarrEvent::DeleteDownload(None)
|
||||
SonarrEvent::DeleteDownload(1)
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::Downloads,
|
||||
@@ -355,7 +357,7 @@ mod tests {
|
||||
.data
|
||||
.sonarr_data
|
||||
.downloads
|
||||
.set_items(vec![DownloadRecord::default()]);
|
||||
.set_items(vec![download_record()]);
|
||||
app.push_navigation_stack(base_route.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
|
||||
@@ -387,6 +389,26 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_download_id() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.downloads
|
||||
.set_items(vec![download_record()]);
|
||||
|
||||
let download_id = DownloadsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::Downloads,
|
||||
None,
|
||||
)
|
||||
.extract_download_id();
|
||||
|
||||
assert_eq!(download_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_downloads_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -27,6 +27,10 @@ impl<'a, 'b> DownloadsHandler<'a, 'b> {
|
||||
self.app.data.sonarr_data.downloads,
|
||||
DownloadRecord
|
||||
);
|
||||
|
||||
fn extract_download_id(&self) -> i64 {
|
||||
self.app.data.sonarr_data.downloads.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a, 'b> {
|
||||
@@ -95,7 +99,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a,
|
||||
match self.active_sonarr_block {
|
||||
ActiveSonarrBlock::DeleteDownloadPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteDownload(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteDownload(self.extract_download_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -138,7 +143,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a,
|
||||
ActiveSonarrBlock::DeleteDownloadPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteDownload(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteDownload(self.extract_download_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS};
|
||||
use crate::models::servarr_models::EditIndexerParams;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
||||
|
||||
@@ -17,6 +19,60 @@ pub(super) struct EditIndexerHandler<'a, 'b> {
|
||||
_context: Option<ActiveSonarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> EditIndexerHandler<'a, 'b> {
|
||||
fn build_edit_indexer_params(&mut self) -> EditIndexerParams {
|
||||
let indexer_id = self.app.data.sonarr_data.indexers.current_selection().id;
|
||||
let tags = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.edit_indexer_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
let params = {
|
||||
let EditIndexerModal {
|
||||
name,
|
||||
enable_rss,
|
||||
enable_automatic_search,
|
||||
enable_interactive_search,
|
||||
url,
|
||||
api_key,
|
||||
seed_ratio,
|
||||
priority,
|
||||
..
|
||||
} = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.edit_indexer_modal
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
EditIndexerParams {
|
||||
indexer_id,
|
||||
name: Some(name.text.clone()),
|
||||
enable_rss: Some(enable_rss.unwrap_or_default()),
|
||||
enable_automatic_search: Some(enable_automatic_search.unwrap_or_default()),
|
||||
enable_interactive_search: Some(enable_interactive_search.unwrap_or_default()),
|
||||
url: Some(url.text.clone()),
|
||||
api_key: Some(api_key.text.clone()),
|
||||
seed_ratio: Some(seed_ratio.text.clone()),
|
||||
tags: None,
|
||||
tag_input_string: Some(tags),
|
||||
priority: Some(*priority),
|
||||
clear_tags: false,
|
||||
}
|
||||
};
|
||||
|
||||
self.app.data.sonarr_data.edit_indexer_modal = None;
|
||||
|
||||
params
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveSonarrBlock) -> bool {
|
||||
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
||||
@@ -297,12 +353,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
||||
let selected_block = self.app.data.sonarr_data.selected_block.get_active_block();
|
||||
match selected_block {
|
||||
ActiveSonarrBlock::EditIndexerConfirmPrompt => {
|
||||
let sonarr_data = &mut self.app.data.sonarr_data;
|
||||
if sonarr_data.prompt_confirm {
|
||||
sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditIndexer(None));
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::EditIndexer(self.build_edit_indexer_params()));
|
||||
self.app.should_refresh = true;
|
||||
} else {
|
||||
sonarr_data.edit_indexer_modal = None;
|
||||
self.app.data.sonarr_data.edit_indexer_modal = None;
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -464,7 +520,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditIndexer(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::EditIndexer(self.build_edit_indexer_params()));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -4,9 +4,12 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::indexer;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS};
|
||||
use crate::models::servarr_models::EditIndexerParams;
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
@@ -896,7 +899,32 @@ mod tests {
|
||||
.sonarr_data
|
||||
.selected_block
|
||||
.set_index(0, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||
let edit_indexer_modal = EditIndexerModal {
|
||||
name: "Test Update".into(),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: "https://localhost:9696/1/".into(),
|
||||
api_key: "test1234".into(),
|
||||
seed_ratio: "1.3".into(),
|
||||
tags: "usenet, testing".into(),
|
||||
priority: 0,
|
||||
};
|
||||
app.data.sonarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
let expected_edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
name: Some("Test Update".to_owned()),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: Some("https://localhost:9696/1/".to_owned()),
|
||||
api_key: Some("test1234".to_owned()),
|
||||
seed_ratio: Some("1.3".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
priority: Some(0),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
|
||||
EditIndexerHandler::with(
|
||||
@@ -908,11 +936,11 @@ mod tests {
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||
assert!(app.data.sonarr_data.edit_indexer_modal.is_some());
|
||||
assert!(app.data.sonarr_data.edit_indexer_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::EditIndexer(None))
|
||||
Some(SonarrEvent::EditIndexer(expected_edit_indexer_params))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1408,7 +1436,7 @@ mod tests {
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS;
|
||||
use crate::models::BlockSelectionState;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1709,7 +1737,32 @@ mod tests {
|
||||
.sonarr_data
|
||||
.selected_block
|
||||
.set_index(0, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||
let edit_indexer_modal = EditIndexerModal {
|
||||
name: "Test Update".into(),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: "https://localhost:9696/1/".into(),
|
||||
api_key: "test1234".into(),
|
||||
seed_ratio: "1.3".into(),
|
||||
tags: "usenet, testing".into(),
|
||||
priority: 0,
|
||||
};
|
||||
app.data.sonarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
let expected_edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
name: Some("Test Update".to_owned()),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: Some("https://localhost:9696/1/".to_owned()),
|
||||
api_key: Some("test1234".to_owned()),
|
||||
seed_ratio: Some("1.3".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
priority: Some(0),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
EditIndexerHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
@@ -1720,11 +1773,11 @@ mod tests {
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||
assert!(app.data.sonarr_data.edit_indexer_modal.is_some());
|
||||
assert!(app.data.sonarr_data.edit_indexer_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::EditIndexer(None))
|
||||
Some(SonarrEvent::EditIndexer(expected_edit_indexer_params))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1740,6 +1793,48 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_indexer_params() {
|
||||
let mut app = App::default();
|
||||
let edit_indexer_modal = EditIndexerModal {
|
||||
name: "Test Update".into(),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: "https://localhost:9696/1/".into(),
|
||||
api_key: "test1234".into(),
|
||||
seed_ratio: "1.3".into(),
|
||||
tags: "usenet, testing".into(),
|
||||
priority: 0,
|
||||
};
|
||||
app.data.sonarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
let expected_edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
name: Some("Test Update".to_owned()),
|
||||
enable_rss: Some(false),
|
||||
enable_automatic_search: Some(false),
|
||||
enable_interactive_search: Some(false),
|
||||
url: Some("https://localhost:9696/1/".to_owned()),
|
||||
api_key: Some("test1234".to_owned()),
|
||||
seed_ratio: Some("1.3".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
priority: Some(0),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
let params = EditIndexerHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::EditIndexerPrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_indexer_params();
|
||||
|
||||
assert_eq!(params, expected_edit_indexer_params);
|
||||
assert!(app.data.sonarr_data.edit_indexer_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_indexer_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS,
|
||||
};
|
||||
use crate::models::sonarr_models::IndexerSettings;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -19,6 +20,23 @@ pub(super) struct IndexerSettingsHandler<'a, 'b> {
|
||||
_context: Option<ActiveSonarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> IndexerSettingsHandler<'a, 'b> {
|
||||
fn build_edit_indexer_settings_params(&mut self) -> IndexerSettings {
|
||||
let indexer_settings = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexer_settings
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
self.app.data.sonarr_data.indexer_settings = None;
|
||||
|
||||
indexer_settings
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveSonarrBlock) -> bool {
|
||||
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
||||
@@ -119,12 +137,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandl
|
||||
ActiveSonarrBlock::AllIndexerSettingsPrompt => {
|
||||
match self.app.data.sonarr_data.selected_block.get_active_block() {
|
||||
ActiveSonarrBlock::IndexerSettingsConfirmPrompt => {
|
||||
let sonarr_data = &mut self.app.data.sonarr_data;
|
||||
if sonarr_data.prompt_confirm {
|
||||
sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditAllIndexerSettings(None));
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::EditAllIndexerSettings(self.build_edit_indexer_settings_params()),
|
||||
);
|
||||
self.app.should_refresh = true;
|
||||
} else {
|
||||
sonarr_data.indexer_settings = None;
|
||||
self.app.data.sonarr_data.indexer_settings = None;
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -172,8 +191,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandl
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::EditAllIndexerSettings(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditAllIndexerSettings(
|
||||
self.build_edit_indexer_settings_params(),
|
||||
));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::indexer_settings;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS,
|
||||
@@ -285,7 +287,7 @@ mod tests {
|
||||
.sonarr_data
|
||||
.selected_block
|
||||
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.sonarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||
app.data.sonarr_data.indexer_settings = Some(indexer_settings());
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
|
||||
IndexerSettingsHandler::with(
|
||||
@@ -299,9 +301,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::EditAllIndexerSettings(None))
|
||||
Some(SonarrEvent::EditAllIndexerSettings(indexer_settings()))
|
||||
);
|
||||
assert!(app.data.sonarr_data.indexer_settings.is_some());
|
||||
assert!(app.data.sonarr_data.indexer_settings.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
|
||||
@@ -468,11 +470,11 @@ mod tests {
|
||||
mod test_handle_key_char {
|
||||
use crate::{
|
||||
models::{
|
||||
servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS,
|
||||
sonarr_models::IndexerSettings, BlockSelectionState,
|
||||
servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, BlockSelectionState,
|
||||
},
|
||||
network::sonarr_network::SonarrEvent,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -488,7 +490,7 @@ mod tests {
|
||||
.sonarr_data
|
||||
.selected_block
|
||||
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
||||
app.data.sonarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||
app.data.sonarr_data.indexer_settings = Some(indexer_settings());
|
||||
|
||||
IndexerSettingsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.confirm.key,
|
||||
@@ -501,9 +503,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::EditAllIndexerSettings(None))
|
||||
Some(SonarrEvent::EditAllIndexerSettings(indexer_settings()))
|
||||
);
|
||||
assert!(app.data.sonarr_data.indexer_settings.is_some());
|
||||
assert!(app.data.sonarr_data.indexer_settings.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
}
|
||||
@@ -519,6 +521,23 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_indexer_settings_params() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.indexer_settings = Some(indexer_settings());
|
||||
|
||||
let actual_indexer_settings = IndexerSettingsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::AllIndexerSettingsPrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_indexer_settings_params();
|
||||
|
||||
assert_eq!(actual_indexer_settings, indexer_settings());
|
||||
assert!(app.data.sonarr_data.indexer_settings.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_indexer_settings_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -7,6 +8,7 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::indexers::IndexersHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::indexer;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS,
|
||||
@@ -245,11 +247,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_delete_indexer_prompt_confirm_submit() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexers
|
||||
.set_items(vec![Indexer::default()]);
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::DeleteIndexerPrompt.into());
|
||||
@@ -265,7 +263,7 @@ mod tests {
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::DeleteIndexer(None))
|
||||
Some(SonarrEvent::DeleteIndexer(1))
|
||||
);
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||
}
|
||||
@@ -556,11 +554,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_delete_indexer_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexers
|
||||
.set_items(vec![Indexer::default()]);
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::DeleteIndexerPrompt.into());
|
||||
|
||||
@@ -575,7 +569,7 @@ mod tests {
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::DeleteIndexer(None))
|
||||
Some(SonarrEvent::DeleteIndexer(1))
|
||||
);
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||
}
|
||||
@@ -649,6 +643,22 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_indexer_id() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
|
||||
let indexer_id = IndexersHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::Indexers,
|
||||
None,
|
||||
)
|
||||
.extract_indexer_id();
|
||||
|
||||
assert_eq!(indexer_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_indexers_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -33,6 +33,10 @@ pub(super) struct IndexersHandler<'a, 'b> {
|
||||
|
||||
impl<'a, 'b> IndexersHandler<'a, 'b> {
|
||||
handle_table_events!(self, indexers, self.app.data.sonarr_data.indexers, Indexer);
|
||||
|
||||
fn extract_indexer_id(&self) -> i64 {
|
||||
self.app.data.sonarr_data.indexers.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a, 'b> {
|
||||
@@ -115,9 +119,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a,
|
||||
fn handle_submit(&mut self) {
|
||||
match self.active_sonarr_block {
|
||||
ActiveSonarrBlock::DeleteIndexerPrompt => {
|
||||
let sonarr_data = &mut self.app.data.sonarr_data;
|
||||
if sonarr_data.prompt_confirm {
|
||||
sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteIndexer(None));
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -189,7 +193,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a,
|
||||
ActiveSonarrBlock::DeleteIndexerPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteIndexer(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::handlers::table_handler::TableHandlingConfig;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::sonarr::modals::AddSeriesModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ActiveSonarrBlock, ADD_SERIES_BLOCKS, ADD_SERIES_SELECTION_BLOCKS,
|
||||
};
|
||||
use crate::models::sonarr_models::AddSeriesSearchResult;
|
||||
use crate::models::sonarr_models::{AddSeriesBody, AddSeriesOptions, AddSeriesSearchResult};
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::models::{BlockSelectionState, Scrollable};
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
|
||||
@@ -30,9 +32,90 @@ impl<'a, 'b> AddSeriesHandler<'a, 'b> {
|
||||
.sonarr_data
|
||||
.add_searched_series
|
||||
.as_mut()
|
||||
.unwrap(),
|
||||
.unwrap_or(&mut StatefulTable::default()),
|
||||
AddSeriesSearchResult
|
||||
);
|
||||
|
||||
fn build_add_series_body(&mut self) -> AddSeriesBody {
|
||||
let tags = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.add_series_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
let AddSeriesModal {
|
||||
root_folder_list,
|
||||
monitor_list,
|
||||
quality_profile_list,
|
||||
language_profile_list,
|
||||
series_type_list,
|
||||
use_season_folder,
|
||||
..
|
||||
} = self.app.data.sonarr_data.add_series_modal.as_ref().unwrap();
|
||||
let season_folder = *use_season_folder;
|
||||
let (tvdb_id, title) = {
|
||||
let AddSeriesSearchResult { tvdb_id, title, .. } = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.add_searched_series
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.current_selection()
|
||||
.clone();
|
||||
(tvdb_id, title.text)
|
||||
};
|
||||
let quality_profile = quality_profile_list.current_selection();
|
||||
let quality_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.quality_profile_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == quality_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
let language_profile = language_profile_list.current_selection();
|
||||
let language_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.language_profiles_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == language_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let path = root_folder_list.current_selection().path.clone();
|
||||
let monitor = monitor_list.current_selection().to_string();
|
||||
let series_type = series_type_list.current_selection().to_string();
|
||||
|
||||
self.app.data.sonarr_data.add_series_modal = None;
|
||||
|
||||
AddSeriesBody {
|
||||
tvdb_id,
|
||||
title,
|
||||
monitored: true,
|
||||
root_folder_path: path,
|
||||
quality_profile_id,
|
||||
language_profile_id,
|
||||
series_type,
|
||||
season_folder,
|
||||
tags: Vec::new(),
|
||||
tag_input_string: Some(tags),
|
||||
add_options: AddSeriesOptions {
|
||||
monitor,
|
||||
search_for_cutoff_unmet_episodes: true,
|
||||
search_for_missing_episodes: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a, 'b> {
|
||||
@@ -403,7 +486,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
||||
match self.app.data.sonarr_data.selected_block.get_active_block() {
|
||||
ActiveSonarrBlock::AddSeriesConfirmPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::AddSeries(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::AddSeries(self.build_add_series_body()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -534,7 +618,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::AddSeries(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::AddSeries(self.build_add_series_body()));
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::library::add_series_handler::AddSeriesHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::add_series_search_result;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::modals::AddSeriesModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ADD_SERIES_BLOCKS};
|
||||
use crate::models::servarr_models::RootFolder;
|
||||
use crate::models::sonarr_models::{AddSeriesSearchResult, SeriesMonitor, SeriesType};
|
||||
use crate::models::sonarr_models::{
|
||||
AddSeriesBody, AddSeriesOptions, AddSeriesSearchResult, SeriesMonitor, SeriesType,
|
||||
};
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
@@ -366,6 +372,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_home_end {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use strum::IntoEnumIterator;
|
||||
@@ -763,6 +770,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_left_right_action {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::models::servarr_data::sonarr::modals::AddSeriesModal;
|
||||
@@ -1109,10 +1117,67 @@ mod tests {
|
||||
#[test]
|
||||
fn test_add_series_confirm_prompt_prompt_confirmation_submit() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.add_series_modal = Some(AddSeriesModal::default());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into());
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
let mut add_series_modal = AddSeriesModal {
|
||||
use_season_folder: true,
|
||||
tags: "usenet, testing".into(),
|
||||
..AddSeriesModal::default()
|
||||
};
|
||||
add_series_modal.root_folder_list.set_items(vec![
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
RootFolder {
|
||||
id: 2,
|
||||
path: "/nfs2".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 21990232555520,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
]);
|
||||
add_series_modal.root_folder_list.state.select(Some(1));
|
||||
add_series_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["HD - 1080p".to_owned()]);
|
||||
add_series_modal
|
||||
.language_profile_list
|
||||
.set_items(vec!["English".to_owned()]);
|
||||
add_series_modal
|
||||
.monitor_list
|
||||
.set_items(Vec::from_iter(SeriesMonitor::iter()));
|
||||
add_series_modal
|
||||
.series_type_list
|
||||
.set_items(Vec::from_iter(SeriesType::iter()));
|
||||
app.data.sonarr_data.add_series_modal = Some(add_series_modal);
|
||||
app.data.sonarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||
app.data.sonarr_data.language_profiles_map = BiMap::from_iter([(2222, "English".to_owned())]);
|
||||
let mut add_searched_series = StatefulTable::default();
|
||||
add_searched_series.set_items(vec![add_series_search_result()]);
|
||||
app.data.sonarr_data.add_searched_series = Some(add_searched_series);
|
||||
let expected_add_series_body = AddSeriesBody {
|
||||
tvdb_id: 1234,
|
||||
title: "Test".to_owned(),
|
||||
monitored: true,
|
||||
root_folder_path: "/nfs2".to_owned(),
|
||||
quality_profile_id: 2222,
|
||||
language_profile_id: 2222,
|
||||
series_type: "standard".to_owned(),
|
||||
season_folder: true,
|
||||
tags: Vec::default(),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
add_options: AddSeriesOptions {
|
||||
monitor: "all".to_owned(),
|
||||
search_for_cutoff_unmet_episodes: true,
|
||||
search_for_missing_episodes: true,
|
||||
},
|
||||
};
|
||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(ADD_SERIES_SELECTION_BLOCKS);
|
||||
app
|
||||
.data
|
||||
@@ -1131,9 +1196,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::AddSeries(None))
|
||||
Some(SonarrEvent::AddSeries(expected_add_series_body))
|
||||
);
|
||||
assert!(app.data.sonarr_data.add_series_modal.is_some());
|
||||
assert!(app.data.sonarr_data.add_series_modal.is_none());
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
@@ -1440,6 +1505,7 @@ mod tests {
|
||||
},
|
||||
network::sonarr_network::SonarrEvent,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_add_series_search_input_backspace() {
|
||||
@@ -1553,7 +1619,64 @@ mod tests {
|
||||
#[test]
|
||||
fn test_add_series_confirm_prompt_prompt_confirmation_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.add_series_modal = Some(AddSeriesModal::default());
|
||||
let mut add_series_modal = AddSeriesModal {
|
||||
use_season_folder: true,
|
||||
tags: "usenet, testing".into(),
|
||||
..AddSeriesModal::default()
|
||||
};
|
||||
add_series_modal.root_folder_list.set_items(vec![
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
RootFolder {
|
||||
id: 2,
|
||||
path: "/nfs2".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 21990232555520,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
]);
|
||||
add_series_modal.root_folder_list.state.select(Some(1));
|
||||
add_series_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["HD - 1080p".to_owned()]);
|
||||
add_series_modal
|
||||
.language_profile_list
|
||||
.set_items(vec!["English".to_owned()]);
|
||||
add_series_modal
|
||||
.monitor_list
|
||||
.set_items(Vec::from_iter(SeriesMonitor::iter()));
|
||||
add_series_modal
|
||||
.series_type_list
|
||||
.set_items(Vec::from_iter(SeriesType::iter()));
|
||||
app.data.sonarr_data.add_series_modal = Some(add_series_modal);
|
||||
app.data.sonarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||
app.data.sonarr_data.language_profiles_map = BiMap::from_iter([(2222, "English".to_owned())]);
|
||||
let mut add_searched_series = StatefulTable::default();
|
||||
add_searched_series.set_items(vec![add_series_search_result()]);
|
||||
app.data.sonarr_data.add_searched_series = Some(add_searched_series);
|
||||
let expected_add_series_body = AddSeriesBody {
|
||||
tvdb_id: 1234,
|
||||
title: "Test".to_owned(),
|
||||
monitored: true,
|
||||
root_folder_path: "/nfs2".to_owned(),
|
||||
quality_profile_id: 2222,
|
||||
language_profile_id: 2222,
|
||||
series_type: "standard".to_owned(),
|
||||
season_folder: true,
|
||||
tags: Vec::default(),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
add_options: AddSeriesOptions {
|
||||
monitor: "all".to_owned(),
|
||||
search_for_cutoff_unmet_episodes: true,
|
||||
search_for_missing_episodes: true,
|
||||
},
|
||||
};
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into());
|
||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(ADD_SERIES_SELECTION_BLOCKS);
|
||||
@@ -1574,9 +1697,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::AddSeries(None))
|
||||
Some(SonarrEvent::AddSeries(expected_add_series_body))
|
||||
);
|
||||
assert!(app.data.sonarr_data.add_series_modal.is_some());
|
||||
assert!(app.data.sonarr_data.add_series_modal.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1591,6 +1714,93 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_series_search_no_panic_on_none_search_result() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.add_series_search = None;
|
||||
|
||||
AddSeriesHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::AddSeriesSearchResults,
|
||||
None,
|
||||
)
|
||||
.handle();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_add_series_body() {
|
||||
let mut app = App::default();
|
||||
let mut add_series_modal = AddSeriesModal {
|
||||
use_season_folder: true,
|
||||
tags: "usenet, testing".into(),
|
||||
..AddSeriesModal::default()
|
||||
};
|
||||
add_series_modal.root_folder_list.set_items(vec![
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
RootFolder {
|
||||
id: 2,
|
||||
path: "/nfs2".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 21990232555520,
|
||||
unmapped_folders: None,
|
||||
},
|
||||
]);
|
||||
add_series_modal.root_folder_list.state.select(Some(1));
|
||||
add_series_modal
|
||||
.quality_profile_list
|
||||
.set_items(vec!["HD - 1080p".to_owned()]);
|
||||
add_series_modal
|
||||
.language_profile_list
|
||||
.set_items(vec!["English".to_owned()]);
|
||||
add_series_modal
|
||||
.monitor_list
|
||||
.set_items(Vec::from_iter(SeriesMonitor::iter()));
|
||||
add_series_modal
|
||||
.series_type_list
|
||||
.set_items(Vec::from_iter(SeriesType::iter()));
|
||||
app.data.sonarr_data.add_series_modal = Some(add_series_modal);
|
||||
app.data.sonarr_data.quality_profile_map = BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||
app.data.sonarr_data.language_profiles_map = BiMap::from_iter([(2222, "English".to_owned())]);
|
||||
let mut add_searched_series = StatefulTable::default();
|
||||
add_searched_series.set_items(vec![add_series_search_result()]);
|
||||
app.data.sonarr_data.add_searched_series = Some(add_searched_series);
|
||||
let expected_add_series_body = AddSeriesBody {
|
||||
tvdb_id: 1234,
|
||||
title: "Test".to_owned(),
|
||||
monitored: true,
|
||||
root_folder_path: "/nfs2".to_owned(),
|
||||
quality_profile_id: 2222,
|
||||
language_profile_id: 2222,
|
||||
series_type: "standard".to_owned(),
|
||||
season_folder: true,
|
||||
tags: Vec::default(),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
add_options: AddSeriesOptions {
|
||||
monitor: "all".to_owned(),
|
||||
search_for_cutoff_unmet_episodes: true,
|
||||
search_for_missing_episodes: true,
|
||||
},
|
||||
};
|
||||
|
||||
let add_series_body = AddSeriesHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::AddSeriesPrompt,
|
||||
None,
|
||||
)
|
||||
.build_add_series_body();
|
||||
|
||||
assert_eq!(add_series_body, expected_add_series_body);
|
||||
assert!(app.data.sonarr_data.add_series_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_series_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::models::sonarr_models::DeleteSeriesParams;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use crate::{
|
||||
app::{key_binding::DEFAULT_KEYBINDINGS, App},
|
||||
event::Key,
|
||||
handlers::{handle_prompt_toggle, KeyEventHandler},
|
||||
models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS},
|
||||
network::sonarr_network::SonarrEvent,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -17,6 +18,21 @@ pub(super) struct DeleteSeriesHandler<'a, 'b> {
|
||||
_context: Option<ActiveSonarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeleteSeriesHandler<'a, 'b> {
|
||||
fn build_delete_series_params(&mut self) -> DeleteSeriesParams {
|
||||
let id = self.app.data.sonarr_data.series.current_selection().id;
|
||||
let delete_series_files = self.app.data.sonarr_data.delete_series_files;
|
||||
let add_list_exclusion = self.app.data.sonarr_data.add_list_exclusion;
|
||||
self.app.data.sonarr_data.reset_delete_series_preferences();
|
||||
|
||||
DeleteSeriesParams {
|
||||
id,
|
||||
delete_series_files,
|
||||
add_list_exclusion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DeleteSeriesHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveSonarrBlock) -> bool {
|
||||
DELETE_SERIES_BLOCKS.contains(&active_block)
|
||||
@@ -73,7 +89,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DeleteSeriesHandler<
|
||||
match self.app.data.sonarr_data.selected_block.get_active_block() {
|
||||
ActiveSonarrBlock::DeleteSeriesConfirmPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteSeries(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteSeries(self.build_delete_series_params()));
|
||||
self.app.should_refresh = true;
|
||||
} else {
|
||||
self.app.data.sonarr_data.reset_delete_series_preferences();
|
||||
@@ -109,7 +126,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DeleteSeriesHandler<
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteSeries(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteSeries(self.build_delete_series_params()));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::library::delete_series_handler::DeleteSeriesHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::series;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS};
|
||||
use crate::models::sonarr_models::DeleteSeriesParams;
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -132,6 +135,12 @@ mod tests {
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.data.sonarr_data.delete_series_files = true;
|
||||
app.data.sonarr_data.add_list_exclusion = true;
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
let expected_delete_series_params = DeleteSeriesParams {
|
||||
id: 1,
|
||||
delete_series_files: true,
|
||||
add_list_exclusion: true,
|
||||
};
|
||||
app.data.sonarr_data.selected_block =
|
||||
BlockSelectionState::new(DELETE_SERIES_SELECTION_BLOCKS);
|
||||
app
|
||||
@@ -151,12 +160,12 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::DeleteSeries(None))
|
||||
Some(SonarrEvent::DeleteSeries(expected_delete_series_params))
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert!(app.data.sonarr_data.delete_series_files);
|
||||
assert!(app.data.sonarr_data.add_list_exclusion);
|
||||
assert!(!app.data.sonarr_data.delete_series_files);
|
||||
assert!(!app.data.sonarr_data.add_list_exclusion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -222,6 +231,7 @@ mod tests {
|
||||
|
||||
mod test_handle_esc {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
||||
@@ -258,6 +268,7 @@ mod tests {
|
||||
},
|
||||
network::sonarr_network::SonarrEvent,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -268,6 +279,12 @@ mod tests {
|
||||
app.push_navigation_stack(ActiveSonarrBlock::DeleteSeriesPrompt.into());
|
||||
app.data.sonarr_data.delete_series_files = true;
|
||||
app.data.sonarr_data.add_list_exclusion = true;
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
let expected_delete_series_params = DeleteSeriesParams {
|
||||
id: 1,
|
||||
delete_series_files: true,
|
||||
add_list_exclusion: true,
|
||||
};
|
||||
app.data.sonarr_data.selected_block =
|
||||
BlockSelectionState::new(DELETE_SERIES_SELECTION_BLOCKS);
|
||||
app
|
||||
@@ -287,12 +304,12 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::DeleteSeries(None))
|
||||
Some(SonarrEvent::DeleteSeries(expected_delete_series_params))
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert!(app.data.sonarr_data.delete_series_files);
|
||||
assert!(app.data.sonarr_data.add_list_exclusion);
|
||||
assert!(!app.data.sonarr_data.delete_series_files);
|
||||
assert!(!app.data.sonarr_data.add_list_exclusion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,6 +324,31 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_delete_series_params() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
app.data.sonarr_data.delete_series_files = true;
|
||||
app.data.sonarr_data.add_list_exclusion = true;
|
||||
let expected_delete_series_params = DeleteSeriesParams {
|
||||
id: 1,
|
||||
delete_series_files: true,
|
||||
add_list_exclusion: true,
|
||||
};
|
||||
|
||||
let delete_series_params = DeleteSeriesHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::DeleteSeriesPrompt,
|
||||
None,
|
||||
)
|
||||
.build_delete_series_params();
|
||||
|
||||
assert_eq!(delete_series_params, expected_delete_series_params);
|
||||
assert!(!app.data.sonarr_data.delete_series_files);
|
||||
assert!(!app.data.sonarr_data.add_list_exclusion);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_series_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -2,7 +2,9 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::sonarr::modals::EditSeriesModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS};
|
||||
use crate::models::sonarr_models::EditSeriesParams;
|
||||
use crate::models::Scrollable;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
|
||||
@@ -18,6 +20,78 @@ pub(super) struct EditSeriesHandler<'a, 'b> {
|
||||
context: Option<ActiveSonarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> EditSeriesHandler<'a, 'b> {
|
||||
fn build_edit_series_params(&mut self) -> EditSeriesParams {
|
||||
let series_id = self.app.data.sonarr_data.series.current_selection().id;
|
||||
let tags = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.edit_series_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
|
||||
let params = {
|
||||
let EditSeriesModal {
|
||||
monitored,
|
||||
use_season_folders,
|
||||
path,
|
||||
series_type_list,
|
||||
quality_profile_list,
|
||||
language_profile_list,
|
||||
..
|
||||
} = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.edit_series_modal
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let quality_profile = quality_profile_list.current_selection();
|
||||
let quality_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.quality_profile_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == quality_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
let language_profile = language_profile_list.current_selection();
|
||||
let language_profile_id = *self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.language_profiles_map
|
||||
.iter()
|
||||
.filter(|(_, value)| *value == language_profile)
|
||||
.map(|(key, _)| key)
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
EditSeriesParams {
|
||||
series_id,
|
||||
monitored: Some(monitored.unwrap_or_default()),
|
||||
use_season_folders: Some(use_season_folders.unwrap_or_default()),
|
||||
series_type: Some(*series_type_list.current_selection()),
|
||||
quality_profile_id: Some(quality_profile_id),
|
||||
language_profile_id: Some(language_profile_id),
|
||||
root_folder_path: Some(path.text.clone()),
|
||||
tag_input_string: Some(tags),
|
||||
..EditSeriesParams::default()
|
||||
}
|
||||
};
|
||||
|
||||
self.app.data.sonarr_data.edit_series_modal = None;
|
||||
|
||||
params
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveSonarrBlock) -> bool {
|
||||
EDIT_SERIES_BLOCKS.contains(&active_block)
|
||||
@@ -258,7 +332,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
||||
match self.app.data.sonarr_data.selected_block.get_active_block() {
|
||||
ActiveSonarrBlock::EditSeriesConfirmPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditSeries(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::EditSeries(self.build_edit_series_params()));
|
||||
self.app.should_refresh = true;
|
||||
}
|
||||
|
||||
@@ -392,7 +467,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditSeries(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::EditSeries(self.build_edit_series_params()));
|
||||
self.app.should_refresh = true;
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::library::edit_series_handler::EditSeriesHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::series;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::modals::EditSeriesModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS};
|
||||
use crate::models::sonarr_models::SeriesType;
|
||||
use crate::models::sonarr_models::{EditSeriesParams, Series, SeriesType};
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -243,6 +245,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_home_end {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use strum::IntoEnumIterator;
|
||||
@@ -531,6 +534,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_left_right_action {
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::models::servarr_data::sonarr::modals::EditSeriesModal;
|
||||
@@ -770,7 +774,43 @@ mod tests {
|
||||
#[test]
|
||||
fn test_edit_series_confirm_prompt_prompt_confirmation_submit() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||
let mut edit_series = EditSeriesModal {
|
||||
tags: "usenet, testing".to_owned().into(),
|
||||
path: "/nfs/Test Path".to_owned().into(),
|
||||
monitored: Some(false),
|
||||
use_season_folders: Some(false),
|
||||
..EditSeriesModal::default()
|
||||
};
|
||||
edit_series
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_series
|
||||
.language_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "English".to_owned()]);
|
||||
edit_series
|
||||
.series_type_list
|
||||
.set_items(Vec::from_iter(SeriesType::iter()));
|
||||
app.data.sonarr_data.edit_series_modal = Some(edit_series);
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
monitored: false,
|
||||
season_folder: false,
|
||||
..series()
|
||||
}]);
|
||||
app.data.sonarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
app.data.sonarr_data.language_profiles_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "English".to_owned())]);
|
||||
let expected_edit_series_params = EditSeriesParams {
|
||||
series_id: 1,
|
||||
monitored: Some(false),
|
||||
use_season_folders: Some(false),
|
||||
series_type: Some(SeriesType::Standard),
|
||||
quality_profile_id: Some(1111),
|
||||
language_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
..EditSeriesParams::default()
|
||||
};
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
@@ -792,9 +832,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::EditSeries(None))
|
||||
Some(SonarrEvent::EditSeries(expected_edit_series_params))
|
||||
);
|
||||
assert!(app.data.sonarr_data.edit_series_modal.is_some());
|
||||
assert!(app.data.sonarr_data.edit_series_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
|
||||
@@ -1135,6 +1175,7 @@ mod tests {
|
||||
},
|
||||
network::sonarr_network::SonarrEvent,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn test_edit_series_path_input_backspace() {
|
||||
@@ -1253,7 +1294,43 @@ mod tests {
|
||||
#[test]
|
||||
fn test_edit_series_confirm_prompt_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||
let mut edit_series = EditSeriesModal {
|
||||
tags: "usenet, testing".to_owned().into(),
|
||||
path: "/nfs/Test Path".to_owned().into(),
|
||||
monitored: Some(false),
|
||||
use_season_folders: Some(false),
|
||||
..EditSeriesModal::default()
|
||||
};
|
||||
edit_series
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_series
|
||||
.language_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "English".to_owned()]);
|
||||
edit_series
|
||||
.series_type_list
|
||||
.set_items(Vec::from_iter(SeriesType::iter()));
|
||||
app.data.sonarr_data.edit_series_modal = Some(edit_series);
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
monitored: false,
|
||||
season_folder: false,
|
||||
..series()
|
||||
}]);
|
||||
app.data.sonarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
app.data.sonarr_data.language_profiles_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "English".to_owned())]);
|
||||
let expected_edit_series_params = EditSeriesParams {
|
||||
series_id: 1,
|
||||
monitored: Some(false),
|
||||
use_season_folders: Some(false),
|
||||
series_type: Some(SeriesType::Standard),
|
||||
quality_profile_id: Some(1111),
|
||||
language_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
..EditSeriesParams::default()
|
||||
};
|
||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
||||
app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||
@@ -1274,9 +1351,9 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::EditSeries(None))
|
||||
Some(SonarrEvent::EditSeries(expected_edit_series_params))
|
||||
);
|
||||
assert!(app.data.sonarr_data.edit_series_modal.is_some());
|
||||
assert!(app.data.sonarr_data.edit_series_modal.is_none());
|
||||
assert!(app.should_refresh);
|
||||
}
|
||||
}
|
||||
@@ -1292,6 +1369,59 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_edit_series_params() {
|
||||
let mut app = App::default();
|
||||
let mut edit_series = EditSeriesModal {
|
||||
tags: "usenet, testing".to_owned().into(),
|
||||
path: "/nfs/Test Path".to_owned().into(),
|
||||
monitored: Some(false),
|
||||
use_season_folders: Some(false),
|
||||
..EditSeriesModal::default()
|
||||
};
|
||||
edit_series
|
||||
.quality_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||
edit_series
|
||||
.language_profile_list
|
||||
.set_items(vec!["Any".to_owned(), "English".to_owned()]);
|
||||
edit_series
|
||||
.series_type_list
|
||||
.set_items(Vec::from_iter(SeriesType::iter()));
|
||||
app.data.sonarr_data.edit_series_modal = Some(edit_series);
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
monitored: false,
|
||||
season_folder: false,
|
||||
..series()
|
||||
}]);
|
||||
app.data.sonarr_data.quality_profile_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||
app.data.sonarr_data.language_profiles_map =
|
||||
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "English".to_owned())]);
|
||||
let expected_edit_series_params = EditSeriesParams {
|
||||
series_id: 1,
|
||||
monitored: Some(false),
|
||||
use_season_folders: Some(false),
|
||||
series_type: Some(SeriesType::Standard),
|
||||
quality_profile_id: Some(1111),
|
||||
language_profile_id: Some(1111),
|
||||
root_folder_path: Some("/nfs/Test Path".to_owned()),
|
||||
tag_input_string: Some("usenet, testing".to_owned()),
|
||||
..EditSeriesParams::default()
|
||||
};
|
||||
|
||||
let edit_series_params = EditSeriesHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::EditSeriesPrompt,
|
||||
None,
|
||||
)
|
||||
.build_edit_series_params();
|
||||
|
||||
assert_eq!(edit_series_params, expected_edit_series_params);
|
||||
assert!(app.data.sonarr_data.edit_series_modal.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edit_series_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -53,6 +53,19 @@ impl<'a, 'b> EpisodeDetailsHandler<'a, 'b> {
|
||||
.episode_releases,
|
||||
SonarrRelease
|
||||
);
|
||||
|
||||
fn extract_episode_id(&self) -> i64 {
|
||||
self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.season_details_modal
|
||||
.as_ref()
|
||||
.expect("Season details modal is undefined")
|
||||
.episodes
|
||||
.current_selection()
|
||||
.id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandler<'a, 'b> {
|
||||
@@ -204,8 +217,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
||||
}
|
||||
ActiveSonarrBlock::AutomaticallySearchEpisodePrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::TriggerAutomaticEpisodeSearch(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(self.extract_episode_id()),
|
||||
);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -308,8 +322,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::TriggerAutomaticEpisodeSearch(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(self.extract_episode_id()),
|
||||
);
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -3,14 +3,16 @@ mod tests {
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::handlers::sonarr_handlers::library::episode_details_handler::EpisodeDetailsHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::episode;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::modals::EpisodeDetailsModal;
|
||||
use crate::models::servarr_data::sonarr::modals::{EpisodeDetailsModal, SeasonDetailsModal};
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS,
|
||||
};
|
||||
use crate::models::sonarr_models::SonarrReleaseDownloadBody;
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -206,7 +208,7 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveSonarrBlock::AutomaticallySearchEpisodePrompt,
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(None)
|
||||
SonarrEvent::TriggerAutomaticEpisodeSearch(1)
|
||||
)]
|
||||
fn test_episode_details_prompt_confirm_submit(
|
||||
#[case] prompt_block: ActiveSonarrBlock,
|
||||
@@ -221,6 +223,14 @@ mod tests {
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data = create_test_sonarr_data();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.season_details_modal
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.episodes
|
||||
.set_items(vec![episode()]);
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(active_sonarr_block.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
@@ -543,6 +553,14 @@ mod tests {
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data = create_test_sonarr_data();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.season_details_modal
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.episodes
|
||||
.set_items(vec![episode()]);
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(active_sonarr_block.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt.into());
|
||||
@@ -559,7 +577,7 @@ mod tests {
|
||||
assert_eq!(app.get_current_route(), active_sonarr_block.into());
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::TriggerAutomaticEpisodeSearch(None))
|
||||
Some(SonarrEvent::TriggerAutomaticEpisodeSearch(1))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -607,6 +625,38 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_episode_id() {
|
||||
let mut app = App::default();
|
||||
let mut season_details_modal = SeasonDetailsModal::default();
|
||||
season_details_modal.episodes.set_items(vec![episode()]);
|
||||
app.data.sonarr_data.season_details_modal = Some(season_details_modal);
|
||||
|
||||
let episode_id = EpisodeDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::EpisodeDetails,
|
||||
None,
|
||||
)
|
||||
.extract_episode_id();
|
||||
|
||||
assert_eq!(episode_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "Season details modal is undefined"]
|
||||
fn test_extract_episode_id_panics_when_season_details_modal_is_none() {
|
||||
let mut app = App::default();
|
||||
|
||||
EpisodeDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::EpisodeDetails,
|
||||
None,
|
||||
)
|
||||
.extract_episode_id();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_episode_details_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -65,6 +65,44 @@ 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
|
||||
}
|
||||
|
||||
fn extract_episode_id(&self) -> i64 {
|
||||
self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.season_details_modal
|
||||
.as_ref()
|
||||
.expect("Season details have not been loaded")
|
||||
.episodes
|
||||
.current_selection()
|
||||
.id
|
||||
}
|
||||
|
||||
fn extract_series_id_season_number_tuple(&self) -> (i64, i64) {
|
||||
let series_id = self.app.data.sonarr_data.series.current_selection().id;
|
||||
let season_number = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.seasons
|
||||
.current_selection()
|
||||
.season_number;
|
||||
(series_id, season_number)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler<'a, 'b> {
|
||||
@@ -233,16 +271,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
||||
.push_navigation_stack(ActiveSonarrBlock::SeasonHistoryDetails.into()),
|
||||
ActiveSonarrBlock::DeleteEpisodeFilePrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteEpisodeFile(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteEpisodeFile(
|
||||
self.extract_episode_file_id(),
|
||||
));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveSonarrBlock::AutomaticallySearchSeasonPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::TriggerAutomaticSeasonSearch(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch(self.extract_series_id_season_number_tuple()),
|
||||
);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -340,8 +380,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
||||
match self.active_sonarr_block {
|
||||
ActiveSonarrBlock::SeasonDetails if self.key == DEFAULT_KEYBINDINGS.toggle_monitoring.key => {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::ToggleEpisodeMonitoring(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::ToggleEpisodeMonitoring(self.extract_episode_id()),
|
||||
);
|
||||
|
||||
self
|
||||
.app
|
||||
@@ -366,15 +407,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::TriggerAutomaticSeasonSearch(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch(self.extract_series_id_season_number_tuple()),
|
||||
);
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
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));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteEpisodeFile(
|
||||
self.extract_episode_file_id(),
|
||||
));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ mod tests {
|
||||
use crate::handlers::sonarr_handlers::library::season_details_handler::{
|
||||
releases_sorting_options, SeasonDetailsHandler,
|
||||
};
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::episode;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::modals::SeasonDetailsModal;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data;
|
||||
@@ -14,7 +15,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_eq, assert_str_eq};
|
||||
use rstest::rstest;
|
||||
use serde_json::Number;
|
||||
use std::cmp::Ordering;
|
||||
@@ -275,11 +276,11 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveSonarrBlock::AutomaticallySearchSeasonPrompt,
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch(None)
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch((0, 0))
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::DeleteEpisodeFilePrompt,
|
||||
SonarrEvent::DeleteEpisodeFile(None)
|
||||
SonarrEvent::DeleteEpisodeFile(0)
|
||||
)]
|
||||
fn test_season_details_prompt_confirm_submit(
|
||||
#[case] prompt_block: ActiveSonarrBlock,
|
||||
@@ -550,6 +551,14 @@ mod tests {
|
||||
fn test_toggle_monitoring_key() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data = create_test_sonarr_data();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.season_details_modal
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.episodes
|
||||
.set_items(vec![episode()]);
|
||||
app.push_navigation_stack(ActiveSonarrBlock::SeasonDetails.into());
|
||||
app.is_routing = false;
|
||||
|
||||
@@ -569,7 +578,7 @@ mod tests {
|
||||
assert!(app.is_routing);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::ToggleEpisodeMonitoring(None))
|
||||
Some(SonarrEvent::ToggleEpisodeMonitoring(1))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -704,11 +713,11 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveSonarrBlock::AutomaticallySearchSeasonPrompt,
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch(None)
|
||||
SonarrEvent::TriggerAutomaticSeasonSearch((0, 0))
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::DeleteEpisodeFilePrompt,
|
||||
SonarrEvent::DeleteEpisodeFile(None)
|
||||
SonarrEvent::DeleteEpisodeFile(0)
|
||||
)]
|
||||
fn test_season_details_prompt_confirm_confirm_key(
|
||||
#[case] prompt_block: ActiveSonarrBlock,
|
||||
@@ -783,6 +792,85 @@ 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();
|
||||
|
||||
SeasonDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SeasonDetails,
|
||||
None,
|
||||
)
|
||||
.extract_episode_file_id();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_episode_id() {
|
||||
let mut app = App::default();
|
||||
let mut season_details_modal = SeasonDetailsModal::default();
|
||||
season_details_modal.episodes.set_items(vec![episode()]);
|
||||
app.data.sonarr_data.season_details_modal = Some(season_details_modal);
|
||||
|
||||
let episode_id = SeasonDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SeasonDetails,
|
||||
None,
|
||||
)
|
||||
.extract_episode_id();
|
||||
|
||||
assert_eq!(episode_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Season details have not been loaded")]
|
||||
fn test_extract_episode_id_panic_when_season_details_modal_is_none() {
|
||||
let mut app = App::default();
|
||||
|
||||
SeasonDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SeasonDetails,
|
||||
None,
|
||||
)
|
||||
.extract_episode_id();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_series_id_season_number_tuple() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data = create_test_sonarr_data();
|
||||
|
||||
let (series_id, season_number) = SeasonDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SeasonDetails,
|
||||
None,
|
||||
)
|
||||
.extract_series_id_season_number_tuple();
|
||||
|
||||
assert_eq!(series_id, 0);
|
||||
assert_eq!(season_number, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_season_details_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -37,6 +37,23 @@ impl<'a, 'b> SeriesDetailsHandler<'a, 'b> {
|
||||
.expect("Series history is undefined"),
|
||||
SonarrHistoryItem
|
||||
);
|
||||
|
||||
fn extract_series_id_season_number_tuple(&self) -> (i64, i64) {
|
||||
let series_id = self.app.data.sonarr_data.series.current_selection().id;
|
||||
let season_number = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.seasons
|
||||
.current_selection()
|
||||
.season_number;
|
||||
|
||||
(series_id, season_number)
|
||||
}
|
||||
|
||||
fn extract_series_id(&self) -> i64 {
|
||||
self.app.data.sonarr_data.series.current_selection().id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler<'a, 'b> {
|
||||
@@ -168,8 +185,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
||||
}
|
||||
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::TriggerAutomaticSeriesSearch(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(self.extract_series_id()),
|
||||
);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -177,7 +195,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
||||
ActiveSonarrBlock::UpdateAndScanSeriesPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::UpdateAndScanSeries(None));
|
||||
Some(SonarrEvent::UpdateAndScanSeries(self.extract_series_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -259,8 +277,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
||||
}
|
||||
_ if key == DEFAULT_KEYBINDINGS.toggle_monitoring.key => {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::ToggleSeasonMonitoring(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::ToggleSeasonMonitoring(self.extract_series_id_season_number_tuple()),
|
||||
);
|
||||
|
||||
self
|
||||
.app
|
||||
@@ -299,8 +318,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
||||
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt => {
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::TriggerAutomaticSeriesSearch(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(self.extract_series_id()),
|
||||
);
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
@@ -308,7 +328,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
||||
ActiveSonarrBlock::UpdateAndScanSeriesPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::UpdateAndScanSeries(None));
|
||||
Some(SonarrEvent::UpdateAndScanSeries(self.extract_series_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
|
||||
@@ -4,6 +4,7 @@ mod tests {
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::library::series_details_handler::SeriesDetailsHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::{season, series};
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ActiveSonarrBlock, SERIES_DETAILS_BLOCKS,
|
||||
@@ -11,6 +12,7 @@ mod tests {
|
||||
use crate::models::sonarr_models::Season;
|
||||
use crate::models::sonarr_models::SonarrHistoryItem;
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -181,11 +183,11 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt,
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(None)
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(1)
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::UpdateAndScanSeriesPrompt,
|
||||
SonarrEvent::UpdateAndScanSeries(None)
|
||||
SonarrEvent::UpdateAndScanSeries(1)
|
||||
)]
|
||||
fn test_series_details_prompt_confirm_submit(
|
||||
#[case] prompt_block: ActiveSonarrBlock,
|
||||
@@ -193,6 +195,7 @@ mod tests {
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
app.push_navigation_stack(ActiveSonarrBlock::SeriesDetails.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
|
||||
@@ -398,7 +401,7 @@ mod tests {
|
||||
assert!(app.is_routing);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::ToggleSeasonMonitoring(None))
|
||||
Some(SonarrEvent::ToggleSeasonMonitoring((0, 0)))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -565,11 +568,11 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(
|
||||
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt,
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(None)
|
||||
SonarrEvent::TriggerAutomaticSeriesSearch(1)
|
||||
)]
|
||||
#[case(
|
||||
ActiveSonarrBlock::UpdateAndScanSeriesPrompt,
|
||||
SonarrEvent::UpdateAndScanSeries(None)
|
||||
SonarrEvent::UpdateAndScanSeries(1)
|
||||
)]
|
||||
fn test_series_details_prompt_confirm_confirm_key(
|
||||
#[case] prompt_block: ActiveSonarrBlock,
|
||||
@@ -579,6 +582,7 @@ mod tests {
|
||||
) {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
app.push_navigation_stack(active_sonarr_block.into());
|
||||
app.push_navigation_stack(prompt_block.into());
|
||||
|
||||
@@ -610,6 +614,39 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_series_id_season_number_tuple() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
app.data.sonarr_data.seasons.set_items(vec![season()]);
|
||||
|
||||
let series_id_season_number_tuple = SeriesDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SeriesDetails,
|
||||
None,
|
||||
)
|
||||
.extract_series_id_season_number_tuple();
|
||||
|
||||
assert_eq!(series_id_season_number_tuple, (1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_series_id() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_items(vec![series()]);
|
||||
|
||||
let series_id = SeriesDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SeriesDetails,
|
||||
None,
|
||||
)
|
||||
.extract_series_id();
|
||||
|
||||
assert_eq!(series_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_series_details_handler_is_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||
use crate::handlers::table_handler::TableHandlingConfig;
|
||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS};
|
||||
use crate::models::servarr_models::RootFolder;
|
||||
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys};
|
||||
@@ -28,6 +28,30 @@ impl<'a, 'b> RootFoldersHandler<'a, 'b> {
|
||||
self.app.data.sonarr_data.root_folders,
|
||||
RootFolder
|
||||
);
|
||||
|
||||
fn build_add_root_folder_body(&mut self) -> AddRootFolderBody {
|
||||
let root_folder = self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.edit_root_folder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.text
|
||||
.clone();
|
||||
self.app.data.sonarr_data.edit_root_folder = None;
|
||||
AddRootFolderBody { path: root_folder }
|
||||
}
|
||||
|
||||
fn extract_root_folder_id(&self) -> i64 {
|
||||
self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.root_folders
|
||||
.current_selection()
|
||||
.id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'a, 'b> {
|
||||
@@ -124,7 +148,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
||||
ActiveSonarrBlock::DeleteRootFolderPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteRootFolder(None));
|
||||
Some(SonarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -140,7 +164,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
||||
.text
|
||||
.is_empty() =>
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::AddRootFolder(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::AddRootFolder(
|
||||
self.build_add_root_folder_body(),
|
||||
));
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.should_ignore_quit_key = false;
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -192,7 +218,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::DeleteRootFolder(None));
|
||||
Some(SonarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::sonarr_handlers::root_folders::RootFoldersHandler;
|
||||
use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::root_folder;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS};
|
||||
use crate::models::servarr_models::RootFolder;
|
||||
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
|
||||
mod test_handle_home_end {
|
||||
@@ -257,6 +259,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_add_root_folder_prompt_confirm_submit() {
|
||||
let mut app = App::default();
|
||||
let expected_add_root_folder_body = AddRootFolderBody {
|
||||
path: "Test".to_owned(),
|
||||
};
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
@@ -280,12 +285,13 @@ mod tests {
|
||||
assert!(!app.should_ignore_quit_key);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::AddRootFolder(None))
|
||||
Some(SonarrEvent::AddRootFolder(expected_add_root_folder_body))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
ActiveSonarrBlock::RootFolders.into()
|
||||
);
|
||||
assert!(app.data.sonarr_data.edit_root_folder.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -321,7 +327,7 @@ mod tests {
|
||||
.data
|
||||
.sonarr_data
|
||||
.root_folders
|
||||
.set_items(vec![RootFolder::default()]);
|
||||
.set_items(vec![root_folder()]);
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::DeleteRootFolderPrompt.into());
|
||||
@@ -337,7 +343,7 @@ mod tests {
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::DeleteRootFolder(None))
|
||||
Some(SonarrEvent::DeleteRootFolder(1))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -614,7 +620,7 @@ mod tests {
|
||||
.data
|
||||
.sonarr_data
|
||||
.root_folders
|
||||
.set_items(vec![RootFolder::default()]);
|
||||
.set_items(vec![root_folder()]);
|
||||
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::DeleteRootFolderPrompt.into());
|
||||
|
||||
@@ -629,7 +635,7 @@ mod tests {
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::DeleteRootFolder(None))
|
||||
Some(SonarrEvent::DeleteRootFolder(1))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -649,6 +655,46 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_root_folder_id() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.root_folders
|
||||
.set_items(vec![root_folder()]);
|
||||
|
||||
let root_folder_id = RootFoldersHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::DeleteRootFolderPrompt,
|
||||
None,
|
||||
)
|
||||
.extract_root_folder_id();
|
||||
|
||||
assert_eq!(root_folder_id, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_add_root_folder_body() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.edit_root_folder = Some("/nfs/test".into());
|
||||
let expected_add_root_folder_body = AddRootFolderBody {
|
||||
path: "/nfs/test".to_owned(),
|
||||
};
|
||||
|
||||
let root_folder = RootFoldersHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::AddRootFolderPrompt,
|
||||
None,
|
||||
)
|
||||
.build_add_root_folder_body();
|
||||
|
||||
assert_eq!(root_folder, expected_add_root_folder_body);
|
||||
assert!(app.data.sonarr_data.edit_root_folder.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root_folders_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod utils {
|
||||
pub(in crate::handlers::sonarr_handlers) mod utils {
|
||||
use crate::models::servarr_models::{
|
||||
Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder,
|
||||
};
|
||||
use crate::models::sonarr_models::{
|
||||
AddSeriesSearchResult, AddSeriesSearchResultStatistics, DownloadRecord, DownloadStatus,
|
||||
Episode, EpisodeFile, IndexerSettings, MediaInfo, Rating, Season, SeasonStatistics, Series,
|
||||
SeriesStatistics, SeriesStatus, SeriesType,
|
||||
};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use chrono::DateTime;
|
||||
use serde_json::{json, Number};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! test_edit_series_key {
|
||||
@@ -154,4 +165,230 @@ mod utils {
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn add_series_search_result() -> AddSeriesSearchResult {
|
||||
AddSeriesSearchResult {
|
||||
tvdb_id: 1234,
|
||||
title: HorizontallyScrollableText::from("Test"),
|
||||
status: Some("continuing".to_owned()),
|
||||
ended: false,
|
||||
overview: Some("New series blah blah blah".to_owned()),
|
||||
genres: genres(),
|
||||
year: 2023,
|
||||
network: Some("Prime Video".to_owned()),
|
||||
runtime: 60,
|
||||
ratings: Some(rating()),
|
||||
statistics: Some(add_series_search_result_statistics()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_series_search_result_statistics() -> AddSeriesSearchResultStatistics {
|
||||
AddSeriesSearchResultStatistics { season_count: 3 }
|
||||
}
|
||||
|
||||
pub fn download_record() -> DownloadRecord {
|
||||
DownloadRecord {
|
||||
title: "Test Download Title".to_owned(),
|
||||
status: DownloadStatus::Downloading,
|
||||
id: 1,
|
||||
episode_id: 1,
|
||||
size: 3543348019f64,
|
||||
sizeleft: 1771674009f64,
|
||||
output_path: Some(HorizontallyScrollableText::from(
|
||||
"/nfs/tv/Test show/season 1/",
|
||||
)),
|
||||
indexer: "kickass torrents".to_owned(),
|
||||
download_client: Some("transmission".to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn episode() -> Episode {
|
||||
Episode {
|
||||
id: 1,
|
||||
series_id: 1,
|
||||
tvdb_id: 1234,
|
||||
episode_file_id: 1,
|
||||
season_number: 1,
|
||||
episode_number: 1,
|
||||
title: "Something cool".to_owned(),
|
||||
air_date_utc: Some(DateTime::from(
|
||||
DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap(),
|
||||
)),
|
||||
overview: Some("Okay so this one time at band camp...".to_owned()),
|
||||
has_file: true,
|
||||
monitored: true,
|
||||
episode_file: Some(episode_file()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn episode_file() -> EpisodeFile {
|
||||
EpisodeFile {
|
||||
id: 1,
|
||||
relative_path: "/season 1/episode 1.mkv".to_owned(),
|
||||
path: "/nfs/tv/series/season 1/episode 1.mkv".to_owned(),
|
||||
size: 3543348019,
|
||||
quality: quality_wrapper(),
|
||||
languages: vec![language()],
|
||||
date_added: DateTime::from(DateTime::parse_from_rfc3339("2024-02-10T07:28:45Z").unwrap()),
|
||||
media_info: Some(media_info()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn genres() -> Vec<String> {
|
||||
vec!["cool".to_owned(), "family".to_owned(), "fun".to_owned()]
|
||||
}
|
||||
|
||||
pub fn indexer() -> Indexer {
|
||||
Indexer {
|
||||
enable_rss: true,
|
||||
enable_automatic_search: true,
|
||||
enable_interactive_search: true,
|
||||
supports_rss: true,
|
||||
supports_search: true,
|
||||
protocol: "torrent".to_owned(),
|
||||
priority: 25,
|
||||
download_client_id: 0,
|
||||
name: Some("Test Indexer".to_owned()),
|
||||
implementation_name: Some("Torznab".to_owned()),
|
||||
implementation: Some("Torznab".to_owned()),
|
||||
config_contract: Some("TorznabSettings".to_owned()),
|
||||
tags: vec![Number::from(1)],
|
||||
id: 1,
|
||||
fields: Some(vec![
|
||||
IndexerField {
|
||||
name: Some("baseUrl".to_owned()),
|
||||
value: Some(json!("https://test.com")),
|
||||
},
|
||||
IndexerField {
|
||||
name: Some("apiKey".to_owned()),
|
||||
value: Some(json!("")),
|
||||
},
|
||||
IndexerField {
|
||||
name: Some("seedCriteria.seedRatio".to_owned()),
|
||||
value: Some(json!("1.2")),
|
||||
},
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indexer_settings() -> IndexerSettings {
|
||||
IndexerSettings {
|
||||
id: 1,
|
||||
minimum_age: 1,
|
||||
retention: 1,
|
||||
maximum_size: 12345,
|
||||
rss_sync_interval: 60,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn language() -> Language {
|
||||
Language {
|
||||
id: 1,
|
||||
name: "English".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn media_info() -> MediaInfo {
|
||||
MediaInfo {
|
||||
audio_bitrate: 0,
|
||||
audio_channels: Number::from_f64(7.1).unwrap(),
|
||||
audio_codec: Some("AAC".to_owned()),
|
||||
audio_languages: Some("eng".to_owned()),
|
||||
audio_stream_count: 1,
|
||||
video_bit_depth: 10,
|
||||
video_bitrate: 0,
|
||||
video_codec: "x265".to_owned(),
|
||||
video_fps: Number::from_f64(23.976).unwrap(),
|
||||
resolution: "1920x1080".to_owned(),
|
||||
run_time: "23:51".to_owned(),
|
||||
scan_type: "Progressive".to_owned(),
|
||||
subtitles: Some("English".to_owned()),
|
||||
}
|
||||
}
|
||||
pub fn quality() -> Quality {
|
||||
Quality {
|
||||
name: "Bluray-1080p".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quality_wrapper() -> QualityWrapper {
|
||||
QualityWrapper { quality: quality() }
|
||||
}
|
||||
|
||||
pub fn rating() -> Rating {
|
||||
Rating {
|
||||
votes: 406744,
|
||||
value: 8.4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn season() -> Season {
|
||||
Season {
|
||||
title: None,
|
||||
season_number: 1,
|
||||
monitored: true,
|
||||
statistics: season_statistics(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn season_statistics() -> SeasonStatistics {
|
||||
SeasonStatistics {
|
||||
previous_airing: Some(DateTime::from(
|
||||
DateTime::parse_from_rfc3339("2022-10-24T01:00:00Z").unwrap(),
|
||||
)),
|
||||
next_airing: None,
|
||||
episode_file_count: 10,
|
||||
episode_count: 10,
|
||||
total_episode_count: 10,
|
||||
size_on_disk: 36708563419,
|
||||
percent_of_episodes: 100.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn series() -> Series {
|
||||
Series {
|
||||
title: "Test".to_owned().into(),
|
||||
status: SeriesStatus::Continuing,
|
||||
ended: false,
|
||||
overview: Some("Blah blah blah".to_owned()),
|
||||
network: Some("HBO".to_owned()),
|
||||
seasons: Some(vec![season()]),
|
||||
year: 2022,
|
||||
path: "/nfs/tv/Test".to_owned(),
|
||||
quality_profile_id: 6,
|
||||
language_profile_id: 1,
|
||||
season_folder: true,
|
||||
monitored: true,
|
||||
runtime: 63,
|
||||
tvdb_id: 371572,
|
||||
series_type: SeriesType::Standard,
|
||||
certification: Some("TV-MA".to_owned()),
|
||||
genres: vec!["cool".to_owned(), "family".to_owned(), "fun".to_owned()],
|
||||
tags: vec![Number::from(3)],
|
||||
ratings: rating(),
|
||||
statistics: Some(series_statistics()),
|
||||
id: 1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn series_statistics() -> SeriesStatistics {
|
||||
SeriesStatistics {
|
||||
season_count: 2,
|
||||
episode_file_count: 18,
|
||||
episode_count: 18,
|
||||
total_episode_count: 50,
|
||||
size_on_disk: 63894022699,
|
||||
percent_of_episodes: 100.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_folder() -> RootFolder {
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS};
|
||||
use crate::models::sonarr_models::SonarrTaskName;
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
use crate::models::Scrollable;
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
@@ -18,6 +19,18 @@ pub(super) struct SystemDetailsHandler<'a, 'b> {
|
||||
_context: Option<ActiveSonarrBlock>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> SystemDetailsHandler<'a, 'b> {
|
||||
fn extract_task_name(&self) -> SonarrTaskName {
|
||||
self
|
||||
.app
|
||||
.data
|
||||
.sonarr_data
|
||||
.tasks
|
||||
.current_selection()
|
||||
.task_name
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler<'a, 'b> {
|
||||
fn accepts(active_block: ActiveSonarrBlock) -> bool {
|
||||
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
|
||||
@@ -137,7 +150,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler
|
||||
}
|
||||
ActiveSonarrBlock::SystemTaskStartConfirmPrompt => {
|
||||
if self.app.data.sonarr_data.prompt_confirm {
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::StartTask(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::StartTask(self.extract_task_name()));
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -174,7 +188,8 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler
|
||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
||||
{
|
||||
self.app.data.sonarr_data.prompt_confirm = true;
|
||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::StartTask(None));
|
||||
self.app.data.sonarr_data.prompt_confirm_action =
|
||||
Some(SonarrEvent::StartTask(self.extract_task_name()));
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
@@ -12,10 +12,11 @@ mod tests {
|
||||
ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS,
|
||||
};
|
||||
use crate::models::servarr_models::QueueEvent;
|
||||
use crate::models::sonarr_models::SonarrTask;
|
||||
use crate::models::sonarr_models::{SonarrTask, SonarrTaskName};
|
||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||
@@ -245,6 +246,7 @@ mod tests {
|
||||
use crate::{extended_stateful_iterable_vec, test_iterable_home_and_end};
|
||||
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
test_iterable_home_and_end!(
|
||||
test_log_details_home_end,
|
||||
@@ -693,6 +695,11 @@ mod tests {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.updates = ScrollableText::with_string("Test".to_owned());
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.tasks
|
||||
.set_items(vec![SonarrTask::default()]);
|
||||
app.push_navigation_stack(ActiveSonarrBlock::SystemTasks.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::SystemTaskStartConfirmPrompt.into());
|
||||
|
||||
@@ -707,7 +714,7 @@ mod tests {
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::StartTask(None))
|
||||
Some(SonarrEvent::StartTask(SonarrTaskName::default()))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -848,6 +855,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_key_char {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
@@ -914,6 +922,11 @@ mod tests {
|
||||
let mut app = App::default();
|
||||
app.push_navigation_stack(ActiveSonarrBlock::System.into());
|
||||
app.data.sonarr_data.updates = ScrollableText::with_string("Test".to_owned());
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.tasks
|
||||
.set_items(vec![SonarrTask::default()]);
|
||||
app.push_navigation_stack(ActiveSonarrBlock::SystemTasks.into());
|
||||
app.push_navigation_stack(ActiveSonarrBlock::SystemTaskStartConfirmPrompt.into());
|
||||
|
||||
@@ -928,7 +941,7 @@ mod tests {
|
||||
assert!(app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
app.data.sonarr_data.prompt_confirm_action,
|
||||
Some(SonarrEvent::StartTask(None))
|
||||
Some(SonarrEvent::StartTask(SonarrTaskName::default()))
|
||||
);
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
@@ -948,6 +961,26 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_task_name() {
|
||||
let mut app = App::default();
|
||||
app
|
||||
.data
|
||||
.sonarr_data
|
||||
.tasks
|
||||
.set_items(vec![SonarrTask::default()]);
|
||||
|
||||
let task_name = SystemDetailsHandler::with(
|
||||
DEFAULT_KEYBINDINGS.esc.key,
|
||||
&mut app,
|
||||
ActiveSonarrBlock::SystemTasks,
|
||||
None,
|
||||
)
|
||||
.extract_task_name();
|
||||
|
||||
assert_eq!(task_name, SonarrTaskName::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_details_handler_not_ready_when_loading() {
|
||||
let mut app = App::default();
|
||||
|
||||
@@ -29,6 +29,8 @@ pub struct AddMovieBody {
|
||||
pub minimum_availability: String,
|
||||
pub monitored: bool,
|
||||
pub tags: Vec<i64>,
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub tag_input_string: Option<String>,
|
||||
pub add_options: AddMovieOptions,
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ pub enum CreditType {
|
||||
Crew,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Default)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct DeleteMovieParams {
|
||||
pub id: i64,
|
||||
@@ -188,6 +190,8 @@ pub struct EditMovieParams {
|
||||
pub quality_profile_id: Option<i64>,
|
||||
pub root_folder_path: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub tag_input_string: Option<String>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::HorizontallyScrollableText;
|
||||
#[path = "servarr_models_tests.rs"]
|
||||
mod servarr_models_tests;
|
||||
|
||||
#[derive(Default, Serialize, Debug)]
|
||||
#[derive(Default, Serialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct AddRootFolderBody {
|
||||
pub path: String,
|
||||
}
|
||||
@@ -101,6 +101,8 @@ pub struct EditIndexerParams {
|
||||
pub api_key: Option<String>,
|
||||
pub seed_ratio: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub tag_input_string: Option<String>,
|
||||
pub priority: Option<i64>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ pub struct AddSeriesBody {
|
||||
pub series_type: String,
|
||||
pub season_folder: bool,
|
||||
pub tags: Vec<i64>,
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub tag_input_string: Option<String>,
|
||||
pub add_options: AddSeriesOptions,
|
||||
}
|
||||
|
||||
@@ -95,7 +97,7 @@ pub struct BlocklistResponse {
|
||||
pub records: Vec<BlocklistItem>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct DeleteSeriesParams {
|
||||
pub id: i64,
|
||||
@@ -192,6 +194,8 @@ pub struct EditSeriesParams {
|
||||
pub series_type: Option<SeriesType>,
|
||||
pub root_folder_path: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub tag_input_string: Option<String>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
|
||||
+262
-711
File diff suppressed because it is too large
Load Diff
+413
-1519
File diff suppressed because it is too large
Load Diff
+296
-787
File diff suppressed because it is too large
Load Diff
+522
-2639
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user