feat(network): Support for testing all Sonarr indexers at once
This commit is contained in:
@@ -5,7 +5,7 @@ mod tests {
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::radarr::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use strum::IntoEnumIterator;
|
||||
@@ -14,7 +14,7 @@ mod tests {
|
||||
use pretty_assertions::assert_str_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::models::servarr_data::radarr::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::simple_stateful_iterable_vec;
|
||||
|
||||
@@ -112,7 +112,7 @@ mod tests {
|
||||
|
||||
mod test_handle_home_end {
|
||||
use crate::extended_stateful_iterable_vec;
|
||||
use crate::models::servarr_data::radarr::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use pretty_assertions::assert_str_eq;
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod modals;
|
||||
pub mod radarr;
|
||||
pub mod sonarr;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
|
||||
#[derive(Default, Clone, Eq, PartialEq, Debug)]
|
||||
pub struct IndexerTestResultModalItem {
|
||||
pub name: String,
|
||||
pub is_valid: bool,
|
||||
pub validation_failures: HorizontallyScrollableText,
|
||||
}
|
||||
@@ -291,10 +291,3 @@ impl From<&RadarrData<'_>> for EditCollectionModal {
|
||||
edit_collection_modal
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Eq, PartialEq, Debug)]
|
||||
pub struct IndexerTestResultModalItem {
|
||||
pub name: String,
|
||||
pub is_valid: bool,
|
||||
pub validation_failures: HorizontallyScrollableText,
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ use crate::models::radarr_models::{
|
||||
AddMovieSearchResult, BlocklistItem, Collection, CollectionMovie, DownloadRecord,
|
||||
IndexerSettings, Movie, RadarrTask,
|
||||
};
|
||||
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_models::{DiskSpace, Indexer, QueueEvent, RootFolder};
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
|
||||
@@ -3,6 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use strum::EnumIter;
|
||||
|
||||
use crate::models::{
|
||||
servarr_data::modals::IndexerTestResultModalItem,
|
||||
servarr_models::{DiskSpace, Indexer, QueueEvent, RootFolder},
|
||||
sonarr_models::{
|
||||
BlocklistItem, DownloadRecord, IndexerSettings, Season, Series, SonarrHistoryItem, SonarrTask,
|
||||
@@ -26,6 +27,7 @@ pub struct SonarrData {
|
||||
pub history: StatefulTable<SonarrHistoryItem>,
|
||||
pub indexers: StatefulTable<Indexer>,
|
||||
pub indexer_settings: Option<IndexerSettings>,
|
||||
pub indexer_test_all_results: Option<StatefulTable<IndexerTestResultModalItem>>,
|
||||
pub indexer_test_error: Option<String>,
|
||||
pub logs: StatefulList<HorizontallyScrollableText>,
|
||||
pub quality_profile_map: BiMap<i64, String>,
|
||||
@@ -53,6 +55,7 @@ impl Default for SonarrData {
|
||||
indexers: StatefulTable::default(),
|
||||
indexer_settings: None,
|
||||
indexer_test_error: None,
|
||||
indexer_test_all_results: None,
|
||||
logs: StatefulList::default(),
|
||||
quality_profile_map: BiMap::new(),
|
||||
queued_events: StatefulTable::default(),
|
||||
|
||||
@@ -42,6 +42,7 @@ mod tests {
|
||||
assert!(sonarr_data.indexers.is_empty());
|
||||
assert!(sonarr_data.indexer_settings.is_none());
|
||||
assert!(sonarr_data.indexer_test_error.is_none());
|
||||
assert!(sonarr_data.indexer_test_all_results.is_none());
|
||||
assert!(sonarr_data.logs.is_empty());
|
||||
assert!(sonarr_data.quality_profile_map.is_empty());
|
||||
assert!(sonarr_data.queued_events.is_empty());
|
||||
|
||||
@@ -10,6 +10,7 @@ use strum::EnumIter;
|
||||
use crate::serde_enum_from;
|
||||
|
||||
use super::{
|
||||
radarr_models::IndexerTestResult,
|
||||
servarr_models::{
|
||||
DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper,
|
||||
QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
|
||||
@@ -437,6 +438,7 @@ pub enum SonarrSerdeable {
|
||||
HostConfig(HostConfig),
|
||||
IndexerSettings(IndexerSettings),
|
||||
Indexers(Vec<Indexer>),
|
||||
IndexerTestResults(Vec<IndexerTestResult>),
|
||||
LogResponse(LogResponse),
|
||||
QualityProfiles(Vec<QualityProfile>),
|
||||
QueueEvents(Vec<QueueEvent>),
|
||||
@@ -477,6 +479,7 @@ serde_enum_from!(
|
||||
HostConfig(HostConfig),
|
||||
IndexerSettings(IndexerSettings),
|
||||
Indexers(Vec<Indexer>),
|
||||
IndexerTestResults(Vec<IndexerTestResult>),
|
||||
LogResponse(LogResponse),
|
||||
QualityProfiles(Vec<QualityProfile>),
|
||||
QueueEvents(Vec<QueueEvent>),
|
||||
|
||||
@@ -4,6 +4,7 @@ mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
use crate::models::{
|
||||
radarr_models::IndexerTestResult,
|
||||
servarr_models::{
|
||||
DiskSpace, HostConfig, Indexer, Log, LogResponse, QualityProfile, QueueEvent, Release,
|
||||
RootFolder, SecurityConfig, Tag, Update,
|
||||
@@ -438,4 +439,19 @@ mod tests {
|
||||
|
||||
assert_eq!(sonarr_serdeable, SonarrSerdeable::Updates(updates));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sonarr_serdeable_from_indexer_test_results() {
|
||||
let indexer_test_results = vec![IndexerTestResult {
|
||||
id: 1,
|
||||
..IndexerTestResult::default()
|
||||
}];
|
||||
|
||||
let sonarr_serdeable: SonarrSerdeable = indexer_test_results.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
sonarr_serdeable,
|
||||
SonarrSerdeable::IndexerTestResults(indexer_test_results)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::app::context_clues::{build_context_clue_string, BARE_POPUP_CONTEXT_CLUES};
|
||||
use crate::app::App;
|
||||
use crate::models::servarr_data::radarr::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use crate::models::Route;
|
||||
use crate::ui::radarr_ui::indexers::draw_indexers;
|
||||
|
||||
Reference in New Issue
Block a user