fix: Improved fault tolerance for search result tables and test all indexer results tables

This commit is contained in:
2026-01-07 14:58:32 -07:00
parent 64d8c65831
commit d3947d9e15
8 changed files with 145 additions and 16 deletions
+8 -2
View File
@@ -368,7 +368,7 @@ impl Network<'_, '_> {
.await; .await;
request_props.ignore_status_code = true; request_props.ignore_status_code = true;
self let result = self
.handle_request::<(), Vec<IndexerTestResult>>(request_props, |test_results, mut app| { .handle_request::<(), Vec<IndexerTestResult>>(request_props, |test_results, mut app| {
let mut test_all_indexer_results = StatefulTable::default(); let mut test_all_indexer_results = StatefulTable::default();
let indexers = app.data.radarr_data.indexers.items.clone(); let indexers = app.data.radarr_data.indexers.items.clone();
@@ -403,6 +403,12 @@ impl Network<'_, '_> {
test_all_indexer_results.set_items(modal_test_results); test_all_indexer_results.set_items(modal_test_results);
app.data.radarr_data.indexer_test_all_results = Some(test_all_indexer_results); app.data.radarr_data.indexer_test_all_results = Some(test_all_indexer_results);
}) })
.await .await;
if result.is_err() {
self.app.lock().await.data.radarr_data.indexer_test_all_results = Some(StatefulTable::default());
}
result
} }
} }
@@ -925,4 +925,29 @@ mod tests {
); );
assert_eq!(results, response); assert_eq!(results, response);
} }
#[tokio::test]
async fn test_handle_test_all_radarr_indexers_event_sets_empty_table_on_api_error() {
let (async_server, app, _server) = MockServarrApi::post()
.status(500)
.build_for(RadarrEvent::TestAllIndexers)
.await;
let mut network = test_network(&app);
let result = network
.handle_radarr_event(RadarrEvent::TestAllIndexers)
.await;
async_server.assert_async().await;
assert_err!(result);
assert_some!(
&app
.lock()
.await
.data
.radarr_data
.indexer_test_all_results
);
assert_is_empty!(app.lock().await.data.radarr_data.indexer_test_all_results.as_ref().unwrap());
}
} }
+8 -2
View File
@@ -498,7 +498,7 @@ impl Network<'_, '_> {
) )
.await; .await;
self let result = self
.handle_request::<(), Vec<AddMovieSearchResult>>(request_props, |movie_vec, mut app| { .handle_request::<(), Vec<AddMovieSearchResult>>(request_props, |movie_vec, mut app| {
if movie_vec.is_empty() { if movie_vec.is_empty() {
app.pop_and_push_navigation_stack(ActiveRadarrBlock::AddMovieEmptySearchResults.into()); app.pop_and_push_navigation_stack(ActiveRadarrBlock::AddMovieEmptySearchResults.into());
@@ -511,7 +511,13 @@ impl Network<'_, '_> {
app.data.radarr_data.add_searched_movies = Some(add_searched_movies); app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
} }
}) })
.await .await;
if result.is_err() {
self.app.lock().await.data.radarr_data.add_searched_movies = Some(StatefulTable::default());
}
result
} }
pub(in crate::network) async fn toggle_movie_monitoring(&mut self, movie_id: i64) -> Result<()> { pub(in crate::network) async fn toggle_movie_monitoring(&mut self, movie_id: i64) -> Result<()> {
@@ -981,14 +981,13 @@ mod tests {
); );
async_server.assert_async().await; async_server.assert_async().await;
assert!( assert_none!(
app_arc &app_arc
.lock() .lock()
.await .await
.data .data
.radarr_data .radarr_data
.add_searched_movies .add_searched_movies
.is_none()
); );
assert_eq!( assert_eq!(
app_arc.lock().await.get_current_route(), app_arc.lock().await.get_current_route(),
@@ -996,6 +995,33 @@ mod tests {
); );
} }
#[tokio::test]
async fn test_handle_search_new_movie_event_sets_empty_table_on_api_error() {
let (async_server, app_arc, _server) = MockServarrApi::get()
.returns(json!([]))
.status(500)
.query("term=test%20term")
.build_for(RadarrEvent::SearchNewMovie("test term".into()))
.await;
let mut network = test_network(&app_arc);
let result = network
.handle_radarr_event(RadarrEvent::SearchNewMovie("test term".into()))
.await;
async_server.assert_async().await;
assert_err!(result);
assert_some!(
&app_arc
.lock()
.await
.data
.radarr_data
.add_searched_movies
);
assert_is_empty!(app_arc.lock().await.data.radarr_data.add_searched_movies.as_ref().unwrap());
}
#[tokio::test] #[tokio::test]
async fn test_handle_toggle_movie_monitoring_event() { async fn test_handle_toggle_movie_monitoring_event() {
let mut expected_body: Value = serde_json::from_str(MOVIE_JSON).unwrap(); let mut expected_body: Value = serde_json::from_str(MOVIE_JSON).unwrap();
+8 -2
View File
@@ -366,7 +366,7 @@ impl Network<'_, '_> {
.await; .await;
request_props.ignore_status_code = true; request_props.ignore_status_code = true;
self let result = self
.handle_request::<(), Vec<IndexerTestResult>>(request_props, |test_results, mut app| { .handle_request::<(), Vec<IndexerTestResult>>(request_props, |test_results, mut app| {
let mut test_all_indexer_results = StatefulTable::default(); let mut test_all_indexer_results = StatefulTable::default();
let indexers = app.data.sonarr_data.indexers.items.clone(); let indexers = app.data.sonarr_data.indexers.items.clone();
@@ -401,6 +401,12 @@ impl Network<'_, '_> {
test_all_indexer_results.set_items(modal_test_results); test_all_indexer_results.set_items(modal_test_results);
app.data.sonarr_data.indexer_test_all_results = Some(test_all_indexer_results); app.data.sonarr_data.indexer_test_all_results = Some(test_all_indexer_results);
}) })
.await .await;
if result.is_err() {
self.app.lock().await.data.sonarr_data.indexer_test_all_results = Some(StatefulTable::default());
}
result
} }
} }
@@ -884,4 +884,29 @@ mod tests {
); );
assert_eq!(results, response); assert_eq!(results, response);
} }
#[tokio::test]
async fn test_handle_test_all_sonarr_indexers_event_sets_empty_table_on_api_error() {
let (async_server, app, _server) = MockServarrApi::post()
.status(500)
.build_for(SonarrEvent::TestAllIndexers)
.await;
let mut network = test_network(&app);
app.lock().await.server_tabs.next();
let result = network
.handle_sonarr_event(SonarrEvent::TestAllIndexers)
.await;
async_server.assert_async().await;
assert_err!(result);
let app = app.lock().await;
assert_some!(
&app
.data
.sonarr_data
.indexer_test_all_results
);
assert_is_empty!(app.data.sonarr_data.indexer_test_all_results.as_ref().unwrap());
}
} }
@@ -362,20 +362,26 @@ impl Network<'_, '_> {
) )
.await; .await;
self let result = self
.handle_request::<(), Vec<AddSeriesSearchResult>>(request_props, |series_vec, mut app| { .handle_request::<(), Vec<AddSeriesSearchResult>>(request_props, |series_vec, mut app| {
if series_vec.is_empty() { if series_vec.is_empty() {
app.pop_and_push_navigation_stack(ActiveSonarrBlock::AddSeriesEmptySearchResults.into()); app.pop_and_push_navigation_stack(ActiveSonarrBlock::AddSeriesEmptySearchResults.into());
} else if let Some(add_searched_seriess) = app.data.sonarr_data.add_searched_series.as_mut() } else if let Some(add_searched_series) = app.data.sonarr_data.add_searched_series.as_mut()
{ {
add_searched_seriess.set_items(series_vec); add_searched_series.set_items(series_vec);
} else { } else {
let mut add_searched_seriess = StatefulTable::default(); let mut add_searched_series = StatefulTable::default();
add_searched_seriess.set_items(series_vec); add_searched_series.set_items(series_vec);
app.data.sonarr_data.add_searched_series = Some(add_searched_seriess); app.data.sonarr_data.add_searched_series = Some(add_searched_series);
} }
}) })
.await .await;
if result.is_err() {
self.app.lock().await.data.sonarr_data.add_searched_series = Some(StatefulTable::default());
}
result
} }
pub(in crate::network::sonarr_network) async fn trigger_automatic_series_search( pub(in crate::network::sonarr_network) async fn trigger_automatic_series_search(
@@ -943,6 +943,35 @@ mod tests {
); );
} }
#[tokio::test]
async fn test_handle_search_new_series_event_sets_empty_table_on_api_error() {
let (async_server, app, _server) = MockServarrApi::get()
.status(500)
.query("term=test%20term")
.build_for(SonarrEvent::SearchNewSeries("test term".into()))
.await;
app.lock().await.server_tabs.next();
let mut network = test_network(&app);
let result =
network
.handle_sonarr_event(SonarrEvent::SearchNewSeries("test term".into()))
.await;
async_server.assert_async().await;
assert_err!(result);
let app = app.lock().await;
assert_some!(
&app
.data
.sonarr_data
.add_searched_series
);
assert_is_empty!(
app.data.sonarr_data.add_searched_series.as_ref().unwrap()
);
}
#[tokio::test] #[tokio::test]
async fn test_handle_trigger_automatic_series_search_event() { async fn test_handle_trigger_automatic_series_search_event() {
let (async_server, app, _server) = MockServarrApi::post() let (async_server, app, _server) = MockServarrApi::post()