feat(app): Dispatch support for all relevant Sonarr blocks
This commit is contained in:
+15
-26
@@ -5,9 +5,9 @@ mod tests {
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES};
|
||||
use crate::app::{App, AppConfig, Data, ServarrConfig, DEFAULT_ROUTE};
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData};
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData};
|
||||
use crate::app::{App, AppConfig, ServarrConfig, DEFAULT_ROUTE};
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
||||
use crate::models::{HorizontallyScrollableText, TabRoute};
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use crate::network::NetworkEvent;
|
||||
@@ -19,6 +19,7 @@ mod tests {
|
||||
assert_eq!(app.navigation_stack, vec![DEFAULT_ROUTE]);
|
||||
assert!(app.network_tx.is_none());
|
||||
assert!(!app.cancellation_token.is_cancelled());
|
||||
assert!(app.is_first_render);
|
||||
assert_eq!(app.error, HorizontallyScrollableText::default());
|
||||
assert_eq!(app.server_tabs.index, 0);
|
||||
assert_eq!(
|
||||
@@ -55,14 +56,11 @@ mod tests {
|
||||
fn test_navigation_stack_methods() {
|
||||
let mut app = App::default();
|
||||
|
||||
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
|
||||
assert_eq!(app.get_current_route(), DEFAULT_ROUTE);
|
||||
|
||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
&ActiveRadarrBlock::Downloads.into()
|
||||
);
|
||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into());
|
||||
assert!(app.is_routing);
|
||||
|
||||
app.is_routing = false;
|
||||
@@ -70,20 +68,20 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
&ActiveRadarrBlock::Collections.into()
|
||||
ActiveRadarrBlock::Collections.into()
|
||||
);
|
||||
assert!(app.is_routing);
|
||||
|
||||
app.is_routing = false;
|
||||
app.pop_navigation_stack();
|
||||
|
||||
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
|
||||
assert_eq!(app.get_current_route(), DEFAULT_ROUTE);
|
||||
assert!(app.is_routing);
|
||||
|
||||
app.is_routing = false;
|
||||
app.pop_navigation_stack();
|
||||
|
||||
assert_eq!(app.get_current_route(), &DEFAULT_ROUTE);
|
||||
assert_eq!(app.get_current_route(), DEFAULT_ROUTE);
|
||||
assert!(app.is_routing);
|
||||
}
|
||||
|
||||
@@ -123,16 +121,7 @@ mod tests {
|
||||
let mut app = App {
|
||||
tick_count: 2,
|
||||
error: "Test error".to_owned().into(),
|
||||
data: Data {
|
||||
radarr_data: RadarrData {
|
||||
version: "test".to_owned(),
|
||||
..RadarrData::default()
|
||||
},
|
||||
sonarr_data: SonarrData {
|
||||
version: "test".to_owned(),
|
||||
..SonarrData::default()
|
||||
},
|
||||
},
|
||||
is_first_render: false,
|
||||
..App::default()
|
||||
};
|
||||
|
||||
@@ -140,8 +129,7 @@ mod tests {
|
||||
|
||||
assert_eq!(app.tick_count, 0);
|
||||
assert_eq!(app.error, HorizontallyScrollableText::default());
|
||||
assert!(app.data.radarr_data.version.is_empty());
|
||||
assert!(app.data.sonarr_data.version.is_empty());
|
||||
assert!(app.is_first_render);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -188,12 +176,13 @@ mod tests {
|
||||
let mut app = App {
|
||||
tick_until_poll: 2,
|
||||
network_tx: Some(sync_network_tx),
|
||||
is_first_render: true,
|
||||
..App::default()
|
||||
};
|
||||
|
||||
assert_eq!(app.tick_count, 0);
|
||||
|
||||
app.on_tick(true).await;
|
||||
app.on_tick().await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -237,7 +226,7 @@ mod tests {
|
||||
..App::default()
|
||||
};
|
||||
|
||||
app.on_tick(false).await;
|
||||
app.on_tick().await;
|
||||
assert!(!app.is_routing);
|
||||
}
|
||||
|
||||
@@ -250,7 +239,7 @@ mod tests {
|
||||
..App::default()
|
||||
};
|
||||
|
||||
app.on_tick(false).await;
|
||||
app.on_tick().await;
|
||||
assert!(!app.should_refresh);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,3 +21,58 @@ pub static SERVARR_CONTEXT_CLUES: [ContextClue; 2] = [
|
||||
|
||||
pub static BARE_POPUP_CONTEXT_CLUES: [ContextClue; 1] =
|
||||
[(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc)];
|
||||
|
||||
pub static BLOCKLIST_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(DEFAULT_KEYBINDINGS.clear, "clear blocklist"),
|
||||
];
|
||||
|
||||
pub static DOWNLOADS_CONTEXT_CLUES: [ContextClue; 3] = [
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(DEFAULT_KEYBINDINGS.update, "update downloads"),
|
||||
];
|
||||
|
||||
pub static ROOT_FOLDERS_CONTEXT_CLUES: [ContextClue; 3] = [
|
||||
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
];
|
||||
|
||||
pub static INDEXERS_CONTEXT_CLUES: [ContextClue; 6] = [
|
||||
(DEFAULT_KEYBINDINGS.submit, "edit indexer"),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.settings,
|
||||
DEFAULT_KEYBINDINGS.settings.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(DEFAULT_KEYBINDINGS.test, "test indexer"),
|
||||
(DEFAULT_KEYBINDINGS.test_all, "test all indexers"),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
];
|
||||
|
||||
pub static SYSTEM_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||
(DEFAULT_KEYBINDINGS.tasks, "open tasks"),
|
||||
(DEFAULT_KEYBINDINGS.events, "open events"),
|
||||
(DEFAULT_KEYBINDINGS.logs, "open logs"),
|
||||
(DEFAULT_KEYBINDINGS.update, "open updates"),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
mod test {
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
|
||||
use crate::app::context_clues::{BARE_POPUP_CONTEXT_CLUES, SERVARR_CONTEXT_CLUES};
|
||||
use crate::app::context_clues::{
|
||||
BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES,
|
||||
INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SERVARR_CONTEXT_CLUES,
|
||||
SYSTEM_CONTEXT_CLUES,
|
||||
};
|
||||
use crate::app::{context_clues::build_context_clue_string, key_binding::DEFAULT_KEYBINDINGS};
|
||||
|
||||
#[test]
|
||||
@@ -44,4 +48,144 @@ mod test {
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||
assert_eq!(bare_popup_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_downloads_context_clues() {
|
||||
let mut downloads_context_clues_iter = DOWNLOADS_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = downloads_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
|
||||
let (key_binding, description) = downloads_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = downloads_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update);
|
||||
assert_str_eq!(*description, "update downloads");
|
||||
assert_eq!(downloads_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blocklist_context_clues() {
|
||||
let mut blocklist_context_clues_iter = BLOCKLIST_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||
assert_str_eq!(*description, "details");
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.clear);
|
||||
assert_str_eq!(*description, "clear blocklist");
|
||||
assert_eq!(blocklist_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root_folders_context_clues() {
|
||||
let mut root_folders_context_clues_iter = ROOT_FOLDERS_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = root_folders_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.add);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.add.desc);
|
||||
|
||||
let (key_binding, description) = root_folders_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = root_folders_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
assert_eq!(root_folders_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_indexers_context_clues() {
|
||||
let mut indexers_context_clues_iter = INDEXERS_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||
assert_str_eq!(*description, "edit indexer");
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.settings);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.settings.desc);
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.test);
|
||||
assert_str_eq!(*description, "test indexer");
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.test_all);
|
||||
assert_str_eq!(*description, "test all indexers");
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
assert_eq!(indexers_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_context_clues() {
|
||||
let mut system_context_clues_iter = SYSTEM_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.tasks);
|
||||
assert_str_eq!(*description, "open tasks");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.events);
|
||||
assert_str_eq!(*description, "open events");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.logs);
|
||||
assert_str_eq!(*description, "open logs");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update);
|
||||
assert_str_eq!(*description, "open updates");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
assert_eq!(system_context_clues_iter.next(), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ generate_keybindings! {
|
||||
left,
|
||||
right,
|
||||
backspace,
|
||||
next_servarr,
|
||||
previous_servarr,
|
||||
clear,
|
||||
search,
|
||||
settings,
|
||||
@@ -69,6 +71,14 @@ pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings {
|
||||
key: Key::Backspace,
|
||||
desc: "backspace",
|
||||
},
|
||||
next_servarr: KeyBinding {
|
||||
key: Key::Tab,
|
||||
desc: "next servarr",
|
||||
},
|
||||
previous_servarr: KeyBinding {
|
||||
key: Key::BackTab,
|
||||
desc: "previous servarr",
|
||||
},
|
||||
clear: KeyBinding {
|
||||
key: Key::Char('c'),
|
||||
desc: "clear",
|
||||
|
||||
@@ -13,6 +13,8 @@ mod test {
|
||||
#[case(DEFAULT_KEYBINDINGS.left, Key::Left, "left")]
|
||||
#[case(DEFAULT_KEYBINDINGS.right, Key::Right, "right")]
|
||||
#[case(DEFAULT_KEYBINDINGS.backspace, Key::Backspace, "backspace")]
|
||||
#[case(DEFAULT_KEYBINDINGS.next_servarr, Key::Tab, "next servarr")]
|
||||
#[case(DEFAULT_KEYBINDINGS.previous_servarr, Key::BackTab, "previous servarr")]
|
||||
#[case(DEFAULT_KEYBINDINGS.clear, Key::Char('c'), "clear")]
|
||||
#[case(DEFAULT_KEYBINDINGS.search, Key::Char('s'), "search")]
|
||||
#[case(DEFAULT_KEYBINDINGS.settings, Key::Char('s'), "settings")]
|
||||
|
||||
+14
-11
@@ -1,6 +1,6 @@
|
||||
use std::process;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{anyhow, Error};
|
||||
use colored::Colorize;
|
||||
use log::{debug, error};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -21,6 +21,7 @@ pub mod context_clues;
|
||||
pub mod key_binding;
|
||||
mod key_binding_tests;
|
||||
pub mod radarr;
|
||||
pub mod sonarr;
|
||||
|
||||
const DEFAULT_ROUTE: Route = Route::Radarr(ActiveRadarrBlock::Movies, None);
|
||||
|
||||
@@ -28,6 +29,7 @@ pub struct App<'a> {
|
||||
navigation_stack: Vec<Route>,
|
||||
network_tx: Option<Sender<NetworkEvent>>,
|
||||
cancellation_token: CancellationToken,
|
||||
pub is_first_render: bool,
|
||||
pub server_tabs: TabState,
|
||||
pub error: HorizontallyScrollableText,
|
||||
pub tick_until_poll: u64,
|
||||
@@ -81,21 +83,21 @@ impl<'a> App<'a> {
|
||||
pub fn reset(&mut self) {
|
||||
self.reset_tick_count();
|
||||
self.error = HorizontallyScrollableText::default();
|
||||
self.data = Data::default();
|
||||
self.is_first_render = true;
|
||||
}
|
||||
|
||||
pub fn handle_error(&mut self, error: anyhow::Error) {
|
||||
pub fn handle_error(&mut self, error: Error) {
|
||||
if self.error.text.is_empty() {
|
||||
self.error = error.to_string().into();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn on_tick(&mut self, is_first_render: bool) {
|
||||
pub async fn on_tick(&mut self) {
|
||||
if self.tick_count % self.tick_until_poll == 0 || self.is_routing || self.should_refresh {
|
||||
if let Route::Radarr(active_radarr_block, _) = self.get_current_route() {
|
||||
self
|
||||
.radarr_on_tick(*active_radarr_block, is_first_render)
|
||||
.await;
|
||||
match self.get_current_route() {
|
||||
Route::Radarr(active_radarr_block, _) => self.radarr_on_tick(active_radarr_block).await,
|
||||
Route::Sonarr(active_sonarr_block, _) => self.sonarr_on_tick(active_sonarr_block).await,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.is_routing = false;
|
||||
@@ -130,8 +132,8 @@ impl<'a> App<'a> {
|
||||
self.push_navigation_stack(route);
|
||||
}
|
||||
|
||||
pub fn get_current_route(&self) -> &Route {
|
||||
self.navigation_stack.last().unwrap_or(&DEFAULT_ROUTE)
|
||||
pub fn get_current_route(&self) -> Route {
|
||||
*self.navigation_stack.last().unwrap_or(&DEFAULT_ROUTE)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +144,7 @@ impl<'a> Default for App<'a> {
|
||||
network_tx: None,
|
||||
cancellation_token: CancellationToken::new(),
|
||||
error: HorizontallyScrollableText::default(),
|
||||
is_first_render: true,
|
||||
server_tabs: TabState::new(vec![
|
||||
TabRoute {
|
||||
title: "Radarr",
|
||||
@@ -176,7 +179,7 @@ impl<'a> Default for App<'a> {
|
||||
#[derive(Default)]
|
||||
pub struct Data<'a> {
|
||||
pub radarr_data: RadarrData<'a>,
|
||||
pub sonarr_data: SonarrData,
|
||||
pub sonarr_data: SonarrData<'a>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
||||
|
||||
+10
-13
@@ -119,11 +119,11 @@ impl<'a> App<'a> {
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.check_for_prompt_action().await;
|
||||
self.check_for_radarr_prompt_action().await;
|
||||
self.reset_tick_count();
|
||||
}
|
||||
|
||||
async fn check_for_prompt_action(&mut self) {
|
||||
async fn check_for_radarr_prompt_action(&mut self) {
|
||||
if self.data.radarr_data.prompt_confirm {
|
||||
self.data.radarr_data.prompt_confirm = false;
|
||||
if let Some(radarr_event) = &self.data.radarr_data.prompt_confirm_action {
|
||||
@@ -136,19 +136,16 @@ impl<'a> App<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn radarr_on_tick(
|
||||
&mut self,
|
||||
active_radarr_block: ActiveRadarrBlock,
|
||||
is_first_render: bool,
|
||||
) {
|
||||
if is_first_render {
|
||||
self.refresh_metadata().await;
|
||||
pub(super) async fn radarr_on_tick(&mut self, active_radarr_block: ActiveRadarrBlock) {
|
||||
if self.is_first_render {
|
||||
self.refresh_radarr_metadata().await;
|
||||
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
||||
self.is_first_render = false;
|
||||
}
|
||||
|
||||
if self.should_refresh {
|
||||
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
||||
self.refresh_metadata().await;
|
||||
self.refresh_radarr_metadata().await;
|
||||
}
|
||||
|
||||
if self.is_routing {
|
||||
@@ -156,16 +153,16 @@ impl<'a> App<'a> {
|
||||
self.cancellation_token.cancel();
|
||||
} else {
|
||||
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
||||
self.refresh_metadata().await;
|
||||
self.refresh_radarr_metadata().await;
|
||||
}
|
||||
}
|
||||
|
||||
if self.tick_count % self.tick_until_poll == 0 {
|
||||
self.refresh_metadata().await;
|
||||
self.refresh_radarr_metadata().await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_metadata(&mut self) {
|
||||
async fn refresh_radarr_metadata(&mut self) {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetQualityProfiles.into())
|
||||
.await;
|
||||
|
||||
@@ -35,60 +35,6 @@ pub static COLLECTIONS_CONTEXT_CLUES: [ContextClue; 8] = [
|
||||
(DEFAULT_KEYBINDINGS.esc, "cancel filter"),
|
||||
];
|
||||
|
||||
pub static DOWNLOADS_CONTEXT_CLUES: [ContextClue; 2] = [
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
];
|
||||
|
||||
pub static BLOCKLIST_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(DEFAULT_KEYBINDINGS.clear, "clear blocklist"),
|
||||
];
|
||||
|
||||
pub static ROOT_FOLDERS_CONTEXT_CLUES: [ContextClue; 3] = [
|
||||
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
];
|
||||
|
||||
pub static INDEXERS_CONTEXT_CLUES: [ContextClue; 6] = [
|
||||
(DEFAULT_KEYBINDINGS.submit, "edit indexer"),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.settings,
|
||||
DEFAULT_KEYBINDINGS.settings.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(DEFAULT_KEYBINDINGS.test, "test indexer"),
|
||||
(DEFAULT_KEYBINDINGS.test_all, "test all indexers"),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
];
|
||||
|
||||
pub static SYSTEM_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||
(DEFAULT_KEYBINDINGS.tasks, "open tasks"),
|
||||
(DEFAULT_KEYBINDINGS.events, "open events"),
|
||||
(DEFAULT_KEYBINDINGS.logs, "open logs"),
|
||||
(DEFAULT_KEYBINDINGS.update, "open updates"),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
];
|
||||
|
||||
pub static MOVIE_DETAILS_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
|
||||
@@ -4,11 +4,10 @@ mod tests {
|
||||
|
||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||
use crate::app::radarr::radarr_context_clues::{
|
||||
ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, COLLECTIONS_CONTEXT_CLUES,
|
||||
COLLECTION_DETAILS_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES,
|
||||
INDEXERS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXTUAL_CONTEXT_CLUES,
|
||||
MANUAL_MOVIE_SEARCH_CONTEXT_CLUES, MOVIE_DETAILS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES,
|
||||
SYSTEM_CONTEXT_CLUES, SYSTEM_TASKS_CONTEXT_CLUES,
|
||||
ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, COLLECTIONS_CONTEXT_CLUES,
|
||||
COLLECTION_DETAILS_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES,
|
||||
MANUAL_MOVIE_SEARCH_CONTEXTUAL_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES,
|
||||
MOVIE_DETAILS_CONTEXT_CLUES, SYSTEM_TASKS_CONTEXT_CLUES,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -113,141 +112,6 @@ mod tests {
|
||||
assert_eq!(collections_context_clues.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_downloads_context_clues() {
|
||||
let mut downloads_context_clues_iter = DOWNLOADS_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = downloads_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
|
||||
let (key_binding, description) = downloads_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
assert_eq!(downloads_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blocklist_context_clues() {
|
||||
let mut blocklist_context_clues_iter = BLOCKLIST_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||
assert_str_eq!(*description, "details");
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = blocklist_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.clear);
|
||||
assert_str_eq!(*description, "clear blocklist");
|
||||
assert_eq!(blocklist_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root_folders_context_clues() {
|
||||
let mut root_folders_context_clues_iter = ROOT_FOLDERS_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = root_folders_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.add);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.add.desc);
|
||||
|
||||
let (key_binding, description) = root_folders_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = root_folders_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
assert_eq!(root_folders_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_indexers_context_clues() {
|
||||
let mut indexers_context_clues_iter = INDEXERS_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||
assert_str_eq!(*description, "edit indexer");
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.settings);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.settings.desc);
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.test);
|
||||
assert_str_eq!(*description, "test indexer");
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.test_all);
|
||||
assert_str_eq!(*description, "test all indexers");
|
||||
|
||||
let (key_binding, description) = indexers_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
assert_eq!(indexers_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_context_clues() {
|
||||
let mut system_context_clues_iter = SYSTEM_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.tasks);
|
||||
assert_str_eq!(*description, "open tasks");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.events);
|
||||
assert_str_eq!(*description, "open events");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.logs);
|
||||
assert_str_eq!(*description, "open logs");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update);
|
||||
assert_str_eq!(*description, "open updates");
|
||||
|
||||
let (key_binding, description) = system_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
assert_eq!(system_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_movie_details_context_clues() {
|
||||
let mut movie_details_context_clues_iter = MOVIE_DETAILS_CONTEXT_CLUES.iter();
|
||||
|
||||
@@ -459,22 +459,22 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_for_prompt_action_no_prompt_confirm() {
|
||||
async fn test_check_for_radarr_prompt_action_no_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.radarr_data.prompt_confirm = false;
|
||||
|
||||
app.check_for_prompt_action().await;
|
||||
app.check_for_radarr_prompt_action().await;
|
||||
|
||||
assert!(!app.data.radarr_data.prompt_confirm);
|
||||
assert!(!app.should_refresh);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_for_prompt_action() {
|
||||
async fn test_check_for_radarr_prompt_action() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::GetStatus);
|
||||
|
||||
app.check_for_prompt_action().await;
|
||||
app.check_for_radarr_prompt_action().await;
|
||||
|
||||
assert!(!app.data.radarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
@@ -490,7 +490,7 @@ mod tests {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.is_routing = true;
|
||||
|
||||
app.refresh_metadata().await;
|
||||
app.refresh_radarr_metadata().await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -522,8 +522,9 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_radarr_on_tick_first_render() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.is_first_render = true;
|
||||
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads, true).await;
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -551,6 +552,7 @@ mod tests {
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
assert!(!app.data.radarr_data.prompt_confirm);
|
||||
assert!(!app.is_first_render);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -559,9 +561,7 @@ mod tests {
|
||||
app.is_routing = true;
|
||||
app.should_refresh = true;
|
||||
|
||||
app
|
||||
.radarr_on_tick(ActiveRadarrBlock::Downloads, false)
|
||||
.await;
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -592,9 +592,7 @@ mod tests {
|
||||
app.is_routing = true;
|
||||
app.should_refresh = false;
|
||||
|
||||
app
|
||||
.radarr_on_tick(ActiveRadarrBlock::Downloads, false)
|
||||
.await;
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads).await;
|
||||
|
||||
assert!(app.cancellation_token.is_cancelled());
|
||||
}
|
||||
@@ -604,9 +602,7 @@ mod tests {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.should_refresh = true;
|
||||
|
||||
app
|
||||
.radarr_on_tick(ActiveRadarrBlock::Downloads, false)
|
||||
.await;
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -623,9 +619,7 @@ mod tests {
|
||||
app.is_routing = true;
|
||||
app.should_refresh = true;
|
||||
|
||||
app
|
||||
.radarr_on_tick(ActiveRadarrBlock::Downloads, false)
|
||||
.await;
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -643,9 +637,7 @@ mod tests {
|
||||
app.tick_count = 2;
|
||||
app.tick_until_poll = 2;
|
||||
|
||||
app
|
||||
.radarr_on_tick(ActiveRadarrBlock::Downloads, false)
|
||||
.await;
|
||||
app.radarr_on_tick(ActiveRadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
@@ -701,6 +693,7 @@ mod tests {
|
||||
let mut app = App {
|
||||
network_tx: Some(sync_network_tx),
|
||||
tick_count: 1,
|
||||
is_first_render: false,
|
||||
..App::default()
|
||||
};
|
||||
app.data.radarr_data.prompt_confirm = true;
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
use crate::{
|
||||
models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock,
|
||||
network::sonarr_network::SonarrEvent,
|
||||
};
|
||||
|
||||
use super::App;
|
||||
|
||||
pub mod sonarr_context_clues;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "sonarr_tests.rs"]
|
||||
mod sonarr_tests;
|
||||
|
||||
impl<'a> App<'a> {
|
||||
pub(super) async fn dispatch_by_sonarr_block(&mut self, active_sonarr_block: &ActiveSonarrBlock) {
|
||||
match active_sonarr_block {
|
||||
ActiveSonarrBlock::Series => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::ListSeries.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::SeriesDetails => {
|
||||
self.is_loading = true;
|
||||
self.populate_seasons_table().await;
|
||||
self.is_loading = false;
|
||||
}
|
||||
ActiveSonarrBlock::SeriesHistory => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetSeriesHistory(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::SeasonDetails => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodes(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::ManualSeasonSearch => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetSeasonReleases(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::EpisodeDetails | ActiveSonarrBlock::EpisodeFile => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeDetails(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::EpisodeHistory => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeHistory(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::ManualEpisodeSearch => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetEpisodeReleases(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::Downloads => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::Blocklist => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetBlocklist.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::History => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetHistory(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::RootFolders => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetRootFolders.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::Indexers => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetIndexers.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::AllIndexerSettingsPrompt => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetAllIndexerSettings.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::TestIndexer => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::TestIndexer(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::TestAllIndexers => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::TestAllIndexers.into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::System => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetTasks.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetQueuedEvents.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetLogs(None).into())
|
||||
.await;
|
||||
}
|
||||
ActiveSonarrBlock::SystemUpdates => {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetUpdates.into())
|
||||
.await;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.check_for_sonarr_prompt_action().await;
|
||||
self.reset_tick_count();
|
||||
}
|
||||
|
||||
async fn check_for_sonarr_prompt_action(&mut self) {
|
||||
if self.data.sonarr_data.prompt_confirm {
|
||||
self.data.sonarr_data.prompt_confirm = false;
|
||||
if let Some(sonarr_event) = &self.data.sonarr_data.prompt_confirm_action {
|
||||
self
|
||||
.dispatch_network_event(sonarr_event.clone().into())
|
||||
.await;
|
||||
self.should_refresh = true;
|
||||
self.data.sonarr_data.prompt_confirm_action = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn sonarr_on_tick(&mut self, active_sonarr_block: ActiveSonarrBlock) {
|
||||
if self.is_first_render {
|
||||
self.refresh_sonarr_metadata().await;
|
||||
self.dispatch_by_sonarr_block(&active_sonarr_block).await;
|
||||
self.is_first_render = false;
|
||||
}
|
||||
|
||||
if self.should_refresh {
|
||||
self.dispatch_by_sonarr_block(&active_sonarr_block).await;
|
||||
self.refresh_sonarr_metadata().await;
|
||||
}
|
||||
|
||||
if self.is_routing {
|
||||
if !self.should_refresh {
|
||||
self.cancellation_token.cancel();
|
||||
} else {
|
||||
self.dispatch_by_sonarr_block(&active_sonarr_block).await;
|
||||
self.refresh_sonarr_metadata().await;
|
||||
}
|
||||
}
|
||||
|
||||
if self.tick_count % self.tick_until_poll == 0 {
|
||||
self.refresh_sonarr_metadata().await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_sonarr_metadata(&mut self) {
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetQualityProfiles.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetLanguageProfiles.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetTags.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetRootFolders.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetDiskSpace.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(SonarrEvent::GetStatus.into())
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn populate_seasons_table(&mut self) {
|
||||
let seasons = self
|
||||
.data
|
||||
.sonarr_data
|
||||
.series
|
||||
.current_selection()
|
||||
.clone()
|
||||
.seasons
|
||||
.unwrap_or_default();
|
||||
self.data.sonarr_data.seasons.set_items(seasons);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
use crate::app::{context_clues::ContextClue, key_binding::DEFAULT_KEYBINDINGS};
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "sonarr_context_clues_tests.rs"]
|
||||
mod sonarr_context_clues_tests;
|
||||
|
||||
pub static SERIES_CONTEXT_CLUES: [ContextClue; 10] = [
|
||||
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
||||
(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc),
|
||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
||||
(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.update, "update all"),
|
||||
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||
(DEFAULT_KEYBINDINGS.esc, "cancel filter"),
|
||||
];
|
||||
|
||||
pub static HISTORY_CONTEXT_CLUES: [ContextClue; 6] = [
|
||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||
(DEFAULT_KEYBINDINGS.delete, "mark as failed"),
|
||||
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
||||
(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc),
|
||||
(
|
||||
DEFAULT_KEYBINDINGS.refresh,
|
||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||
),
|
||||
(DEFAULT_KEYBINDINGS.esc, "cancel filter"),
|
||||
];
|
||||
@@ -0,0 +1,101 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
|
||||
use crate::app::{
|
||||
key_binding::DEFAULT_KEYBINDINGS,
|
||||
sonarr::sonarr_context_clues::{HISTORY_CONTEXT_CLUES, SERIES_CONTEXT_CLUES},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_series_context_clues() {
|
||||
let mut series_context_clues_iter = SERIES_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.add);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.add.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update);
|
||||
assert_str_eq!(*description, "update all");
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||
assert_str_eq!(*description, "details");
|
||||
|
||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||
assert_str_eq!(*description, "cancel filter");
|
||||
assert_eq!(series_context_clues_iter.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_history_context_clues() {
|
||||
let mut history_context_clues_iter = HISTORY_CONTEXT_CLUES.iter();
|
||||
|
||||
let (key_binding, description) = history_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
||||
|
||||
let (key_binding, description) = history_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||
assert_str_eq!(*description, "mark as failed");
|
||||
|
||||
let (key_binding, description) = history_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc);
|
||||
|
||||
let (key_binding, description) = history_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc);
|
||||
|
||||
let (key_binding, description) = history_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh);
|
||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||
|
||||
let (key_binding, description) = history_context_clues_iter.next().unwrap();
|
||||
|
||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||
assert_str_eq!(*description, "cancel filter");
|
||||
assert_eq!(history_context_clues_iter.next(), None);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,606 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod sonarr_tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::{
|
||||
app::App,
|
||||
models::{
|
||||
servarr_data::sonarr::sonarr_data::ActiveSonarrBlock,
|
||||
sonarr_models::{Season, Series},
|
||||
},
|
||||
network::{sonarr_network::SonarrEvent, NetworkEvent},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_blocklist_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::Blocklist)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetBlocklist.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_series_history_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeriesHistory)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetSeriesHistory(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_series_details_block() {
|
||||
let (mut app, _) = construct_app_unit();
|
||||
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
seasons: Some(vec![Season::default()]),
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeriesDetails)
|
||||
.await;
|
||||
|
||||
assert!(!app.is_loading);
|
||||
assert!(!app.data.sonarr_data.seasons.items.is_empty());
|
||||
assert_eq!(app.tick_count, 0);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_season_details_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SeasonDetails)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodes(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_season_search_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::ManualSeasonSearch)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetSeasonReleases(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_episode_details_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::EpisodeDetails)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeDetails(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_episode_file_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::EpisodeFile)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeDetails(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_episode_history_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::EpisodeHistory)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeHistory(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_episode_search_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::ManualEpisodeSearch)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetEpisodeReleases(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_history_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::History)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetHistory(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_downloads_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::Downloads)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_root_folders_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::RootFolders)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_series_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::Series)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::ListSeries.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_indexers_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::Indexers)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetIndexers.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_all_indexer_settings_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::AllIndexerSettingsPrompt)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetAllIndexerSettings.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_test_indexer_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::TestIndexer)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::TestIndexer(None).into()
|
||||
);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_test_all_indexers_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::TestAllIndexers)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::TestAllIndexers.into()
|
||||
);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_system_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::System)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetTasks.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetQueuedEvents.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetLogs(None).into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_system_updates_block() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
|
||||
app
|
||||
.dispatch_by_sonarr_block(&ActiveSonarrBlock::SystemUpdates)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetUpdates.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_for_sonarr_prompt_action_no_prompt_confirm() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.prompt_confirm = false;
|
||||
|
||||
app.check_for_sonarr_prompt_action().await;
|
||||
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert!(!app.should_refresh);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_for_sonarr_prompt_action() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::GetStatus);
|
||||
|
||||
app.check_for_sonarr_prompt_action().await;
|
||||
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetStatus.into()
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_refresh_metadata() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.is_routing = true;
|
||||
|
||||
app.refresh_sonarr_metadata().await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetLanguageProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetTags.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDiskSpace.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetStatus.into()
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_on_tick_first_render() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.is_first_render = true;
|
||||
|
||||
app.sonarr_on_tick(ActiveSonarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetLanguageProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetTags.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDiskSpace.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetStatus.into()
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert!(!app.is_first_render);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_on_tick_routing() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.is_routing = true;
|
||||
app.should_refresh = true;
|
||||
|
||||
app.sonarr_on_tick(ActiveSonarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetLanguageProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetTags.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_on_tick_routing_while_long_request_is_running_should_cancel_request() {
|
||||
let (mut app, _) = construct_app_unit();
|
||||
app.is_routing = true;
|
||||
app.should_refresh = false;
|
||||
|
||||
app.sonarr_on_tick(ActiveSonarrBlock::Downloads).await;
|
||||
|
||||
assert!(app.cancellation_token.is_cancelled());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_on_tick_should_refresh() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.should_refresh = true;
|
||||
|
||||
app.sonarr_on_tick(ActiveSonarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_on_tick_should_refresh_does_not_cancel_prompt_requests() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.is_loading = true;
|
||||
app.is_routing = true;
|
||||
app.should_refresh = true;
|
||||
|
||||
app.sonarr_on_tick(ActiveSonarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
assert!(app.should_refresh);
|
||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||
assert!(!app.cancellation_token.is_cancelled());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_sonarr_on_tick_network_tick_frequency() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.tick_count = 2;
|
||||
app.tick_until_poll = 2;
|
||||
|
||||
app.sonarr_on_tick(ActiveSonarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetLanguageProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetTags.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
sync_network_rx.recv().await.unwrap(),
|
||||
SonarrEvent::GetDownloads.into()
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_populate_seasons_table_unfiltered() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_items(vec![Series {
|
||||
seasons: Some(vec![Season::default()]),
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
app.populate_seasons_table().await;
|
||||
|
||||
assert!(!app.data.sonarr_data.seasons.items.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_populate_seasons_table_filtered() {
|
||||
let mut app = App::default();
|
||||
app.data.sonarr_data.series.set_filtered_items(vec![Series {
|
||||
seasons: Some(vec![Season::default()]),
|
||||
..Series::default()
|
||||
}]);
|
||||
|
||||
app.populate_seasons_table().await;
|
||||
|
||||
assert!(!app.data.sonarr_data.seasons.items.is_empty());
|
||||
}
|
||||
|
||||
fn construct_app_unit<'a>() -> (App<'a>, mpsc::Receiver<NetworkEvent>) {
|
||||
let (sync_network_tx, sync_network_rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App {
|
||||
network_tx: Some(sync_network_tx),
|
||||
tick_count: 1,
|
||||
is_first_render: false,
|
||||
..App::default()
|
||||
};
|
||||
app.data.sonarr_data.prompt_confirm = true;
|
||||
|
||||
(app, sync_network_rx)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user