Merge remote-tracking branch 'origin/main' into readarr-support

# Conflicts:
#	src/utils_tests.rs
This commit is contained in:
Dark-Alex-17 committed 2026-09-29 12:46:54 -06:00
commit a70019b88f
6 files changed
+392 -21

No files matched your search

+31
View File
@@ -16,6 +16,7 @@ mod tests {
use crate::models::{HorizontallyScrollableText, TabRoute};
use crate::network::NetworkEvent;
use crate::network::radarr_network::RadarrEvent;
use crate::network::sonarr_network::SonarrEvent;
use tokio_util::sync::CancellationToken;
#[test]
@@ -165,6 +166,36 @@ mod tests {
assert!(app.is_routing);
}
#[tokio::test]
async fn test_named_tab_uses_selected_servarr_route_and_network_events() {
let (network_tx, mut network_rx) = mpsc::channel(500);
let mut app = App::new(
network_tx,
AppConfig {
radarr: Some(vec![ServarrConfig {
name: Some("Movies".to_owned()),
..ServarrConfig::default()
}]),
sonarr: Some(vec![ServarrConfig {
name: Some("Shows".to_owned()),
..ServarrConfig::default()
}]),
..AppConfig::default()
},
CancellationToken::new(),
);
assert!(app.server_tabs.select_tab_by_title("Shows"));
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
app.on_tick().await;
assert_eq!(
network_rx.recv().await.unwrap(),
SonarrEvent::GetQualityProfiles.into()
);
}
#[test]
fn test_reset_cancellation_token() {
let mut app = App {
+5 -8
View File
@@ -263,14 +263,11 @@ impl App<'_> {
}
pub fn get_current_route(&self) -> Route {
*self.navigation_stack.last().unwrap_or(
&self
.server_tabs
.tabs
.first()
.expect("At least one server tab must exist")
.route,
)
self
.navigation_stack
.last()
.copied()
.unwrap_or_else(|| self.server_tabs.get_active_route())
}
}
+29 -2
View File
@@ -171,13 +171,40 @@ async fn main() -> Result<()> {
cancellation_token.clone(),
)));
if args.command.is_none()
&& let Some(name) = args.global.servarr_name.as_deref()
{
let mut app = app.lock().await;
anyhow::ensure!(
app.server_tabs.select_tab_by_title(name.trim()),
"A Servarr titled '{}' was not found in your configuration file",
name.trim()
);
}
match args.command {
Some(command) => match command {
Command::Radarr(_) | Command::Sonarr(_) | Command::Lidarr(_) | Command::Readarr(_) => {
if spinner_disabled {
start_cli_no_spinner(config, reqwest_client, cancellation_token, app, command).await;
start_cli_no_spinner(
config,
reqwest_client,
cancellation_token,
app,
command,
args.global.servarr_name.as_deref(),
)
.await;
} else {
start_cli_with_spinner(config, reqwest_client, cancellation_token, app, command).await;
start_cli_with_spinner(
config,
reqwest_client,
cancellation_token,
app,
command,
args.global.servarr_name.as_deref(),
)
.await;
}
}
Command::Completions { shell } => {
+26 -10
View File
@@ -23,6 +23,7 @@ use tokio_util::sync::CancellationToken;
use crate::app::{App, AppConfig, log_and_print_error};
use crate::cli::{self, Command};
use crate::models::Route;
use crate::network::Network;
use crate::ui::theme::ThemeDefinitionsWrapper;
@@ -287,12 +288,16 @@ pub(super) async fn start_cli_with_spinner(
cancellation_token: CancellationToken,
app: Arc<Mutex<App<'_>>>,
command: Command,
servarr_name: Option<&str>,
) {
config.verify_config_present_for_cli(&command);
{
let mut app = app.lock().await;
app.cli_mode = true;
select_cli_configuration(&mut app, &config, &command, None);
select_cli_configuration(&mut app, &config, &command, servarr_name).unwrap_or_else(|error| {
log_and_print_error(error.to_string());
process::exit(1);
});
}
let pb = render_spinner();
let app_nw = Arc::clone(&app);
@@ -316,12 +321,16 @@ pub(super) async fn start_cli_no_spinner(
cancellation_token: CancellationToken,
app: Arc<Mutex<App<'_>>>,
command: Command,
servarr_name: Option<&str>,
) {
config.verify_config_present_for_cli(&command);
{
let mut app = app.lock().await;
app.cli_mode = true;
select_cli_configuration(&mut app, &config, &command, None);
select_cli_configuration(&mut app, &config, &command, servarr_name).unwrap_or_else(|error| {
log_and_print_error(error.to_string());
process::exit(1);
});
}
let app_nw = Arc::clone(&app);
let mut network = Network::new(&app_nw, cancellation_token, reqwest_client);
@@ -340,16 +349,22 @@ pub fn select_cli_configuration(
app: &mut App<'_>,
config: &AppConfig,
command: &Command,
servarr_name_arg: Option<String>,
) {
servarr_name_arg: Option<&str>,
) -> Result<()> {
if let Some(servarr_name) = servarr_name_arg {
let trimmed_name = servarr_name.trim();
if !app.server_tabs.select_tab_by_title(trimmed_name) {
log_and_print_error(format!(
"A Servarr titled '{trimmed_name}' was not found in your configuration file"
));
process::exit(1);
}
let selected_index = app.server_tabs.tabs.iter().position(|tab| {
tab.title == trimmed_name
&& matches!(
(&tab.route, command),
(Route::Radarr(..), Command::Radarr(_))
| (Route::Sonarr(..), Command::Sonarr(_))
| (Route::Lidarr(..), Command::Lidarr(_))
)
});
app.server_tabs.index = selected_index.ok_or_else(|| {
anyhow!("A Servarr titled '{trimmed_name}' matching this command was not found in your configuration file")
})?;
} else {
match command {
Command::Radarr(_) => {
@@ -377,4 +392,5 @@ pub fn select_cli_configuration(
_ => (),
}
}
Ok(())
}
+40 -1
View File
@@ -1,11 +1,50 @@
#[cfg(test)]
mod tests {
use clap::Parser;
use std::fs::{self, File};
use std::io::{BufRead, BufReader, Seek, SeekFrom, Write};
use pretty_assertions::{assert_eq, assert_str_eq};
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;
use crate::utils::{convert_runtime, format_size, was_log_rotated};
use crate::{
Cli,
app::{App, AppConfig, ServarrConfig},
utils::{convert_runtime, format_size, select_cli_configuration, was_log_rotated},
};
#[test]
fn test_select_cli_configuration_selects_valid_named_instance() {
let selected_config = ServarrConfig {
name: Some("4K Movies".to_owned()),
..ServarrConfig::default()
};
let config = AppConfig {
radarr: Some(vec![ServarrConfig::default(), selected_config.clone()]),
..AppConfig::default()
};
let (network_tx, _network_rx) = mpsc::channel(1);
let mut app = App::new(network_tx, config.clone(), CancellationToken::new());
let args = Cli::try_parse_from([
"managarr",
"radarr",
"clear-blocklist",
"--servarr-name",
"4K Movies",
])
.unwrap();
select_cli_configuration(
&mut app,
&config,
args.command.as_ref().unwrap(),
args.global.servarr_name.as_deref(),
)
.unwrap();
assert_eq!(app.server_tabs.get_active_config(), &Some(selected_config));
}
#[test]
fn test_format_size() {