feat(network): Support for fetching Sonarr series history for a given series ID
This commit is contained in:
@@ -58,7 +58,6 @@ impl Default for SonarrData {
|
|||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)]
|
||||||
pub enum ActiveSonarrBlock {
|
pub enum ActiveSonarrBlock {
|
||||||
#[default]
|
|
||||||
AddRootFolderPrompt,
|
AddRootFolderPrompt,
|
||||||
AddSeriesAlreadyInLibrary,
|
AddSeriesAlreadyInLibrary,
|
||||||
AddSeriesConfirmPrompt,
|
AddSeriesConfirmPrompt,
|
||||||
@@ -95,6 +94,8 @@ pub enum ActiveSonarrBlock {
|
|||||||
FilterHistoryError,
|
FilterHistoryError,
|
||||||
FilterSeries,
|
FilterSeries,
|
||||||
FilterSeriesError,
|
FilterSeriesError,
|
||||||
|
FilterSeriesHistory,
|
||||||
|
FilterSeriesHistoryError,
|
||||||
History,
|
History,
|
||||||
HistoryDetails,
|
HistoryDetails,
|
||||||
HistorySortPrompt,
|
HistorySortPrompt,
|
||||||
@@ -116,11 +117,15 @@ pub enum ActiveSonarrBlock {
|
|||||||
SearchSeasonError,
|
SearchSeasonError,
|
||||||
SearchSeries,
|
SearchSeries,
|
||||||
SearchSeriesError,
|
SearchSeriesError,
|
||||||
|
SearchSeriesHistory,
|
||||||
|
SearchSeriesHistoryError,
|
||||||
SeasonDetails,
|
SeasonDetails,
|
||||||
SeasonHistory,
|
SeasonHistory,
|
||||||
|
#[default]
|
||||||
Series,
|
Series,
|
||||||
SeriesDetails,
|
SeriesDetails,
|
||||||
SeriesHistory,
|
SeriesHistory,
|
||||||
|
SeriesHistorySortPrompt,
|
||||||
SeriesSortPrompt,
|
SeriesSortPrompt,
|
||||||
System,
|
System,
|
||||||
SystemLogs,
|
SystemLogs,
|
||||||
|
|||||||
@@ -349,6 +349,7 @@ pub enum SonarrSerdeable {
|
|||||||
SecurityConfig(SecurityConfig),
|
SecurityConfig(SecurityConfig),
|
||||||
SeriesVec(Vec<Series>),
|
SeriesVec(Vec<Series>),
|
||||||
Series(Series),
|
Series(Series),
|
||||||
|
SonarrHistoryItems(Vec<SonarrHistoryItem>),
|
||||||
SonarrHistoryWrapper(SonarrHistoryWrapper),
|
SonarrHistoryWrapper(SonarrHistoryWrapper),
|
||||||
SystemStatus(SystemStatus),
|
SystemStatus(SystemStatus),
|
||||||
BlocklistResponse(BlocklistResponse),
|
BlocklistResponse(BlocklistResponse),
|
||||||
@@ -382,6 +383,7 @@ serde_enum_from!(
|
|||||||
SecurityConfig(SecurityConfig),
|
SecurityConfig(SecurityConfig),
|
||||||
SeriesVec(Vec<Series>),
|
SeriesVec(Vec<Series>),
|
||||||
Series(Series),
|
Series(Series),
|
||||||
|
SonarrHistoryItems(Vec<SonarrHistoryItem>),
|
||||||
SonarrHistoryWrapper(SonarrHistoryWrapper),
|
SonarrHistoryWrapper(SonarrHistoryWrapper),
|
||||||
SystemStatus(SystemStatus),
|
SystemStatus(SystemStatus),
|
||||||
BlocklistResponse(BlocklistResponse),
|
BlocklistResponse(BlocklistResponse),
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ mod tests {
|
|||||||
},
|
},
|
||||||
sonarr_models::{
|
sonarr_models::{
|
||||||
BlocklistItem, BlocklistResponse, DownloadRecord, DownloadsResponse, Episode,
|
BlocklistItem, BlocklistResponse, DownloadRecord, DownloadsResponse, Episode,
|
||||||
IndexerSettings, Series, SeriesStatus, SeriesType, SonarrHistoryItem, SonarrHistoryWrapper,
|
IndexerSettings, Series, SeriesStatus, SeriesType, SonarrHistoryItem, SonarrSerdeable,
|
||||||
SonarrSerdeable, SystemStatus,
|
SystemStatus,
|
||||||
},
|
},
|
||||||
Serdeable,
|
Serdeable,
|
||||||
};
|
};
|
||||||
@@ -169,18 +169,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sonarr_serdeable_from_sonarr_history_wrapper() {
|
fn test_sonarr_serdeable_from_sonarr_history_items() {
|
||||||
let history_wrapper = SonarrHistoryWrapper {
|
let history_items = vec![SonarrHistoryItem {
|
||||||
records: vec![SonarrHistoryItem {
|
id: 1,
|
||||||
id: 1,
|
..SonarrHistoryItem::default()
|
||||||
..SonarrHistoryItem::default()
|
}];
|
||||||
}],
|
let sonarr_serdeable: SonarrSerdeable = history_items.clone().into();
|
||||||
};
|
|
||||||
let sonarr_serdeable: SonarrSerdeable = history_wrapper.clone().into();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sonarr_serdeable,
|
sonarr_serdeable,
|
||||||
SonarrSerdeable::SonarrHistoryWrapper(history_wrapper)
|
SonarrSerdeable::SonarrHistoryItems(history_items)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
sonarr_models::{
|
sonarr_models::{
|
||||||
BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, Series,
|
BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, Series,
|
||||||
SonarrHistoryWrapper, SonarrSerdeable, SystemStatus,
|
SonarrHistoryItem, SonarrHistoryWrapper, SonarrSerdeable, SystemStatus,
|
||||||
},
|
},
|
||||||
|
stateful_table::StatefulTable,
|
||||||
HorizontallyScrollableText, Route, Scrollable, ScrollableText,
|
HorizontallyScrollableText, Route, Scrollable, ScrollableText,
|
||||||
},
|
},
|
||||||
network::RequestMethod,
|
network::RequestMethod,
|
||||||
@@ -46,6 +47,7 @@ pub enum SonarrEvent {
|
|||||||
GetSeasonReleases(Option<(i64, i64)>),
|
GetSeasonReleases(Option<(i64, i64)>),
|
||||||
GetSecurityConfig,
|
GetSecurityConfig,
|
||||||
GetSeriesDetails(Option<i64>),
|
GetSeriesDetails(Option<i64>),
|
||||||
|
GetSeriesHistory(Option<i64>),
|
||||||
GetStatus,
|
GetStatus,
|
||||||
HealthCheck,
|
HealthCheck,
|
||||||
ListSeries,
|
ListSeries,
|
||||||
@@ -67,6 +69,7 @@ impl NetworkResource for SonarrEvent {
|
|||||||
SonarrEvent::GetQualityProfiles => "/qualityprofile",
|
SonarrEvent::GetQualityProfiles => "/qualityprofile",
|
||||||
SonarrEvent::GetQueuedEvents => "/command",
|
SonarrEvent::GetQueuedEvents => "/command",
|
||||||
SonarrEvent::GetSeasonReleases(_) | SonarrEvent::GetEpisodeReleases(_) => "/release",
|
SonarrEvent::GetSeasonReleases(_) | SonarrEvent::GetEpisodeReleases(_) => "/release",
|
||||||
|
SonarrEvent::GetSeriesHistory(_) => "/history/series",
|
||||||
SonarrEvent::GetStatus => "/system/status",
|
SonarrEvent::GetStatus => "/system/status",
|
||||||
SonarrEvent::HealthCheck => "/health",
|
SonarrEvent::HealthCheck => "/health",
|
||||||
SonarrEvent::ListSeries | SonarrEvent::GetSeriesDetails(_) => "/series",
|
SonarrEvent::ListSeries | SonarrEvent::GetSeriesDetails(_) => "/series",
|
||||||
@@ -145,6 +148,10 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.get_series_details(series_id)
|
.get_series_details(series_id)
|
||||||
.await
|
.await
|
||||||
.map(SonarrSerdeable::from),
|
.map(SonarrSerdeable::from),
|
||||||
|
SonarrEvent::GetSeriesHistory(series_id) => self
|
||||||
|
.get_sonarr_series_history(series_id)
|
||||||
|
.await
|
||||||
|
.map(SonarrSerdeable::from),
|
||||||
SonarrEvent::GetStatus => self.get_sonarr_status().await.map(SonarrSerdeable::from),
|
SonarrEvent::GetStatus => self.get_sonarr_status().await.map(SonarrSerdeable::from),
|
||||||
SonarrEvent::HealthCheck => self
|
SonarrEvent::HealthCheck => self
|
||||||
.get_sonarr_healthcheck()
|
.get_sonarr_healthcheck()
|
||||||
@@ -726,6 +733,54 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_sonarr_series_history(
|
||||||
|
&mut self,
|
||||||
|
series_id: Option<i64>,
|
||||||
|
) -> Result<Vec<SonarrHistoryItem>> {
|
||||||
|
let (id, series_id_param) = self.extract_series_id(series_id).await;
|
||||||
|
info!("Fetching Sonarr series history for series with ID: {id}");
|
||||||
|
let event = SonarrEvent::GetSeriesHistory(series_id);
|
||||||
|
|
||||||
|
let request_props = self
|
||||||
|
.request_props_from(
|
||||||
|
event,
|
||||||
|
RequestMethod::Get,
|
||||||
|
None::<()>,
|
||||||
|
None,
|
||||||
|
Some(series_id_param),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self
|
||||||
|
.handle_request::<(), Vec<SonarrHistoryItem>>(request_props, |mut history_vec, mut app| {
|
||||||
|
if app.data.sonarr_data.series_history.is_none() {
|
||||||
|
app.data.sonarr_data.series_history = Some(StatefulTable::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matches!(
|
||||||
|
app.get_current_route(),
|
||||||
|
Route::Sonarr(ActiveSonarrBlock::SeriesHistorySortPrompt, _)
|
||||||
|
) {
|
||||||
|
history_vec.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.set_items(history_vec);
|
||||||
|
app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.apply_sorting_toggle(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn list_series(&mut self) -> Result<Vec<Series>> {
|
async fn list_series(&mut self) -> Result<Vec<Series>> {
|
||||||
info!("Fetching Sonarr library");
|
info!("Fetching Sonarr library");
|
||||||
let event = SonarrEvent::ListSeries;
|
let event = SonarrEvent::ListSeries;
|
||||||
|
|||||||
@@ -155,6 +155,11 @@ mod test {
|
|||||||
assert_str_eq!(event.resource(), "/indexer");
|
assert_str_eq!(event.resource(), "/indexer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_resource_history(#[values(SonarrEvent::GetSeriesHistory(None))] event: SonarrEvent) {
|
||||||
|
assert_str_eq!(event.resource(), "/history/series");
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_resource_release(
|
fn test_resource_release(
|
||||||
#[values(
|
#[values(
|
||||||
@@ -999,7 +1004,6 @@ mod test {
|
|||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
.cmp(&b.source_title.text.to_lowercase())
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
};
|
};
|
||||||
|
|
||||||
let history_sort_option = SortOption {
|
let history_sort_option = SortOption {
|
||||||
name: "Source Title",
|
name: "Source Title",
|
||||||
cmp_fn: Some(cmp_fn),
|
cmp_fn: Some(cmp_fn),
|
||||||
@@ -2211,6 +2215,444 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_sonarr_series_history_event(
|
||||||
|
#[values(true, false)] use_custom_sorting: bool,
|
||||||
|
) {
|
||||||
|
let history_json = json!([{
|
||||||
|
"id": 123,
|
||||||
|
"sourceTitle": "z episode",
|
||||||
|
"episodeId": 1007,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 456,
|
||||||
|
"sourceTitle": "A Episode",
|
||||||
|
"episodeId": 2001,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
let response: Vec<SonarrHistoryItem> = serde_json::from_value(history_json.clone()).unwrap();
|
||||||
|
let mut expected_history_items = vec![
|
||||||
|
SonarrHistoryItem {
|
||||||
|
id: 123,
|
||||||
|
episode_id: 1007,
|
||||||
|
source_title: "z episode".into(),
|
||||||
|
..history_item()
|
||||||
|
},
|
||||||
|
SonarrHistoryItem {
|
||||||
|
id: 456,
|
||||||
|
episode_id: 2001,
|
||||||
|
source_title: "A Episode".into(),
|
||||||
|
..history_item()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(history_json),
|
||||||
|
None,
|
||||||
|
SonarrEvent::GetSeriesHistory(None),
|
||||||
|
None,
|
||||||
|
Some("seriesId=1"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let mut series_history_table = StatefulTable {
|
||||||
|
sort_asc: true,
|
||||||
|
..StatefulTable::default()
|
||||||
|
};
|
||||||
|
if use_custom_sorting {
|
||||||
|
let cmp_fn = |a: &SonarrHistoryItem, b: &SonarrHistoryItem| {
|
||||||
|
a.source_title
|
||||||
|
.text
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
|
};
|
||||||
|
expected_history_items.sort_by(cmp_fn);
|
||||||
|
|
||||||
|
let history_sort_option = SortOption {
|
||||||
|
name: "Source Title",
|
||||||
|
cmp_fn: Some(cmp_fn),
|
||||||
|
};
|
||||||
|
series_history_table.sorting(vec![history_sort_option]);
|
||||||
|
}
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series
|
||||||
|
.set_items(vec![series()]);
|
||||||
|
app_arc.lock().await.data.sonarr_data.series_history = Some(series_history_table);
|
||||||
|
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||||
|
|
||||||
|
if let SonarrSerdeable::SonarrHistoryItems(history_items) = network
|
||||||
|
.handle_sonarr_event(SonarrEvent::GetSeriesHistory(None))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert!(app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.items,
|
||||||
|
expected_history_items
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.sort_asc
|
||||||
|
);
|
||||||
|
assert_eq!(history_items, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_sonarr_series_history_event_uses_provided_series_id() {
|
||||||
|
let history_json = json!([{
|
||||||
|
"id": 123,
|
||||||
|
"sourceTitle": "z episode",
|
||||||
|
"episodeId": 1007,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 456,
|
||||||
|
"sourceTitle": "A Episode",
|
||||||
|
"episodeId": 2001,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
let response: Vec<SonarrHistoryItem> = serde_json::from_value(history_json.clone()).unwrap();
|
||||||
|
let expected_history_items = vec![
|
||||||
|
SonarrHistoryItem {
|
||||||
|
id: 123,
|
||||||
|
episode_id: 1007,
|
||||||
|
source_title: "z episode".into(),
|
||||||
|
..history_item()
|
||||||
|
},
|
||||||
|
SonarrHistoryItem {
|
||||||
|
id: 456,
|
||||||
|
episode_id: 2001,
|
||||||
|
source_title: "A Episode".into(),
|
||||||
|
..history_item()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(history_json),
|
||||||
|
None,
|
||||||
|
SonarrEvent::GetSeriesHistory(Some(2)),
|
||||||
|
None,
|
||||||
|
Some("seriesId=2"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
app_arc.lock().await.data.sonarr_data.series_history = Some(StatefulTable {
|
||||||
|
sort_asc: true,
|
||||||
|
..StatefulTable::default()
|
||||||
|
});
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series
|
||||||
|
.set_items(vec![series()]);
|
||||||
|
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||||
|
|
||||||
|
if let SonarrSerdeable::SonarrHistoryItems(history_items) = network
|
||||||
|
.handle_sonarr_event(SonarrEvent::GetSeriesHistory(Some(2)))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert!(app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.items,
|
||||||
|
expected_history_items
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.sort_asc
|
||||||
|
);
|
||||||
|
assert_eq!(history_items, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_sonarr_series_history_event_empty_series_history_table() {
|
||||||
|
let history_json = json!([{
|
||||||
|
"id": 123,
|
||||||
|
"sourceTitle": "z episode",
|
||||||
|
"episodeId": 1007,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 456,
|
||||||
|
"sourceTitle": "A Episode",
|
||||||
|
"episodeId": 2001,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
let response: Vec<SonarrHistoryItem> = serde_json::from_value(history_json.clone()).unwrap();
|
||||||
|
let expected_history_items = vec![
|
||||||
|
SonarrHistoryItem {
|
||||||
|
id: 123,
|
||||||
|
episode_id: 1007,
|
||||||
|
source_title: "z episode".into(),
|
||||||
|
..history_item()
|
||||||
|
},
|
||||||
|
SonarrHistoryItem {
|
||||||
|
id: 456,
|
||||||
|
episode_id: 2001,
|
||||||
|
source_title: "A Episode".into(),
|
||||||
|
..history_item()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(history_json),
|
||||||
|
None,
|
||||||
|
SonarrEvent::GetSeriesHistory(None),
|
||||||
|
None,
|
||||||
|
Some("seriesId=1"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series
|
||||||
|
.set_items(vec![series()]);
|
||||||
|
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||||
|
|
||||||
|
if let SonarrSerdeable::SonarrHistoryItems(history_items) = network
|
||||||
|
.handle_sonarr_event(SonarrEvent::GetSeriesHistory(None))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert!(app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.items,
|
||||||
|
expected_history_items
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.sort_asc
|
||||||
|
);
|
||||||
|
assert_eq!(history_items, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_sonarr_series_history_event_no_op_when_user_is_selecting_sort_options() {
|
||||||
|
let history_json = json!([{
|
||||||
|
"id": 123,
|
||||||
|
"sourceTitle": "z episode",
|
||||||
|
"episodeId": 1007,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 456,
|
||||||
|
"sourceTitle": "A Episode",
|
||||||
|
"episodeId": 2001,
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" } },
|
||||||
|
"languages": [{"name": "English"}],
|
||||||
|
"date": "2024-02-10T07:28:45Z",
|
||||||
|
"eventType": "grabbed",
|
||||||
|
"data": {
|
||||||
|
"droppedPath": "/nfs/nzbget/completed/series/Coolness/something.cool.mkv",
|
||||||
|
"importedPath": "/nfs/tv/Coolness/Season 1/Coolness - S01E01 - Something Cool Bluray-1080p.mkv"
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
let response: Vec<SonarrHistoryItem> = serde_json::from_value(history_json.clone()).unwrap();
|
||||||
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(history_json),
|
||||||
|
None,
|
||||||
|
SonarrEvent::GetSeriesHistory(None),
|
||||||
|
None,
|
||||||
|
Some("seriesId=1"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let cmp_fn = |a: &SonarrHistoryItem, b: &SonarrHistoryItem| {
|
||||||
|
a.source_title
|
||||||
|
.text
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.source_title.text.to_lowercase())
|
||||||
|
};
|
||||||
|
let history_sort_option = SortOption {
|
||||||
|
name: "Source Title",
|
||||||
|
cmp_fn: Some(cmp_fn),
|
||||||
|
};
|
||||||
|
let mut series_history_table = StatefulTable {
|
||||||
|
sort_asc: true,
|
||||||
|
..StatefulTable::default()
|
||||||
|
};
|
||||||
|
series_history_table.sorting(vec![history_sort_option]);
|
||||||
|
app_arc.lock().await.data.sonarr_data.series_history = Some(series_history_table);
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series
|
||||||
|
.set_items(vec![series()]);
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.push_navigation_stack(ActiveSonarrBlock::SeriesHistorySortPrompt.into());
|
||||||
|
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||||
|
|
||||||
|
if let SonarrSerdeable::SonarrHistoryItems(history_items) = network
|
||||||
|
.handle_sonarr_event(SonarrEvent::GetSeriesHistory(None))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert!(app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.is_some());
|
||||||
|
assert!(app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.is_empty());
|
||||||
|
assert!(
|
||||||
|
app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.sort_asc
|
||||||
|
);
|
||||||
|
assert_eq!(history_items, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_series_event_no_op_while_user_is_selecting_sort_options() {
|
async fn test_handle_get_series_event_no_op_while_user_is_selecting_sort_options() {
|
||||||
let mut series_1: Value = serde_json::from_str(SERIES_JSON).unwrap();
|
let mut series_1: Value = serde_json::from_str(SERIES_JSON).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user