feat: Implemented the Lidarr History tab and CLI support

This commit is contained in:
2026-01-12 14:21:58 -07:00
parent f31810e48a
commit 68b08d1cd7
41 changed files with 2505 additions and 78 deletions
@@ -0,0 +1,79 @@
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use crate::app::App;
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, HISTORY_BLOCKS};
use crate::ui::DrawUi;
use crate::ui::lidarr_ui::history::HistoryUi;
use crate::ui::ui_test_utils::test_utils::render_to_string_with_app;
#[test]
fn test_history_ui_accepts() {
ActiveLidarrBlock::iter().for_each(|active_lidarr_block| {
if HISTORY_BLOCKS.contains(&active_lidarr_block) {
assert!(HistoryUi::accepts(active_lidarr_block.into()));
} else {
assert!(!HistoryUi::accepts(active_lidarr_block.into()));
}
});
}
mod snapshot_tests {
use crate::ui::ui_test_utils::test_utils::TerminalSize;
use rstest::rstest;
use super::*;
#[test]
fn test_history_ui_renders_loading() {
let mut app = App::test_default();
app.is_loading = true;
app.push_navigation_stack(ActiveLidarrBlock::History.into());
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
HistoryUi::draw(f, app, f.area());
});
insta::assert_snapshot!(output);
}
#[rstest]
fn test_history_ui_renders_empty(
#[values(ActiveLidarrBlock::History, ActiveLidarrBlock::HistoryItemDetails)]
active_lidarr_block: ActiveLidarrBlock,
) {
let mut app = App::test_default();
app.push_navigation_stack(active_lidarr_block.into());
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
HistoryUi::draw(f, app, f.area());
});
insta::assert_snapshot!(format!("loading_history_tab_{active_lidarr_block}"), output);
}
#[rstest]
fn test_history_ui_renders(
#[values(
ActiveLidarrBlock::History,
ActiveLidarrBlock::HistoryItemDetails,
ActiveLidarrBlock::HistorySortPrompt,
ActiveLidarrBlock::FilterHistory,
ActiveLidarrBlock::FilterHistoryError,
ActiveLidarrBlock::SearchHistory,
ActiveLidarrBlock::SearchHistoryError
)]
active_lidarr_block: ActiveLidarrBlock,
) {
let mut app = App::test_default_fully_populated();
app.push_navigation_stack(active_lidarr_block.into());
let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| {
HistoryUi::draw(f, app, f.area());
});
insta::assert_snapshot!(format!("history_tab_{active_lidarr_block}"), output);
}
}
}
+120
View File
@@ -0,0 +1,120 @@
use super::lidarr_ui_utils::create_history_event_details;
use crate::app::App;
use crate::models::Route;
use crate::models::lidarr_models::LidarrHistoryItem;
use crate::models::servarr_data::lidarr::lidarr_data::{ActiveLidarrBlock, HISTORY_BLOCKS};
use crate::ui::DrawUi;
use crate::ui::styles::{ManagarrStyle, secondary_style};
use crate::ui::utils::{get_width_from_percentage, layout_block_top_border};
use crate::ui::widgets::managarr_table::ManagarrTable;
use crate::ui::widgets::message::Message;
use crate::ui::widgets::popup::{Popup, Size};
use ratatui::Frame;
use ratatui::layout::{Alignment, Rect};
use ratatui::prelude::Constraint;
use ratatui::text::Text;
use ratatui::widgets::{Cell, Row};
#[cfg(test)]
#[path = "history_ui_tests.rs"]
mod history_ui_tests;
pub(super) struct HistoryUi;
impl DrawUi for HistoryUi {
fn accepts(route: Route) -> bool {
if let Route::Lidarr(active_lidarr_block, _) = route {
return HISTORY_BLOCKS.contains(&active_lidarr_block);
}
false
}
fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
if let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() {
draw_history_table(f, app, area);
if active_lidarr_block == ActiveLidarrBlock::HistoryItemDetails {
draw_history_item_details_popup(f, app);
}
}
}
}
fn draw_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
let current_selection = if app.data.lidarr_data.history.items.is_empty() {
LidarrHistoryItem::default()
} else {
app.data.lidarr_data.history.current_selection().clone()
};
if let Route::Lidarr(active_lidarr_block, _) = app.get_current_route() {
let history_row_mapping = |history_item: &LidarrHistoryItem| {
let LidarrHistoryItem {
source_title,
quality,
event_type,
date,
..
} = history_item;
source_title.scroll_left_or_reset(
get_width_from_percentage(area, 50),
current_selection == *history_item,
app.ui_scroll_tick_count == 0,
);
Row::new(vec![
Cell::from(source_title.to_string()),
Cell::from(event_type.to_string()),
Cell::from(quality.quality.name.to_owned()),
Cell::from(date.to_string()),
])
.primary()
};
let history_table =
ManagarrTable::new(Some(&mut app.data.lidarr_data.history), history_row_mapping)
.block(layout_block_top_border())
.loading(app.is_loading)
.sorting(active_lidarr_block == ActiveLidarrBlock::HistorySortPrompt)
.searching(active_lidarr_block == ActiveLidarrBlock::SearchHistory)
.search_produced_empty_results(active_lidarr_block == ActiveLidarrBlock::SearchHistoryError)
.filtering(active_lidarr_block == ActiveLidarrBlock::FilterHistory)
.filter_produced_empty_results(active_lidarr_block == ActiveLidarrBlock::FilterHistoryError)
.headers(["Source Title", "Event Type", "Quality", "Date"])
.constraints([
Constraint::Percentage(50),
Constraint::Percentage(18),
Constraint::Percentage(12),
Constraint::Percentage(20),
]);
if [
ActiveLidarrBlock::SearchHistory,
ActiveLidarrBlock::FilterHistory,
]
.contains(&active_lidarr_block)
{
history_table.show_cursor(f, area);
}
f.render_widget(history_table, area);
}
}
fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
let current_selection = if app.data.lidarr_data.history.items.is_empty() {
LidarrHistoryItem::default()
} else {
app.data.lidarr_data.history.current_selection().clone()
};
let line_vec = create_history_event_details(current_selection);
let text = Text::from(line_vec);
let message = Message::new(text)
.title("Details")
.style(secondary_style())
.alignment(Alignment::Left);
f.render_widget(Popup::new(message).size(Size::NarrowMessage), f.area());
}
@@ -0,0 +1,28 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title ▼ Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
╭───────────────── Filter ──────────────────╮
│test filter │
╰─────────────────────────────────────────────╯
@@ -0,0 +1,31 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title ▼ Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
╭─────────────── Error ───────────────╮
│The given filter produced empty results│
│ │
╰───────────────────────────────────────╯
@@ -0,0 +1,7 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title ▼ Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
@@ -0,0 +1,34 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title ▼ Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
╭─────────────────────────────────── Details ───────────────────────────────────╮
│Source Title: Test source title │
│Event Type: grabbed │
│Quality: Lossless │
│Date: 2023-01-01 00:00:00 UTC │
│Indexer: │
│NZB Info URL: │
│Release Group: │
│Age: 0 days │
╰─────────────────────────────────────────────────────────────────────────────────╯
@@ -0,0 +1,42 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
╭───────────────────────────────╮
│Date │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
╰───────────────────────────────╯
@@ -0,0 +1,28 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title ▼ Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
╭───────────────── Search ──────────────────╮
│test search │
╰─────────────────────────────────────────────╯
@@ -0,0 +1,31 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Source Title ▼ Event Type Quality Date
=> Test source title grabbed Lossless 2023-01-01 00:00:00 UTC
╭─────────────── Error ───────────────╮
│ No items found matching search │
│ │
╰───────────────────────────────────────╯
@@ -0,0 +1,8 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Loading ...
@@ -0,0 +1,5 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,34 @@
---
source: src/ui/lidarr_ui/history/history_ui_tests.rs
expression: output
---
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
╭─────────────────────────────────── Details ───────────────────────────────────╮
│Source Title: │
│Event Type: unknown │
│Quality: │
│Date: 1970-01-01 00:00:00 UTC │
│No additional details available. │
│ │
│ │
│ │
╰─────────────────────────────────────────────────────────────────────────────────╯
+153
View File
@@ -0,0 +1,153 @@
use crate::models::lidarr_models::{LidarrHistoryData, LidarrHistoryEventType, LidarrHistoryItem};
use ratatui::text::Line;
#[cfg(test)]
#[path = "lidarr_ui_utils_tests.rs"]
mod lidarr_ui_utils_tests;
pub(super) fn create_history_event_details(history_item: LidarrHistoryItem) -> Vec<Line<'static>> {
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item;
let LidarrHistoryData {
indexer,
nzb_info_url,
release_group,
age,
published_date,
download_client_name,
download_client,
message,
reason,
dropped_path,
imported_path,
source_path,
path,
status_messages,
} = data;
let mut lines = vec![
Line::from(format!("Source Title: {}", source_title.text)),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!("Quality: {}", quality.quality.name)),
Line::from(format!("Date: {date}")),
];
match event_type {
LidarrHistoryEventType::Grabbed => {
lines.push(Line::from(format!(
"Indexer: {}",
indexer.unwrap_or_default()
)));
lines.push(Line::from(format!(
"NZB Info URL: {}",
nzb_info_url.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Age: {} days",
age.unwrap_or("0".to_owned())
)));
lines.push(Line::from(format!(
"Published Date: {}",
published_date.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Download Client: {}",
download_client_name.unwrap_or(download_client.unwrap_or_default())
)));
}
LidarrHistoryEventType::DownloadImported => {
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
}
LidarrHistoryEventType::DownloadFailed => {
lines.push(Line::from(format!(
"Download Client: {}",
download_client_name.unwrap_or(download_client.unwrap_or_default())
)));
lines.push(Line::from(format!(
"Message: {}",
message.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Indexer: {}",
indexer.unwrap_or_default()
)));
}
LidarrHistoryEventType::TrackFileDeleted => {
lines.push(Line::from(format!(
"Reason: {}",
reason.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
}
LidarrHistoryEventType::TrackFileImported => {
lines.push(Line::from(format!(
"Dropped Path: {}",
dropped_path.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Imported Path: {}",
imported_path.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Download Client: {}",
download_client_name.unwrap_or(download_client.unwrap_or_default())
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
}
LidarrHistoryEventType::TrackFileRenamed => {
lines.push(Line::from(format!(
"Source Path: {}",
source_path.unwrap_or_default()
)));
lines.push(Line::from(format!("Path: {}", path.unwrap_or_default())));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
}
LidarrHistoryEventType::TrackFileRetagged => {
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
}
LidarrHistoryEventType::AlbumImportIncomplete => {
lines.push(Line::from(format!(
"Status Messages: {}",
status_messages.unwrap_or_default()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
)));
}
_ => {
lines.push(Line::from("No additional details available.".to_owned()));
}
}
lines
}
+421
View File
@@ -0,0 +1,421 @@
#[cfg(test)]
mod tests {
use chrono::Utc;
use pretty_assertions::assert_eq;
use ratatui::text::Line;
use crate::models::lidarr_models::{
LidarrHistoryData, LidarrHistoryEventType, LidarrHistoryItem,
};
use crate::models::servarr_models::{Quality, QualityWrapper};
use crate::ui::lidarr_ui::lidarr_ui_utils::create_history_event_details;
#[test]
fn test_create_history_event_details_grabbed() {
let history_item = lidarr_history_item(LidarrHistoryEventType::Grabbed);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Indexer: {}", data.indexer.unwrap()))
);
assert_eq!(
result[5],
Line::from(format!("NZB Info URL: {}", data.nzb_info_url.unwrap()))
);
assert_eq!(
result[6],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(
result[7],
Line::from(format!("Age: {} days", data.age.unwrap()))
);
assert_eq!(
result[8],
Line::from(format!("Published Date: {}", data.published_date.unwrap()))
);
assert_eq!(
result[9],
Line::from(format!(
"Download Client: {}",
data.download_client_name.unwrap()
))
);
assert_eq!(result.len(), 10);
}
#[test]
fn test_create_history_event_details_grabbed_uses_download_client_as_fallback() {
let mut history_item = lidarr_history_item(LidarrHistoryEventType::Grabbed);
history_item.data.download_client_name = None;
history_item.data.download_client = Some("Fallback Client".to_owned());
let result = create_history_event_details(history_item);
assert_eq!(result[9], Line::from("Download Client: Fallback Client"));
}
#[test]
fn test_create_history_event_details_download_imported() {
let history_item = lidarr_history_item(LidarrHistoryEventType::DownloadImported);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(result.len(), 5);
}
#[test]
fn test_create_history_event_details_download_failed() {
let history_item = lidarr_history_item(LidarrHistoryEventType::DownloadFailed);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!(
"Download Client: {}",
data.download_client_name.unwrap()
))
);
assert_eq!(
result[5],
Line::from(format!("Message: {}", data.message.unwrap()))
);
assert_eq!(
result[6],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(
result[7],
Line::from(format!("Indexer: {}", data.indexer.unwrap()))
);
assert_eq!(result.len(), 8);
}
#[test]
fn test_create_history_event_details_track_file_deleted() {
let history_item = lidarr_history_item(LidarrHistoryEventType::TrackFileDeleted);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Reason: {}", data.reason.unwrap()))
);
assert_eq!(
result[5],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(result.len(), 6);
}
#[test]
fn test_create_history_event_details_track_file_imported() {
let history_item = lidarr_history_item(LidarrHistoryEventType::TrackFileImported);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Dropped Path: {}", data.dropped_path.unwrap()))
);
assert_eq!(
result[5],
Line::from(format!("Imported Path: {}", data.imported_path.unwrap()))
);
assert_eq!(
result[6],
Line::from(format!(
"Download Client: {}",
data.download_client_name.unwrap()
))
);
assert_eq!(
result[7],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(result.len(), 8);
}
#[test]
fn test_create_history_event_details_track_file_renamed() {
let history_item = lidarr_history_item(LidarrHistoryEventType::TrackFileRenamed);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Source Path: {}", data.source_path.unwrap()))
);
assert_eq!(
result[5],
Line::from(format!("Path: {}", data.path.unwrap()))
);
assert_eq!(
result[6],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(result.len(), 7);
}
#[test]
fn test_create_history_event_details_track_file_retagged() {
let history_item = lidarr_history_item(LidarrHistoryEventType::TrackFileRetagged);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(result.len(), 5);
}
#[test]
fn test_create_history_event_details_album_import_incomplete() {
let history_item = lidarr_history_item(LidarrHistoryEventType::AlbumImportIncomplete);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
data,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!(
"Status Messages: {}",
data.status_messages.unwrap()
))
);
assert_eq!(
result[5],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
);
assert_eq!(result.len(), 6);
}
#[test]
fn test_create_history_event_details_unknown() {
let history_item = lidarr_history_item(LidarrHistoryEventType::Unknown);
let LidarrHistoryItem {
source_title,
event_type,
quality,
date,
..
} = history_item.clone();
let result = create_history_event_details(history_item);
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(result[4], Line::from("No additional details available."));
assert_eq!(result.len(), 5);
}
#[test]
fn test_create_history_event_details_with_empty_optional_fields() {
let mut history_item = lidarr_history_item(LidarrHistoryEventType::Grabbed);
history_item.data = LidarrHistoryData::default();
let result = create_history_event_details(history_item);
assert_eq!(result[4], Line::from("Indexer: "));
assert_eq!(result[5], Line::from("NZB Info URL: "));
assert_eq!(result[6], Line::from("Release Group: "));
assert_eq!(result[7], Line::from("Age: 0 days"));
assert!(result[8].to_string().starts_with("Published Date:"));
assert_eq!(result[9], Line::from("Download Client: "));
}
fn lidarr_history_item(event_type: LidarrHistoryEventType) -> LidarrHistoryItem {
LidarrHistoryItem {
id: 1,
source_title: "Test Album - Artist Name".into(),
album_id: 100,
artist_id: 10,
event_type,
quality: QualityWrapper {
quality: Quality {
name: "FLAC".to_owned(),
},
},
date: Utc::now(),
data: lidarr_history_data(),
}
}
fn lidarr_history_data() -> LidarrHistoryData {
LidarrHistoryData {
indexer: Some("Test Indexer".to_owned()),
release_group: Some("Test Release Group".to_owned()),
nzb_info_url: Some("https://test.url".to_owned()),
download_client_name: Some("Test Download Client".to_owned()),
download_client: Some("Fallback Download Client".to_owned()),
age: Some("7".to_owned()),
published_date: Some(Utc::now()),
message: Some("Test failure message".to_owned()),
reason: Some("Test deletion reason".to_owned()),
dropped_path: Some("/downloads/completed/album".to_owned()),
imported_path: Some("/music/artist/album".to_owned()),
source_path: Some("/music/artist/old_album_name".to_owned()),
path: Some("/music/artist/new_album_name".to_owned()),
status_messages: Some("Missing tracks: 1, 2, 3".to_owned()),
}
}
}
+4
View File
@@ -5,6 +5,7 @@ use crate::ui::ui_test_utils::test_utils::Utc;
use chrono::Duration;
#[cfg(not(test))]
use chrono::Utc;
use history::HistoryUi;
use library::LibraryUi;
use ratatui::{
Frame,
@@ -35,7 +36,9 @@ use super::{
widgets::loading_block::LoadingBlock,
};
mod history;
mod library;
mod lidarr_ui_utils;
#[cfg(test)]
#[path = "lidarr_ui_tests.rs"]
@@ -54,6 +57,7 @@ impl DrawUi for LidarrUi {
match route {
_ if LibraryUi::accepts(route) => LibraryUi::draw(f, app, content_area),
_ if HistoryUi::accepts(route) => HistoryUi::draw(f, app, content_area),
_ => (),
}
}