feat(network): Added the ability to test an individual indexer in Sonarr
This commit is contained in:
@@ -26,6 +26,7 @@ pub struct SonarrData {
|
||||
pub history: StatefulTable<SonarrHistoryItem>,
|
||||
pub indexers: StatefulTable<Indexer>,
|
||||
pub indexer_settings: Option<IndexerSettings>,
|
||||
pub indexer_test_error: Option<String>,
|
||||
pub logs: StatefulList<HorizontallyScrollableText>,
|
||||
pub quality_profile_map: BiMap<i64, String>,
|
||||
pub queued_events: StatefulTable<QueueEvent>,
|
||||
@@ -51,6 +52,7 @@ impl Default for SonarrData {
|
||||
history: StatefulTable::default(),
|
||||
indexers: StatefulTable::default(),
|
||||
indexer_settings: None,
|
||||
indexer_test_error: None,
|
||||
logs: StatefulList::default(),
|
||||
quality_profile_map: BiMap::new(),
|
||||
queued_events: StatefulTable::default(),
|
||||
|
||||
@@ -41,6 +41,7 @@ mod tests {
|
||||
assert!(sonarr_data.history.is_empty());
|
||||
assert!(sonarr_data.indexers.is_empty());
|
||||
assert!(sonarr_data.indexer_settings.is_none());
|
||||
assert!(sonarr_data.indexer_test_error.is_none());
|
||||
assert!(sonarr_data.logs.is_empty());
|
||||
assert!(sonarr_data.quality_profile_map.is_empty());
|
||||
assert!(sonarr_data.queued_events.is_empty());
|
||||
|
||||
@@ -256,7 +256,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.await
|
||||
.map(RadarrSerdeable::from),
|
||||
RadarrEvent::TestIndexer(indexer_id) => self
|
||||
.test_indexer(indexer_id)
|
||||
.test_radarr_indexer(indexer_id)
|
||||
.await
|
||||
.map(RadarrSerdeable::from),
|
||||
RadarrEvent::TestAllIndexers => self.test_all_indexers().await.map(RadarrSerdeable::from),
|
||||
@@ -2036,7 +2036,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn test_indexer(&mut self, indexer_id: Option<i64>) -> Result<Value> {
|
||||
async fn test_radarr_indexer(&mut self, indexer_id: Option<i64>) -> Result<Value> {
|
||||
let detail_event = RadarrEvent::GetIndexers;
|
||||
let event = RadarrEvent::TestIndexer(None);
|
||||
let id = if let Some(i_id) = indexer_id {
|
||||
|
||||
@@ -862,7 +862,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_test_indexer_event_error() {
|
||||
async fn test_handle_test_radarr_indexer_event_error() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
@@ -938,7 +938,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_test_indexer_event_success() {
|
||||
async fn test_handle_test_radarr_indexer_event_success() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
@@ -1007,7 +1007,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_test_indexer_event_success_uses_provided_id() {
|
||||
async fn test_handle_test_radarr_indexer_event_success_uses_provided_id() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
|
||||
@@ -67,6 +67,7 @@ pub enum SonarrEvent {
|
||||
ListSeries,
|
||||
MarkHistoryItemAsFailed(i64),
|
||||
StartTask(Option<SonarrTaskName>),
|
||||
TestIndexer(Option<i64>),
|
||||
}
|
||||
|
||||
impl NetworkResource for SonarrEvent {
|
||||
@@ -98,6 +99,7 @@ impl NetworkResource for SonarrEvent {
|
||||
SonarrEvent::ListSeries | SonarrEvent::GetSeriesDetails(_) => "/series",
|
||||
SonarrEvent::MarkHistoryItemAsFailed(_) => "/history/failed",
|
||||
SonarrEvent::StartTask(_) => "/command",
|
||||
SonarrEvent::TestIndexer(_) => "/indexer/test",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,6 +226,10 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.start_sonarr_task(task_name)
|
||||
.await
|
||||
.map(SonarrSerdeable::from),
|
||||
SonarrEvent::TestIndexer(indexer_id) => self
|
||||
.test_sonarr_indexer(indexer_id)
|
||||
.await
|
||||
.map(SonarrSerdeable::from),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1311,6 +1317,65 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn test_sonarr_indexer(&mut self, indexer_id: Option<i64>) -> Result<Value> {
|
||||
let detail_event = SonarrEvent::GetIndexers;
|
||||
let event = SonarrEvent::TestIndexer(None);
|
||||
let id = if let Some(i_id) = indexer_id {
|
||||
i_id
|
||||
} else {
|
||||
self
|
||||
.app
|
||||
.lock()
|
||||
.await
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexers
|
||||
.current_selection()
|
||||
.id
|
||||
};
|
||||
info!("Testing Sonarr indexer with ID: {id}");
|
||||
|
||||
info!("Fetching indexer details for indexer with ID: {id}");
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(
|
||||
detail_event,
|
||||
RequestMethod::Get,
|
||||
None::<()>,
|
||||
Some(format!("/{id}")),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut test_body: Value = Value::default();
|
||||
|
||||
self
|
||||
.handle_request::<(), Value>(request_props, |detailed_indexer_body, _| {
|
||||
test_body = detailed_indexer_body;
|
||||
})
|
||||
.await?;
|
||||
|
||||
info!("Testing indexer");
|
||||
|
||||
let mut request_props = self
|
||||
.request_props_from(event, RequestMethod::Post, Some(test_body), None, None)
|
||||
.await;
|
||||
request_props.ignore_status_code = true;
|
||||
|
||||
self
|
||||
.handle_request::<Value, Value>(request_props, |test_results, mut app| {
|
||||
if test_results.as_object().is_none() {
|
||||
app.data.sonarr_data.indexer_test_error = Some(
|
||||
test_results.as_array().unwrap()[0]
|
||||
.get("errorMessage")
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
);
|
||||
};
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn extract_series_id(&mut self, series_id: Option<i64>) -> (i64, String) {
|
||||
let series_id = if let Some(id) = series_id {
|
||||
id
|
||||
|
||||
@@ -5,6 +5,7 @@ mod test {
|
||||
use bimap::BiMap;
|
||||
use chrono::{DateTime, Utc};
|
||||
use indoc::formatdoc;
|
||||
use mockito::Matcher;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use reqwest::Client;
|
||||
use rstest::rstest;
|
||||
@@ -223,6 +224,7 @@ mod test {
|
||||
#[case(SonarrEvent::GetTasks, "/system/task")]
|
||||
#[case(SonarrEvent::GetUpdates, "/update")]
|
||||
#[case(SonarrEvent::MarkHistoryItemAsFailed(0), "/history/failed")]
|
||||
#[case(SonarrEvent::TestIndexer(None), "/indexer/test")]
|
||||
fn test_resource(#[case] event: SonarrEvent, #[case] expected_uri: String) {
|
||||
assert_str_eq!(event.resource(), expected_uri);
|
||||
}
|
||||
@@ -3923,6 +3925,209 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_test_sonarr_indexer_event_error() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
"enableInteractiveSearch": true,
|
||||
"name": "Test Indexer",
|
||||
"fields": [
|
||||
{
|
||||
"name": "baseUrl",
|
||||
"value": "https://test.com",
|
||||
},
|
||||
{
|
||||
"name": "apiKey",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"name": "seedCriteria.seedRatio",
|
||||
"value": "1.2",
|
||||
},
|
||||
],
|
||||
"tags": [1],
|
||||
"id": 1
|
||||
});
|
||||
let response_json = json!([
|
||||
{
|
||||
"isWarning": false,
|
||||
"propertyName": "",
|
||||
"errorMessage": "test failure",
|
||||
"severity": "error"
|
||||
}]);
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json.clone()),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_test_server = server
|
||||
.mock(
|
||||
"POST",
|
||||
format!("/api/v3{}", SonarrEvent::TestIndexer(None).resource()).as_str(),
|
||||
)
|
||||
.with_status(400)
|
||||
.match_header("X-Api-Key", "test1234")
|
||||
.match_body(Matcher::Json(indexer_details_json.clone()))
|
||||
.with_body(response_json.to_string())
|
||||
.create_async()
|
||||
.await;
|
||||
app_arc
|
||||
.lock()
|
||||
.await
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexers
|
||||
.set_items(vec![indexer()]);
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
if let SonarrSerdeable::Value(value) = network
|
||||
.handle_sonarr_event(SonarrEvent::TestIndexer(None))
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
async_details_server.assert_async().await;
|
||||
async_test_server.assert_async().await;
|
||||
assert_eq!(
|
||||
app_arc.lock().await.data.sonarr_data.indexer_test_error,
|
||||
Some("\"test failure\"".to_owned())
|
||||
);
|
||||
assert_eq!(value, response_json)
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_test_sonarr_indexer_event_success() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
"enableInteractiveSearch": true,
|
||||
"name": "Test Indexer",
|
||||
"fields": [
|
||||
{
|
||||
"name": "baseUrl",
|
||||
"value": "https://test.com",
|
||||
},
|
||||
{
|
||||
"name": "apiKey",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"name": "seedCriteria.seedRatio",
|
||||
"value": "1.2",
|
||||
},
|
||||
],
|
||||
"tags": [1],
|
||||
"id": 1
|
||||
});
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json.clone()),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_test_server = server
|
||||
.mock(
|
||||
"POST",
|
||||
format!("/api/v3{}", SonarrEvent::TestIndexer(None).resource()).as_str(),
|
||||
)
|
||||
.with_status(200)
|
||||
.match_header("X-Api-Key", "test1234")
|
||||
.match_body(Matcher::Json(indexer_details_json.clone()))
|
||||
.with_body("{}")
|
||||
.create_async()
|
||||
.await;
|
||||
app_arc
|
||||
.lock()
|
||||
.await
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexers
|
||||
.set_items(vec![indexer()]);
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
if let SonarrSerdeable::Value(value) = network
|
||||
.handle_sonarr_event(SonarrEvent::TestIndexer(None))
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
async_details_server.assert_async().await;
|
||||
async_test_server.assert_async().await;
|
||||
assert_eq!(
|
||||
app_arc.lock().await.data.sonarr_data.indexer_test_error,
|
||||
None
|
||||
);
|
||||
assert_eq!(value, json!({}));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_test_sonarr_indexer_event_success_uses_provided_id() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
"enableInteractiveSearch": true,
|
||||
"name": "Test Indexer",
|
||||
"fields": [
|
||||
{
|
||||
"name": "baseUrl",
|
||||
"value": "https://test.com",
|
||||
},
|
||||
{
|
||||
"name": "apiKey",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"name": "seedCriteria.seedRatio",
|
||||
"value": "1.2",
|
||||
},
|
||||
],
|
||||
"tags": [1],
|
||||
"id": 1
|
||||
});
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json.clone()),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_test_server = server
|
||||
.mock(
|
||||
"POST",
|
||||
format!("/api/v3{}", SonarrEvent::TestIndexer(None).resource()).as_str(),
|
||||
)
|
||||
.with_status(200)
|
||||
.match_header("X-Api-Key", "test1234")
|
||||
.match_body(Matcher::Json(indexer_details_json.clone()))
|
||||
.with_body("{}")
|
||||
.create_async()
|
||||
.await;
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
if let SonarrSerdeable::Value(value) = network
|
||||
.handle_sonarr_event(SonarrEvent::TestIndexer(Some(1)))
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
async_details_server.assert_async().await;
|
||||
async_test_server.assert_async().await;
|
||||
assert_eq!(value, json!({}));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_series_id() {
|
||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
||||
|
||||
Reference in New Issue
Block a user