Added support for editing all indexer settings (finally)!

This commit is contained in:
2023-09-08 16:06:20 -06:00
parent b16a58deae
commit 2b15afcb83
14 changed files with 1018 additions and 37 deletions
@@ -1,9 +1,12 @@
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::App;
use crate::event::Key;
use crate::handlers::KeyEventHandler;
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
use crate::models::servarr_data::radarr::radarr_data::{
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
};
use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
#[cfg(test)]
#[path = "./edit_indexer_settings_handler_tests.rs"]
@@ -40,26 +43,181 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
}
fn handle_scroll_up(&mut self) {
if self.active_radarr_block == &ActiveRadarrBlock::IndexerSettingsPrompt {
self.app.data.radarr_data.selected_block.previous()
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
match self.active_radarr_block {
ActiveRadarrBlock::IndexerSettingsPrompt => {
self.app.data.radarr_data.selected_block.previous()
}
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput => {
indexer_settings.minimum_age += 1;
}
ActiveRadarrBlock::IndexerSettingsRetentionInput => {
indexer_settings.retention += 1;
}
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput => {
indexer_settings.maximum_size += 1;
}
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput => {
indexer_settings.availability_delay += 1;
}
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput => {
indexer_settings.rss_sync_interval += 1;
}
_ => (),
}
}
fn handle_scroll_down(&mut self) {
if self.active_radarr_block == &ActiveRadarrBlock::IndexerSettingsPrompt {
self.app.data.radarr_data.selected_block.next()
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
match self.active_radarr_block {
ActiveRadarrBlock::IndexerSettingsPrompt => self.app.data.radarr_data.selected_block.next(),
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput => {
if indexer_settings.minimum_age > 0 {
indexer_settings.minimum_age -= 1;
}
}
ActiveRadarrBlock::IndexerSettingsRetentionInput => {
if indexer_settings.retention > 0 {
indexer_settings.retention -= 1;
}
}
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput => {
if indexer_settings.maximum_size > 0 {
indexer_settings.maximum_size -= 1;
}
}
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput => {
indexer_settings.availability_delay -= 1;
}
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput => {
if indexer_settings.rss_sync_interval > 0 {
indexer_settings.rss_sync_interval -= 1;
}
}
_ => (),
}
}
fn handle_home(&mut self) {}
fn handle_home(&mut self) {
if self.active_radarr_block == &ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput {
self
.app
.data
.radarr_data
.indexer_settings
.as_mut()
.unwrap()
.whitelisted_hardcoded_subs
.scroll_home();
}
}
fn handle_end(&mut self) {}
fn handle_end(&mut self) {
if self.active_radarr_block == &ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput {
self
.app
.data
.radarr_data
.indexer_settings
.as_mut()
.unwrap()
.whitelisted_hardcoded_subs
.reset_offset();
}
}
fn handle_delete(&mut self) {}
fn handle_left_right_action(&mut self) {}
fn handle_left_right_action(&mut self) {
match self.active_radarr_block {
ActiveRadarrBlock::IndexerSettingsPrompt => {
if self.app.data.radarr_data.selected_block.get_active_block()
== &ActiveRadarrBlock::IndexerSettingsConfirmPrompt
{
handle_prompt_toggle(self.app, self.key);
} else {
let len = self.app.data.radarr_data.selected_block.blocks.len();
let idx = self.app.data.radarr_data.selected_block.index;
self.app.data.radarr_data.selected_block.index = (idx + 5) % len;
}
}
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
handle_text_box_left_right_keys!(
self,
self.key,
self
.app
.data
.radarr_data
.indexer_settings
.as_mut()
.unwrap()
.whitelisted_hardcoded_subs
)
}
_ => (),
}
}
fn handle_submit(&mut self) {}
fn handle_submit(&mut self) {
match self.active_radarr_block {
ActiveRadarrBlock::IndexerSettingsPrompt => {
match self.app.data.radarr_data.selected_block.get_active_block() {
ActiveRadarrBlock::IndexerSettingsConfirmPrompt => {
let radarr_data = &mut self.app.data.radarr_data;
if radarr_data.prompt_confirm {
radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateIndexerSettings);
self.app.should_refresh = true;
} else {
radarr_data.indexer_settings = None;
}
self.app.pop_navigation_stack();
}
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput
| ActiveRadarrBlock::IndexerSettingsRetentionInput
| ActiveRadarrBlock::IndexerSettingsMaximumSizeInput
| ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput
| ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput => {
self.app.push_navigation_stack(
(
*self.app.data.radarr_data.selected_block.get_active_block(),
None,
)
.into(),
)
}
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
self.app.push_navigation_stack(
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
);
self.app.should_ignore_quit_key = true;
}
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags => {
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
indexer_settings.prefer_indexer_flags = !indexer_settings.prefer_indexer_flags;
}
ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs => {
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
indexer_settings.allow_hardcoded_subs = !indexer_settings.allow_hardcoded_subs;
}
_ => (),
}
}
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
self.app.pop_navigation_stack();
self.app.should_ignore_quit_key = false;
}
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput
| ActiveRadarrBlock::IndexerSettingsRetentionInput
| ActiveRadarrBlock::IndexerSettingsMaximumSizeInput
| ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput
| ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput => self.app.pop_navigation_stack(),
_ => (),
}
}
fn handle_esc(&mut self) {
match self.active_radarr_block {
@@ -68,9 +226,28 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
self.app.data.radarr_data.prompt_confirm = false;
self.app.data.radarr_data.indexer_settings = None;
}
_ => self.app.pop_navigation_stack(), // Need to tweak this still and add unit tests
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
self.app.pop_navigation_stack();
self.app.should_ignore_quit_key = false;
}
_ => self.app.pop_navigation_stack(),
}
}
fn handle_char_key_event(&mut self) {}
fn handle_char_key_event(&mut self) {
if self.active_radarr_block == &ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput {
handle_text_box_keys!(
self,
self.key,
self
.app
.data
.radarr_data
.indexer_settings
.as_mut()
.unwrap()
.whitelisted_hardcoded_subs
)
}
}
}
@@ -15,14 +15,87 @@ mod tests {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::models::radarr_models::IndexerSettings;
use crate::models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use super::*;
macro_rules! test_i64_counter_scroll_value {
($block:expr, $key:expr, $data_ref:ident, $negatives:literal) => {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
IndexerSettingsHandler::with(&$key, &mut app, &$block, &None).handle();
if $key == Key::Up {
assert_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.$data_ref,
1
);
} else {
if $negatives {
assert_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.$data_ref,
-1
);
} else {
assert_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.$data_ref,
0
);
IndexerSettingsHandler::with(&Key::Up, &mut app, &$block, &None).handle();
assert_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.$data_ref,
1
);
IndexerSettingsHandler::with(&$key, &mut app, &$block, &None).handle();
assert_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.$data_ref,
0
);
}
}
};
}
#[rstest]
fn test_edit_indexer_settings_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.next();
@@ -47,18 +120,572 @@ mod tests {
);
}
}
#[rstest]
fn test_edit_indexer_settings_minimum_age_scroll(#[values(Key::Up, Key::Down)] key: Key) {
test_i64_counter_scroll_value!(
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
key,
minimum_age,
false
);
}
#[rstest]
fn test_edit_indexer_settings_retention_scroll(#[values(Key::Up, Key::Down)] key: Key) {
test_i64_counter_scroll_value!(
ActiveRadarrBlock::IndexerSettingsRetentionInput,
key,
retention,
false
);
}
#[rstest]
fn test_edit_indexer_settings_maximum_size_scroll(#[values(Key::Up, Key::Down)] key: Key) {
test_i64_counter_scroll_value!(
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
key,
maximum_size,
false
);
}
#[rstest]
fn test_edit_indexer_settings_availability_delay_scroll(
#[values(Key::Up, Key::Down)] key: Key,
) {
test_i64_counter_scroll_value!(
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
key,
availability_delay,
true
);
}
#[rstest]
fn test_edit_indexer_settings_rss_sync_interval_scroll(#[values(Key::Up, Key::Down)] key: Key) {
test_i64_counter_scroll_value!(
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput,
key,
rss_sync_interval,
false
);
}
}
mod test_handle_home_end {}
mod test_handle_home_end {
use pretty_assertions::assert_eq;
mod test_handle_left_right_action {}
use crate::models::radarr_models::IndexerSettings;
mod test_handle_submit {}
use super::*;
#[test]
fn test_edit_indexer_settings_whiteliested_subtitle_tags_input_home_end() {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
whitelisted_hardcoded_subs: "Test".into(),
..IndexerSettings::default()
});
IndexerSettingsHandler::with(
&DEFAULT_KEYBINDINGS.home.key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_eq!(
*app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.offset
.borrow(),
4
);
IndexerSettingsHandler::with(
&DEFAULT_KEYBINDINGS.end.key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_eq!(
*app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.offset
.borrow(),
0
);
}
}
mod test_handle_left_right_action {
use crate::models::radarr_models::IndexerSettings;
use crate::models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS;
use crate::models::BlockSelectionState;
use pretty_assertions::assert_eq;
use rstest::rstest;
use super::*;
#[rstest]
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.index = INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1;
IndexerSettingsHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert!(app.data.radarr_data.prompt_confirm);
IndexerSettingsHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
#[rstest]
#[case(
0,
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput
)]
#[case(
1,
ActiveRadarrBlock::IndexerSettingsRetentionInput,
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput
)]
#[case(
2,
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput
)]
#[case(
3,
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags,
ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs
)]
fn test_left_right_block_toggle(
#[values(Key::Left, Key::Right)] key: Key,
#[case] starting_index: usize,
#[case] left_block: ActiveRadarrBlock,
#[case] right_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.index = starting_index;
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&left_block
);
IndexerSettingsHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&right_block
);
IndexerSettingsHandler::with(
&key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.data.radarr_data.selected_block.get_active_block(),
&left_block
);
}
#[test]
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_left_right_keys() {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
whitelisted_hardcoded_subs: "Test".into(),
..IndexerSettings::default()
});
IndexerSettingsHandler::with(
&DEFAULT_KEYBINDINGS.left.key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_eq!(
*app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.offset
.borrow(),
1
);
IndexerSettingsHandler::with(
&DEFAULT_KEYBINDINGS.right.key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_eq!(
*app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.offset
.borrow(),
0
);
}
}
mod test_handle_submit {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::{
models::{
radarr_models::IndexerSettings,
servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, BlockSelectionState,
},
network::radarr_network::RadarrEvent,
};
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
#[test]
fn test_edit_indexer_settings_prompt_prompt_decline_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Indexers.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
assert!(!app.should_refresh);
assert_eq!(app.data.radarr_data.indexer_settings, None);
}
#[test]
fn test_edit_indexer_settings_prompt_prompt_confirmation_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app
.data
.radarr_data
.selected_block
.set_index(INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
app.data.radarr_data.prompt_confirm = true;
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Indexers.into());
assert_eq!(
app.data.radarr_data.prompt_confirm_action,
Some(RadarrEvent::UpdateIndexerSettings)
);
assert!(app.data.radarr_data.indexer_settings.is_some());
assert!(app.should_refresh);
}
#[rstest]
#[case(ActiveRadarrBlock::IndexerSettingsMinimumAgeInput, 0)]
#[case(ActiveRadarrBlock::IndexerSettingsRetentionInput, 1)]
#[case(ActiveRadarrBlock::IndexerSettingsMaximumSizeInput, 2)]
#[case(ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput, 5)]
#[case(ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput, 6)]
fn test_edit_indexer_settings_prompt_submit_selected_block(
#[case] selected_block: ActiveRadarrBlock,
#[case] index: usize,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(index);
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &selected_block.into());
}
#[test]
fn test_edit_indexer_settings_prompt_submit_whitelisted_subtitle_tags_input() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(7);
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into()
);
assert!(app.should_ignore_quit_key);
}
#[test]
fn test_edit_indexer_settings_toggle_prefer_indexer_flags_submit() {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(3);
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsPrompt.into()
);
assert!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.prefer_indexer_flags
);
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsPrompt.into()
);
assert!(
!app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.prefer_indexer_flags
);
}
#[test]
fn test_edit_indexer_settings_toggle_allow_hardcoded_subs_submit() {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
app.data.radarr_data.selected_block =
BlockSelectionState::new(&INDEXER_SETTINGS_SELECTION_BLOCKS);
app.data.radarr_data.selected_block.set_index(8);
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsPrompt.into()
);
assert!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.allow_hardcoded_subs
);
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsPrompt,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsPrompt.into()
);
assert!(
!app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.allow_hardcoded_subs
);
}
#[test]
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_submit() {
let mut app = App::default();
app.should_ignore_quit_key = true;
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
whitelisted_hardcoded_subs: "Test tags".into(),
..IndexerSettings::default()
});
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.push_navigation_stack(
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
);
IndexerSettingsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert!(!app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.text
.is_empty());
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsPrompt.into()
);
}
#[rstest]
fn test_edit_indexer_settings_selected_block_submit(
#[values(
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
ActiveRadarrBlock::IndexerSettingsRetentionInput,
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.push_navigation_stack(active_radarr_block.into());
IndexerSettingsHandler::with(&SUBMIT_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::IndexerSettingsPrompt.into()
);
}
}
mod test_handle_esc {
use pretty_assertions::assert_eq;
use rstest::rstest;
use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data;
use crate::models::radarr_models::IndexerSettings;
use super::*;
@@ -68,8 +695,8 @@ mod tests {
fn test_edit_indexer_settings_prompt_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
app.data.radarr_data = create_test_radarr_data();
app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsPrompt.into());
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
IndexerSettingsHandler::with(
&ESC_KEY,
@@ -83,9 +710,122 @@ mod tests {
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(app.data.radarr_data.indexer_settings, None);
}
#[test]
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_esc() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
app.push_navigation_stack(
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
);
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
app.should_ignore_quit_key = true;
IndexerSettingsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Indexers.into());
assert!(!app.should_ignore_quit_key);
assert_eq!(
app.data.radarr_data.indexer_settings,
Some(IndexerSettings::default())
);
}
#[rstest]
fn test_edit_indexer_settings_selected_blocks_esc(
#[values(
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
ActiveRadarrBlock::IndexerSettingsRetentionInput,
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput,
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput
)]
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
app.push_navigation_stack(active_radarr_block.into());
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
IndexerSettingsHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Indexers.into());
assert_eq!(
app.data.radarr_data.indexer_settings,
Some(IndexerSettings::default())
);
}
}
mod test_handle_key_char {}
mod test_handle_key_char {
use pretty_assertions::assert_str_eq;
use crate::models::radarr_models::IndexerSettings;
use super::*;
#[test]
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_backspace() {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
whitelisted_hardcoded_subs: "Test".into(),
..IndexerSettings::default()
});
IndexerSettingsHandler::with(
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_str_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.text,
"Tes"
);
}
#[test]
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_char_key() {
let mut app = App::default();
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
IndexerSettingsHandler::with(
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
&None,
)
.handle();
assert_str_eq!(
app
.data
.radarr_data
.indexer_settings
.as_ref()
.unwrap()
.whitelisted_hardcoded_subs
.text,
"h"
);
}
}
#[test]
fn test_indexer_settings_handler_accepts() {
+3 -2
View File
@@ -99,8 +99,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
fn handle_submit(&mut self) {
match self.active_radarr_block {
ActiveRadarrBlock::DeleteIndexerPrompt => {
if self.app.data.radarr_data.prompt_confirm {
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteIndexer);
let radarr_data = &mut self.app.data.radarr_data;
if radarr_data.prompt_confirm {
radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteIndexer);
}
self.app.pop_navigation_stack();
+10 -1
View File
@@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter};
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
use serde::{de, Deserialize, Deserializer};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Number;
use tui::widgets::{ListState, TableState};
@@ -223,6 +223,15 @@ impl Display for HorizontallyScrollableText {
}
}
impl Serialize for HorizontallyScrollableText {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.text)
}
}
impl HorizontallyScrollableText {
pub fn new(text: String) -> HorizontallyScrollableText {
HorizontallyScrollableText {
+11 -1
View File
@@ -7,6 +7,7 @@ mod tests {
use serde::de::value::F64Deserializer;
use serde::de::value::I64Deserializer;
use serde::de::IntoDeserializer;
use serde_json::to_string;
use crate::models::from_i64;
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
@@ -731,12 +732,21 @@ mod tests {
fn test_from_i64_error() {
let deserializer: F64Deserializer<ValueError> = 1f64.into_deserializer();
assert_eq!(
assert_str_eq!(
from_i64(deserializer).unwrap_err().to_string(),
"Unable to convert Number to i64: Number(1.0)"
);
}
#[test]
fn test_horizontally_scrollable_serialize() {
let text = HorizontallyScrollableText::from("Test");
let serialized = to_string(&text).expect("Serialization failed!");
assert_str_eq!(serialized, r#""Test""#);
}
fn create_test_tab_routes() -> Vec<TabRoute> {
vec![
TabRoute {
+2 -1
View File
@@ -207,7 +207,8 @@ pub struct IndexerSettings {
pub retention: i64,
#[serde(deserialize_with = "super::from_i64")]
pub rss_sync_interval: i64,
pub whitelisted_hardcoded_subs: String,
#[serde(default)]
pub whitelisted_hardcoded_subs: HorizontallyScrollableText,
}
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
@@ -424,11 +424,12 @@ pub static INDEXER_SETTINGS_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags,
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
];
pub static INDEXER_SETTINGS_SELECTION_BLOCKS: [ActiveRadarrBlock; 9] = [
pub static INDEXER_SETTINGS_SELECTION_BLOCKS: [ActiveRadarrBlock; 10] = [
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
ActiveRadarrBlock::IndexerSettingsRetentionInput,
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags,
ActiveRadarrBlock::IndexerSettingsConfirmPrompt,
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput,
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
@@ -560,6 +560,10 @@ mod tests {
indexer_settings_block_iter.next().unwrap(),
&ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags
);
assert_eq!(
indexer_settings_block_iter.next().unwrap(),
&ActiveRadarrBlock::IndexerSettingsConfirmPrompt
);
assert_eq!(
indexer_settings_block_iter.next().unwrap(),
&ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput
+5 -1
View File
@@ -747,7 +747,11 @@ impl<'a, 'b> Network<'a, 'b> {
self
.handle_request::<(), IndexerSettings>(request_props, |indexer_settings, mut app| {
app.data.radarr_data.indexer_settings = Some(indexer_settings);
if app.data.radarr_data.indexer_settings.is_none() {
app.data.radarr_data.indexer_settings = Some(indexer_settings);
} else {
debug!("Indexer Settings are being modified. Ignoring update...");
}
})
.await;
}
+34
View File
@@ -1058,6 +1058,40 @@ mod test {
);
}
#[tokio::test]
async fn test_handle_get_indexer_settings_event_no_op_if_already_present() {
let indexer_settings_response_json = json!({
"minimumAge": 0,
"maximumSize": 0,
"retention": 0,
"rssSyncInterval": 60,
"preferIndexerFlags": false,
"availabilityDelay": 0,
"allowHardcodedSubs": true,
"whitelistedHardcodedSubs": "",
"id": 1
});
let (async_server, app_arc, _server) = mock_radarr_api(
RequestMethod::Get,
None,
Some(indexer_settings_response_json),
RadarrEvent::GetIndexerSettings.resource(),
)
.await;
app_arc.lock().await.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
let mut network = Network::new(&app_arc, CancellationToken::new());
network
.handle_radarr_event(RadarrEvent::GetIndexerSettings)
.await;
async_server.assert_async().await;
assert_eq!(
app_arc.lock().await.data.radarr_data.indexer_settings,
Some(IndexerSettings::default())
);
}
#[tokio::test]
async fn test_handle_get_queued_events_event() {
let queued_events_json = json!([{
+1 -1
View File
@@ -97,7 +97,7 @@ fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rec
..
} = download_record;
if matches!(output_path, Some(_)) {
if output_path.is_some() {
output_path.as_ref().unwrap().scroll_left_or_reset(
get_width_from_percentage(area, 18),
current_selection == *download_record,
@@ -39,8 +39,8 @@ impl DrawUi for IndexerSettingsUi {
content_rect,
draw_indexers,
draw_edit_indexer_settings_prompt,
60,
40,
70,
45,
);
}
}
@@ -97,7 +97,7 @@ fn draw_edit_indexer_settings_prompt<B: Backend>(
draw_text_box_with_label(
f,
left_chunks[0],
"Minimum Age",
"Minimum Age (minutes) ▴▾",
&indexer_settings.minimum_age.to_string(),
0,
selected_block == &ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
@@ -106,7 +106,7 @@ fn draw_edit_indexer_settings_prompt<B: Backend>(
draw_text_box_with_label(
f,
left_chunks[1],
"Retention",
"Retention (days) ▴▾",
&indexer_settings.retention.to_string(),
0,
selected_block == &ActiveRadarrBlock::IndexerSettingsRetentionInput,
@@ -115,7 +115,7 @@ fn draw_edit_indexer_settings_prompt<B: Backend>(
draw_text_box_with_label(
f,
left_chunks[2],
"Maximum Size",
"Maximum Size (MB) ▴▾",
&indexer_settings.maximum_size.to_string(),
0,
selected_block == &ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
@@ -124,7 +124,7 @@ fn draw_edit_indexer_settings_prompt<B: Backend>(
draw_text_box_with_label(
f,
right_chunks[0],
"Availability Delay",
"Availability Delay (days) ▴▾",
&indexer_settings.availability_delay.to_string(),
0,
selected_block == &ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
@@ -133,7 +133,7 @@ fn draw_edit_indexer_settings_prompt<B: Backend>(
draw_text_box_with_label(
f,
right_chunks[1],
"RSS Sync Interval",
"RSS Sync Interval (minutes) ▴▾",
&indexer_settings.rss_sync_interval.to_string(),
0,
selected_block == &ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput,
@@ -143,8 +143,8 @@ fn draw_edit_indexer_settings_prompt<B: Backend>(
f,
right_chunks[2],
"Whitelisted Subtitle Tags",
&indexer_settings.whitelisted_hardcoded_subs.to_string(),
0,
&indexer_settings.whitelisted_hardcoded_subs.text,
*indexer_settings.whitelisted_hardcoded_subs.offset.borrow(),
selected_block == &ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
active_radarr_block == ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
);