feat(network): Support for testing all Sonarr indexers at once

This commit is contained in:
2024-11-22 17:35:36 -07:00
parent 68830a8789
commit 6896fcc134
14 changed files with 207 additions and 22 deletions
+8 -5
View File
@@ -12,9 +12,9 @@ use crate::models::radarr_models::{
EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult, Movie, MovieCommandBody,
MovieHistoryItem, RadarrSerdeable, RadarrTask, RadarrTaskName, ReleaseDownloadBody, SystemStatus,
};
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
use crate::models::servarr_data::radarr::modals::{
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, IndexerTestResultModalItem,
MovieDetailsModal,
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, MovieDetailsModal,
};
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
use crate::models::servarr_models::{
@@ -259,7 +259,10 @@ impl<'a, 'b> Network<'a, 'b> {
.test_radarr_indexer(indexer_id)
.await
.map(RadarrSerdeable::from),
RadarrEvent::TestAllIndexers => self.test_all_indexers().await.map(RadarrSerdeable::from),
RadarrEvent::TestAllIndexers => self
.test_all_radarr_indexers()
.await
.map(RadarrSerdeable::from),
RadarrEvent::TriggerAutomaticSearch(movie_id) => self
.trigger_automatic_search(movie_id)
.await
@@ -2095,8 +2098,8 @@ impl<'a, 'b> Network<'a, 'b> {
.await
}
async fn test_all_indexers(&mut self) -> Result<Vec<IndexerTestResult>> {
info!("Testing all indexers");
async fn test_all_radarr_indexers(&mut self) -> Result<Vec<IndexerTestResult>> {
info!("Testing all Radarr indexers");
let event = RadarrEvent::TestAllIndexers;
let mut request_props = self
+1 -1
View File
@@ -1065,7 +1065,7 @@ mod test {
}
#[tokio::test]
async fn test_handle_test_all_indexers_event() {
async fn test_handle_test_all_radarr_indexers_event() {
let indexers = vec![
Indexer {
id: 1,
+60 -3
View File
@@ -5,9 +5,13 @@ use serde_json::{json, Value};
use crate::{
models::{
servarr_data::sonarr::{
modals::{EpisodeDetailsModal, SeasonDetailsModal},
sonarr_data::ActiveSonarrBlock,
radarr_models::IndexerTestResult,
servarr_data::{
modals::IndexerTestResultModalItem,
sonarr::{
modals::{EpisodeDetailsModal, SeasonDetailsModal},
sonarr_data::ActiveSonarrBlock,
},
},
servarr_models::{
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
@@ -68,6 +72,7 @@ pub enum SonarrEvent {
MarkHistoryItemAsFailed(i64),
StartTask(Option<SonarrTaskName>),
TestIndexer(Option<i64>),
TestAllIndexers,
}
impl NetworkResource for SonarrEvent {
@@ -100,6 +105,7 @@ impl NetworkResource for SonarrEvent {
SonarrEvent::MarkHistoryItemAsFailed(_) => "/history/failed",
SonarrEvent::StartTask(_) => "/command",
SonarrEvent::TestIndexer(_) => "/indexer/test",
SonarrEvent::TestAllIndexers => "/indexer/testall",
}
}
}
@@ -230,6 +236,10 @@ impl<'a, 'b> Network<'a, 'b> {
.test_sonarr_indexer(indexer_id)
.await
.map(SonarrSerdeable::from),
SonarrEvent::TestAllIndexers => self
.test_all_sonarr_indexers()
.await
.map(SonarrSerdeable::from),
}
}
@@ -1376,6 +1386,53 @@ impl<'a, 'b> Network<'a, 'b> {
.await
}
async fn test_all_sonarr_indexers(&mut self) -> Result<Vec<IndexerTestResult>> {
info!("Testing all Sonarr indexers");
let event = SonarrEvent::TestAllIndexers;
let mut request_props = self
.request_props_from(event, RequestMethod::Post, None, None, None)
.await;
request_props.ignore_status_code = true;
self
.handle_request::<(), Vec<IndexerTestResult>>(request_props, |test_results, mut app| {
let mut test_all_indexer_results = StatefulTable::default();
let indexers = app.data.sonarr_data.indexers.items.clone();
let modal_test_results = test_results
.iter()
.map(|result| {
let name = indexers
.iter()
.filter(|&indexer| indexer.id == result.id)
.map(|indexer| indexer.name.clone())
.nth(0)
.unwrap_or_default();
let validation_failures = result
.validation_failures
.iter()
.map(|failure| {
format!(
"Failure for field '{}': {}",
failure.property_name, failure.error_message
)
})
.collect::<Vec<String>>()
.join(", ");
IndexerTestResultModalItem {
name: name.unwrap_or_default(),
is_valid: result.is_valid,
validation_failures: validation_failures.into(),
}
})
.collect();
test_all_indexer_results.set_items(modal_test_results);
app.data.sonarr_data.indexer_test_all_results = Some(test_all_indexer_results);
})
.await
}
async fn extract_series_id(&mut self, series_id: Option<i64>) -> (i64, String) {
let series_id = if let Some(id) = series_id {
id
+100
View File
@@ -15,6 +15,8 @@ mod test {
use tokio_util::sync::CancellationToken;
use crate::app::App;
use crate::models::radarr_models::IndexerTestResult;
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
use crate::models::servarr_data::sonarr::modals::{EpisodeDetailsModal, SeasonDetailsModal};
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
use crate::models::servarr_models::{
@@ -225,6 +227,7 @@ mod test {
#[case(SonarrEvent::GetUpdates, "/update")]
#[case(SonarrEvent::MarkHistoryItemAsFailed(0), "/history/failed")]
#[case(SonarrEvent::TestIndexer(None), "/indexer/test")]
#[case(SonarrEvent::TestAllIndexers, "/indexer/testall")]
fn test_resource(#[case] event: SonarrEvent, #[case] expected_uri: String) {
assert_str_eq!(event.resource(), expected_uri);
}
@@ -4128,6 +4131,103 @@ mod test {
}
}
#[tokio::test]
async fn test_handle_test_all_sonarr_indexers_event() {
let indexers = vec![
Indexer {
id: 1,
name: Some("Test 1".to_owned()),
..Indexer::default()
},
Indexer {
id: 2,
name: Some("Test 2".to_owned()),
..Indexer::default()
},
];
let indexer_test_results_modal_items = vec![
IndexerTestResultModalItem {
name: "Test 1".to_owned(),
is_valid: true,
validation_failures: HorizontallyScrollableText::default(),
},
IndexerTestResultModalItem {
name: "Test 2".to_owned(),
is_valid: false,
validation_failures: "Failure for field 'test field 1': test error message, Failure for field 'test field 2': test error message 2".into(),
},
];
let response_json = json!([
{
"id": 1,
"isValid": true,
"validationFailures": []
},
{
"id": 2,
"isValid": false,
"validationFailures": [
{
"propertyName": "test field 1",
"errorMessage": "test error message",
"severity": "error"
},
{
"propertyName": "test field 2",
"errorMessage": "test error message 2",
"severity": "error"
},
]
}]);
let response: Vec<IndexerTestResult> = serde_json::from_value(response_json.clone()).unwrap();
let (async_server, app_arc, _server) = mock_servarr_api(
RequestMethod::Post,
None,
Some(response_json),
Some(400),
SonarrEvent::TestAllIndexers,
None,
None,
)
.await;
app_arc
.lock()
.await
.data
.sonarr_data
.indexers
.set_items(indexers);
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
if let SonarrSerdeable::IndexerTestResults(results) = network
.handle_sonarr_event(SonarrEvent::TestAllIndexers)
.await
.unwrap()
{
async_server.assert_async().await;
assert!(app_arc
.lock()
.await
.data
.sonarr_data
.indexer_test_all_results
.is_some());
assert_eq!(
app_arc
.lock()
.await
.data
.sonarr_data
.indexer_test_all_results
.as_ref()
.unwrap()
.items,
indexer_test_results_modal_items
);
assert_eq!(results, response);
}
}
#[tokio::test]
async fn test_extract_series_id() {
let app_arc = Arc::new(Mutex::new(App::default()));