refactor: Improved and simplified the implementation of history details for both Sonarr and Lidarr

This commit is contained in:
2026-01-13 12:36:21 -07:00
parent ad9e2b3671
commit e1a25bfaf2
18 changed files with 377 additions and 486 deletions
@@ -173,7 +173,7 @@ mod tests {
panic!("Expected LidarrHistoryWrapper")
};
mock.assert_async().await;
assert!(app.lock().await.data.lidarr_data.history.is_empty());
assert_is_empty!(app.lock().await.data.lidarr_data.history);
assert!(app.lock().await.data.lidarr_data.history.sort_asc);
assert_eq!(history, response);
}
@@ -194,6 +194,6 @@ mod tests {
.await;
mock.assert_async().await;
assert!(result.is_ok());
assert_ok!(result);
}
}
+33 -24
View File
@@ -32,9 +32,9 @@ pub(super) fn create_history_event_details(history_item: LidarrHistoryItem) -> V
} = data;
let mut lines = vec![
Line::from(format!("Source Title: {}", source_title.text)),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!("Quality: {}", quality.quality.name)),
Line::from(format!("Quality: {}", quality.quality.name.trim_start())),
Line::from(format!("Date: {date}")),
];
@@ -42,19 +42,19 @@ pub(super) fn create_history_event_details(history_item: LidarrHistoryItem) -> V
LidarrHistoryEventType::Grabbed => {
lines.push(Line::from(format!(
"Indexer: {}",
indexer.unwrap_or_default()
indexer.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"NZB Info URL: {}",
nzb_info_url.unwrap_or_default()
nzb_info_url.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Age: {} days",
age.unwrap_or("0".to_owned())
age.unwrap_or("0".to_owned()).trim_start()
)));
lines.push(Line::from(format!(
"Published Date: {}",
@@ -62,86 +62,95 @@ pub(super) fn create_history_event_details(history_item: LidarrHistoryItem) -> V
)));
lines.push(Line::from(format!(
"Download Client: {}",
download_client_name.unwrap_or(download_client.unwrap_or_default())
download_client_name
.unwrap_or(download_client.unwrap_or_default())
.trim_start()
)));
}
LidarrHistoryEventType::DownloadImported => {
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
}
LidarrHistoryEventType::DownloadFailed => {
lines.push(Line::from(format!(
"Download Client: {}",
download_client_name.unwrap_or(download_client.unwrap_or_default())
download_client_name
.unwrap_or(download_client.unwrap_or_default())
.trim_start()
)));
lines.push(Line::from(format!(
"Message: {}",
message.unwrap_or_default()
message.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Indexer: {}",
indexer.unwrap_or_default()
indexer.unwrap_or_default().trim_start()
)));
}
LidarrHistoryEventType::TrackFileDeleted => {
lines.push(Line::from(format!(
"Reason: {}",
reason.unwrap_or_default()
reason.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
}
LidarrHistoryEventType::TrackFileImported => {
lines.push(Line::from(format!(
"Dropped Path: {}",
dropped_path.unwrap_or_default()
dropped_path.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Imported Path: {}",
imported_path.unwrap_or_default()
imported_path.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Download Client: {}",
download_client_name.unwrap_or(download_client.unwrap_or_default())
download_client_name
.unwrap_or(download_client.unwrap_or_default())
.trim_start()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
}
LidarrHistoryEventType::TrackFileRenamed => {
lines.push(Line::from(format!(
"Source Path: {}",
source_path.unwrap_or_default()
source_path.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Path: {}",
path.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!("Path: {}", path.unwrap_or_default())));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
}
LidarrHistoryEventType::TrackFileRetagged => {
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
}
LidarrHistoryEventType::AlbumImportIncomplete => {
lines.push(Line::from(format!(
"Status Messages: {}",
status_messages.unwrap_or_default()
status_messages.unwrap_or_default().trim_start()
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default()
release_group.unwrap_or_default().trim_start()
)));
}
_ => {
+92 -56
View File
@@ -26,29 +26,35 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Indexer: {}", data.indexer.unwrap()))
Line::from(format!("Indexer: {}", data.indexer.unwrap().trim_start()))
);
assert_eq!(
result[5],
Line::from(format!("NZB Info URL: {}", data.nzb_info_url.unwrap()))
Line::from(format!(
"NZB Info URL: {}",
data.nzb_info_url.unwrap().trim_start()
))
);
assert_eq!(
result[6],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(
result[7],
Line::from(format!("Age: {} days", data.age.unwrap()))
Line::from(format!("Age: {} days", data.age.unwrap().trim_start()))
);
assert_eq!(
result[8],
@@ -58,7 +64,7 @@ mod tests {
result[9],
Line::from(format!(
"Download Client: {}",
data.download_client_name.unwrap()
data.download_client_name.unwrap().trim_start()
))
);
assert_eq!(result.len(), 10);
@@ -68,7 +74,7 @@ mod tests {
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());
history_item.data.download_client = Some("\nFallback Client".to_owned());
let result = create_history_event_details(history_item);
@@ -91,17 +97,20 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(result.len(), 5);
}
@@ -122,32 +131,35 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!(
"Download Client: {}",
data.download_client_name.unwrap()
data.download_client_name.unwrap().trim_start()
))
);
assert_eq!(
result[5],
Line::from(format!("Message: {}", data.message.unwrap()))
Line::from(format!("Message: {}", data.message.unwrap().trim_start()))
);
assert_eq!(
result[6],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(
result[7],
Line::from(format!("Indexer: {}", data.indexer.unwrap()))
Line::from(format!("Indexer: {}", data.indexer.unwrap().trim_start()))
);
assert_eq!(result.len(), 8);
}
@@ -168,21 +180,24 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Reason: {}", data.reason.unwrap()))
Line::from(format!("Reason: {}", data.reason.unwrap().trim_start()))
);
assert_eq!(
result[5],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(result.len(), 6);
}
@@ -203,32 +218,41 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Dropped Path: {}", data.dropped_path.unwrap()))
Line::from(format!(
"Dropped Path: {}",
data.dropped_path.unwrap().trim_start()
))
);
assert_eq!(
result[5],
Line::from(format!("Imported Path: {}", data.imported_path.unwrap()))
Line::from(format!(
"Imported Path: {}",
data.imported_path.unwrap().trim_start()
))
);
assert_eq!(
result[6],
Line::from(format!(
"Download Client: {}",
data.download_client_name.unwrap()
data.download_client_name.unwrap().trim_start()
))
);
assert_eq!(
result[7],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(result.len(), 8);
}
@@ -249,25 +273,31 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Source Path: {}", data.source_path.unwrap()))
Line::from(format!(
"Source Path: {}",
data.source_path.unwrap().trim_start()
))
);
assert_eq!(
result[5],
Line::from(format!("Path: {}", data.path.unwrap()))
Line::from(format!("Path: {}", data.path.unwrap().trim_start()))
);
assert_eq!(
result[6],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(result.len(), 7);
}
@@ -288,17 +318,20 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(result.len(), 5);
}
@@ -319,24 +352,27 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(
result[4],
Line::from(format!(
"Status Messages: {}",
data.status_messages.unwrap()
data.status_messages.unwrap().trim_start()
))
);
assert_eq!(
result[5],
Line::from(format!("Release Group: {}", data.release_group.unwrap()))
Line::from(format!(
"Release Group: {}",
data.release_group.unwrap().trim_start()
))
);
assert_eq!(result.len(), 6);
}
@@ -356,12 +392,12 @@ mod tests {
assert_eq!(
result[0],
Line::from(format!("Source Title: {}", source_title.text))
Line::from(format!("Source Title: {}", source_title.text.trim_start()))
);
assert_eq!(result[1], Line::from(format!("Event Type: {event_type}")));
assert_eq!(
result[2],
Line::from(format!("Quality: {}", quality.quality.name))
Line::from(format!("Quality: {}", quality.quality.name.trim_start()))
);
assert_eq!(result[3], Line::from(format!("Date: {date}")));
assert_eq!(result[4], Line::from("No additional details available."));
@@ -386,13 +422,13 @@ mod tests {
fn lidarr_history_item(event_type: LidarrHistoryEventType) -> LidarrHistoryItem {
LidarrHistoryItem {
id: 1,
source_title: "Test Album - Artist Name".into(),
source_title: "\nTest Album - Artist Name".into(),
album_id: 100,
artist_id: 10,
event_type,
quality: QualityWrapper {
quality: Quality {
name: "FLAC".to_owned(),
name: "\nFLAC".to_owned(),
},
},
date: Utc::now(),
@@ -402,20 +438,20 @@ mod tests {
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()),
indexer: Some("\nTest Indexer".to_owned()),
release_group: Some("\nTest Release Group".to_owned()),
nzb_info_url: Some("\nhttps://test.url".to_owned()),
download_client_name: Some("\nTest Download Client".to_owned()),
download_client: Some("\nFallback Download Client".to_owned()),
age: Some("\n7".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()),
message: Some("\nTest failure message".to_owned()),
reason: Some("\nTest deletion reason".to_owned()),
dropped_path: Some("\n/downloads/completed/album".to_owned()),
imported_path: Some("\n/music/artist/album".to_owned()),
source_path: Some("\n/music/artist/old_album_name".to_owned()),
path: Some("\n/music/artist/new_album_name".to_owned()),
status_messages: Some("\nMissing tracks: 1, 2, 3".to_owned()),
}
}
}
+3 -25
View File
@@ -2,8 +2,9 @@ use crate::app::App;
use crate::models::Route;
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS};
use crate::models::servarr_models::Language;
use crate::models::sonarr_models::{SonarrHistoryEventType, SonarrHistoryItem};
use crate::models::sonarr_models::SonarrHistoryItem;
use crate::ui::DrawUi;
use crate::ui::sonarr_ui::sonarr_ui_utils::create_history_event_details;
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;
@@ -14,14 +15,6 @@ use ratatui::layout::{Alignment, Constraint, Rect};
use ratatui::text::Text;
use ratatui::widgets::{Cell, Row};
use super::sonarr_ui_utils::{
create_download_failed_history_event_details,
create_download_folder_imported_history_event_details,
create_episode_file_deleted_history_event_details,
create_episode_file_renamed_history_event_details, create_grabbed_history_event_details,
create_no_data_history_event_details,
};
#[cfg(test)]
#[path = "history_ui_tests.rs"]
mod history_ui_tests;
@@ -130,22 +123,7 @@ fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
app.data.sonarr_data.history.current_selection().clone()
};
let line_vec = match current_selection.event_type {
SonarrHistoryEventType::Grabbed => create_grabbed_history_event_details(current_selection),
SonarrHistoryEventType::DownloadFolderImported => {
create_download_folder_imported_history_event_details(current_selection)
}
SonarrHistoryEventType::DownloadFailed => {
create_download_failed_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileDeleted => {
create_episode_file_deleted_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileRenamed => {
create_episode_file_renamed_history_event_details(current_selection)
}
_ => create_no_data_history_event_details(current_selection),
};
let line_vec = create_history_event_details(current_selection);
let text = Text::from(line_vec);
let message = Message::new(text)
@@ -19,6 +19,7 @@ expression: output
╭─────────────────────────────────── Details ───────────────────────────────────╮
│Source Title: Test source │
│Event Type: grabbed │
│Indexer: │
│Release Group: │
│Series Match Type: │
@@ -35,5 +36,4 @@ expression: output
│ │
│ │
│ │
│ │
╰─────────────────────────────────────────────────────────────────────────────────╯
@@ -19,6 +19,7 @@ expression: output
╭─────────────────────────────────── Details ───────────────────────────────────╮
│Source Title: │
│Event Type: unknown │
│ │
│No additional data available │
│ │
@@ -35,5 +36,4 @@ expression: output
│ │
│ │
│ │
│ │
╰─────────────────────────────────────────────────────────────────────────────────╯
+3 -24
View File
@@ -3,15 +3,9 @@ use crate::models::Route;
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS};
use crate::models::servarr_models::Language;
use crate::models::sonarr_models::{
DownloadRecord, DownloadStatus, Episode, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease,
};
use crate::ui::sonarr_ui::sonarr_ui_utils::{
create_download_failed_history_event_details,
create_download_folder_imported_history_event_details,
create_episode_file_deleted_history_event_details,
create_episode_file_renamed_history_event_details, create_grabbed_history_event_details,
create_no_data_history_event_details,
DownloadRecord, DownloadStatus, Episode, SonarrHistoryItem, SonarrRelease,
};
use crate::ui::sonarr_ui::sonarr_ui_utils::create_history_event_details;
use crate::ui::styles::ManagarrStyle;
use crate::ui::styles::{
awaiting_import_style, downloaded_style, downloading_style, missing_style, secondary_style,
@@ -372,22 +366,7 @@ fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: R
SonarrHistoryItem::default()
};
let line_vec = match current_selection.event_type {
SonarrHistoryEventType::Grabbed => create_grabbed_history_event_details(current_selection),
SonarrHistoryEventType::DownloadFolderImported => {
create_download_folder_imported_history_event_details(current_selection)
}
SonarrHistoryEventType::DownloadFailed => {
create_download_failed_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileDeleted => {
create_episode_file_deleted_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileRenamed => {
create_episode_file_renamed_history_event_details(current_selection)
}
_ => create_no_data_history_event_details(current_selection),
};
let line_vec = create_history_event_details(current_selection);
let text = Text::from(line_vec);
let message = Message::new(text)
+3 -24
View File
@@ -2,16 +2,10 @@ use crate::app::App;
use crate::models::Route;
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SEASON_DETAILS_BLOCKS};
use crate::models::sonarr_models::{
DownloadRecord, DownloadStatus, Episode, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease,
DownloadRecord, DownloadStatus, Episode, SonarrHistoryItem, SonarrRelease,
};
use crate::ui::sonarr_ui::library::episode_details_ui::EpisodeDetailsUi;
use crate::ui::sonarr_ui::sonarr_ui_utils::{
create_download_failed_history_event_details,
create_download_folder_imported_history_event_details,
create_episode_file_deleted_history_event_details,
create_episode_file_renamed_history_event_details, create_grabbed_history_event_details,
create_no_data_history_event_details,
};
use crate::ui::sonarr_ui::sonarr_ui_utils::create_history_event_details;
use crate::ui::styles::ManagarrStyle;
use crate::ui::styles::secondary_style;
use crate::ui::utils::{
@@ -548,22 +542,7 @@ fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: R
SonarrHistoryItem::default()
};
let line_vec = match current_selection.event_type {
SonarrHistoryEventType::Grabbed => create_grabbed_history_event_details(current_selection),
SonarrHistoryEventType::DownloadFolderImported => {
create_download_folder_imported_history_event_details(current_selection)
}
SonarrHistoryEventType::DownloadFailed => {
create_download_failed_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileDeleted => {
create_episode_file_deleted_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileRenamed => {
create_episode_file_renamed_history_event_details(current_selection)
}
_ => create_no_data_history_event_details(current_selection),
};
let line_vec = create_history_event_details(current_selection);
let text = Text::from(line_vec);
let message = Message::new(text)
+3 -26
View File
@@ -11,18 +11,10 @@ use regex::Regex;
use crate::app::App;
use crate::models::Route;
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SERIES_DETAILS_BLOCKS};
use crate::models::sonarr_models::{
Season, SeasonStatistics, SonarrHistoryEventType, SonarrHistoryItem,
};
use crate::models::sonarr_models::{Season, SeasonStatistics, SonarrHistoryItem};
use crate::ui::sonarr_ui::library::episode_details_ui::EpisodeDetailsUi;
use crate::ui::sonarr_ui::library::season_details_ui::SeasonDetailsUi;
use crate::ui::sonarr_ui::sonarr_ui_utils::{
create_download_failed_history_event_details,
create_download_folder_imported_history_event_details,
create_episode_file_deleted_history_event_details,
create_episode_file_renamed_history_event_details, create_grabbed_history_event_details,
create_no_data_history_event_details,
};
use crate::ui::sonarr_ui::sonarr_ui_utils::create_history_event_details;
use crate::ui::styles::ManagarrStyle;
use crate::ui::utils::{
borderless_block, get_width_from_percentage, layout_block_top_border, title_block,
@@ -408,22 +400,7 @@ fn draw_history_item_details_popup(f: &mut Frame<'_>, app: &mut App<'_>, area: R
SonarrHistoryItem::default()
};
let line_vec = match current_selection.event_type {
SonarrHistoryEventType::Grabbed => create_grabbed_history_event_details(current_selection),
SonarrHistoryEventType::DownloadFolderImported => {
create_download_folder_imported_history_event_details(current_selection)
}
SonarrHistoryEventType::DownloadFailed => {
create_download_failed_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileDeleted => {
create_episode_file_deleted_history_event_details(current_selection)
}
SonarrHistoryEventType::EpisodeFileRenamed => {
create_episode_file_renamed_history_event_details(current_selection)
}
_ => create_no_data_history_event_details(current_selection),
};
let line_vec = create_history_event_details(current_selection);
let text = Text::from(line_vec);
let message = Message::new(text)
@@ -21,6 +21,7 @@ expression: output
│ │
│ ╭──────────────────────── Details ─────────────────────────╮ │
│ │Source Title: │ │
│ │Event Type: unknown │ │
│ │ │ │
│ │No additional data available │ │
│ │ │ │
@@ -33,7 +34,6 @@ expression: output
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰────────────────────────────────────────────────────────────╯ │
│ │
│ │
@@ -21,6 +21,7 @@ expression: output
│ │
│ ╭──────────────────────── Details ─────────────────────────╮ │
│ │Source Title: Test source │ │
│ │Event Type: grabbed │ │
│ │Indexer: │ │
│ │Release Group: │ │
│ │Series Match Type: │ │
@@ -33,7 +34,6 @@ expression: output
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰────────────────────────────────────────────────────────────╯ │
│ │
│ │
@@ -21,6 +21,7 @@ expression: output
│ │
│ ╭──────────────────────────── Details ────────────────────────────╮ │
│ │Source Title: │ │
│ │Event Type: unknown │ │
│ │ │ │
│ │No additional data available │ │
│ │ │ │
@@ -33,7 +34,6 @@ expression: output
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰───────────────────────────────────────────────────────────────────╯ │
│ │
│ │
@@ -21,6 +21,7 @@ expression: output
│ │
│ ╭──────────────────────────── Details ────────────────────────────╮ │
│ │Source Title: │ │
│ │Event Type: unknown │ │
│ │ │ │
│ │No additional data available │ │
│ │ │ │
@@ -33,7 +34,6 @@ expression: output
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰───────────────────────────────────────────────────────────────────╯ │
│ │
│ │
@@ -21,6 +21,7 @@ expression: output
│ │
│ ╭──────────────────────────── Details ────────────────────────────╮ │
│ │Source Title: Test source │ │
│ │Event Type: grabbed │ │
│ │Indexer: │ │
│ │Release Group: │ │
│ │Series Match Type: │ │
@@ -33,7 +34,6 @@ expression: output
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰───────────────────────────────────────────────────────────────────╯ │
│ │
│ │
@@ -21,9 +21,9 @@ expression: output
│Size on Disk: 59.51 GB │
│ ╭─────────────────────────────── Details ───────────────────────────────╮ │
│ │Source Title: │ │
│ │ │ │
│╭ Series Details ─────────────────│No additional data available │───────────────────────────────────╮│
││ Seasons │ History │ │ ││
│ │Event Type: unknown │ │
│╭ Series Details ─────────────────│ │───────────────────────────────────╮│
││ Seasons │ History │No additional data available │ ││
││───────────────────────────────────│ │───────────────────────────────────││
││ │ │ ││
││ │ │ ││
@@ -21,12 +21,13 @@ expression: output
│Size on Disk: 59.51 GB │
│ ╭─────────────────────────────── Details ───────────────────────────────╮ │
│ │Source Title: Test source │ │
│ │Indexer: │ │
│╭ Series Details ─────────────────│Release Group: │───────────────────────────────────╮│
││ Seasons │ History │Series Match Type: │ ││
││───────────────────────────────────│NZB Info URL: │───────────────────────────────────││
││ Source Title ▼ │Download Client Name: │ Date ││
││=> Test source │Age: 0 days │ 2024-02-10 07:28:45 UTC ││
│ │Event Type: grabbed │ │
│╭ Series Details ─────────────────│Indexer: │───────────────────────────────────╮│
││ Seasons │ History │Release Group: │ ││
││───────────────────────────────────│Series Match Type: │───────────────────────────────────││
││ Source Title ▼ │NZB Info URL: │ Date ││
││=> Test source │Download Client Name: │ 2024-02-10 07:28:45 UTC ││
││ │Age: 0 days │ ││
││ │Published Date: 1970-01-01 00:00:00 UTC │ ││
││ │ │ ││
││ │ │ ││
@@ -35,7 +36,6 @@ expression: output
││ │ │ ││
││ │ │ ││
││ │ │ ││
││ │ │ ││
││ ╰─────────────────────────────────────────────────────────────────────────╯ ││
││ ││
││ ││
+89 -154
View File
@@ -1,18 +1,17 @@
use ratatui::style::Stylize;
use ratatui::text::Line;
use crate::models::sonarr_models::{SonarrHistoryData, SonarrHistoryItem};
use crate::ui::styles::ManagarrStyle;
use crate::models::sonarr_models::{SonarrHistoryData, SonarrHistoryEventType, SonarrHistoryItem};
#[cfg(test)]
#[path = "sonarr_ui_utils_tests.rs"]
mod sonarr_ui_utils_tests;
pub(super) fn create_grabbed_history_event_details(
history_item: SonarrHistoryItem,
) -> Vec<Line<'static>> {
pub(super) fn create_history_event_details(history_item: SonarrHistoryItem) -> Vec<Line<'static>> {
let SonarrHistoryItem {
source_title, data, ..
source_title,
data,
event_type,
..
} = history_item;
let SonarrHistoryData {
indexer,
@@ -22,120 +21,10 @@ pub(super) fn create_grabbed_history_event_details(
download_client_name,
age,
published_date,
..
} = data;
vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Indexer: ".bold().secondary(),
indexer.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Release Group: ".bold().secondary(),
release_group.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Series Match Type: ".bold().secondary(),
series_match_type.unwrap_or_default().secondary(),
]),
Line::from(vec![
"NZB Info URL: ".bold().secondary(),
nzb_info_url.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Download Client Name: ".bold().secondary(),
download_client_name.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Age: ".bold().secondary(),
format!("{} days", age.unwrap_or("0".to_owned())).secondary(),
]),
Line::from(vec![
"Published Date: ".bold().secondary(),
published_date.unwrap_or_default().to_string().secondary(),
]),
]
}
pub(super) fn create_download_folder_imported_history_event_details(
history_item: SonarrHistoryItem,
) -> Vec<Line<'static>> {
let SonarrHistoryItem {
source_title, data, ..
} = history_item;
let SonarrHistoryData {
dropped_path,
imported_path,
..
} = data;
vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Dropped Path: ".bold().secondary(),
dropped_path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Imported Path: ".bold().secondary(),
imported_path.unwrap_or_default().secondary(),
]),
]
}
pub(super) fn create_download_failed_history_event_details(
history_item: SonarrHistoryItem,
) -> Vec<Line<'static>> {
let SonarrHistoryItem {
source_title, data, ..
} = history_item;
let SonarrHistoryData { message, .. } = data;
vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Message: ".bold().secondary(),
message.unwrap_or_default().secondary(),
]),
]
}
pub(super) fn create_episode_file_deleted_history_event_details(
history_item: SonarrHistoryItem,
) -> Vec<Line<'static>> {
let SonarrHistoryItem {
source_title, data, ..
} = history_item;
let SonarrHistoryData { reason, .. } = data;
vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Reason: ".bold().secondary(),
reason.unwrap_or_default().secondary(),
]),
]
}
pub(super) fn create_episode_file_renamed_history_event_details(
history_item: SonarrHistoryItem,
) -> Vec<Line<'static>> {
let SonarrHistoryItem {
source_title, data, ..
} = history_item;
let SonarrHistoryData {
message,
reason,
source_path,
source_relative_path,
path,
@@ -143,41 +32,87 @@ pub(super) fn create_episode_file_renamed_history_event_details(
..
} = data;
vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Source Path: ".bold().secondary(),
source_path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Source Relative Path: ".bold().secondary(),
source_relative_path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Destination Path: ".bold().secondary(),
path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Destination Relative Path: ".bold().secondary(),
relative_path.unwrap_or_default().secondary(),
]),
]
}
let mut lines = vec![
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {}", event_type)),
];
pub(super) fn create_no_data_history_event_details(
history_item: SonarrHistoryItem,
) -> Vec<Line<'static>> {
let SonarrHistoryItem { source_title, .. } = history_item;
match event_type {
SonarrHistoryEventType::Grabbed => {
lines.push(Line::from(format!(
"Indexer: {}",
indexer.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Series Match Type: {}",
series_match_type.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"NZB Info URL: {}",
nzb_info_url.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Download Client Name: {}",
download_client_name.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Age: {}",
format!("{} days", age.unwrap_or("0".to_owned())).trim_start(),
)));
lines.push(Line::from(format!(
"Published Date: {}",
published_date.unwrap_or_default().to_string().trim_start(),
)));
}
SonarrHistoryEventType::DownloadFolderImported => {
lines.push(Line::from(format!(
"Dropped Path: {}",
dropped_path.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Imported Path: {}",
imported_path.unwrap_or_default().trim_start(),
)));
}
SonarrHistoryEventType::DownloadFailed => {
lines.push(Line::from(format!(
"Message: {}",
message.unwrap_or_default().trim_start(),
)));
}
SonarrHistoryEventType::EpisodeFileDeleted => {
lines.push(Line::from(format!(
"Reason: {}",
reason.unwrap_or_default().trim_start(),
)));
}
SonarrHistoryEventType::EpisodeFileRenamed => {
lines.push(Line::from(format!(
"Source Path: {}",
source_path.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Source Relative Path: {}",
source_relative_path.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Destination Path: {}",
path.unwrap_or_default().trim_start(),
)));
lines.push(Line::from(format!(
"Destination Relative Path: {}",
relative_path.unwrap_or_default().trim_start(),
)));
}
_ => {
lines.push(Line::from(String::new()));
lines.push(Line::from("No additional data available"));
}
}
vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![String::new().secondary()]),
Line::from(vec!["No additional data available".bold().secondary()]),
]
lines
}
+132 -134
View File
@@ -1,28 +1,21 @@
#[cfg(test)]
mod tests {
use chrono::Utc;
use ratatui::{style::Stylize, text::Line};
use ratatui::text::Line;
use crate::{
models::sonarr_models::{SonarrHistoryData, SonarrHistoryItem},
ui::{
sonarr_ui::sonarr_ui_utils::{
create_download_failed_history_event_details,
create_download_folder_imported_history_event_details,
create_episode_file_deleted_history_event_details,
create_episode_file_renamed_history_event_details, create_grabbed_history_event_details,
create_no_data_history_event_details,
},
styles::ManagarrStyle,
},
};
use crate::models::sonarr_models::SonarrHistoryEventType;
use crate::models::sonarr_models::{SonarrHistoryData, SonarrHistoryItem};
use crate::ui::sonarr_ui::sonarr_ui_utils::create_history_event_details;
use pretty_assertions::assert_eq;
#[test]
fn test_create_grabbed_history_event_details() {
let history_item = sonarr_history_item();
let history_item = sonarr_history_item(SonarrHistoryEventType::Grabbed);
let SonarrHistoryItem {
source_title, data, ..
source_title,
data,
event_type,
..
} = history_item.clone();
let SonarrHistoryData {
indexer,
@@ -35,50 +28,51 @@ mod tests {
..
} = data;
let expected_vec = vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Indexer: ".bold().secondary(),
indexer.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Release Group: ".bold().secondary(),
release_group.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Series Match Type: ".bold().secondary(),
series_match_type.unwrap_or_default().secondary(),
]),
Line::from(vec![
"NZB Info URL: ".bold().secondary(),
nzb_info_url.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Download Client Name: ".bold().secondary(),
download_client_name.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Age: ".bold().secondary(),
format!("{} days", age.unwrap_or("0".to_owned())).secondary(),
]),
Line::from(vec![
"Published Date: ".bold().secondary(),
published_date.unwrap_or_default().to_string().secondary(),
]),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!(
"Indexer: {}",
indexer.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Release Group: {}",
release_group.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Series Match Type: {}",
series_match_type.unwrap_or_default().trim_start()
)),
Line::from(format!(
"NZB Info URL: {}",
nzb_info_url.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Download Client Name: {}",
download_client_name.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Age: {}",
format!("{} days", age.unwrap_or("0".to_owned())).trim_start()
)),
Line::from(format!(
"Published Date: {}",
published_date.unwrap_or_default().to_string().trim_start()
)),
];
let history_details_vec = create_grabbed_history_event_details(history_item);
let history_details_vec = create_history_event_details(history_item);
assert_eq!(expected_vec, history_details_vec);
}
#[test]
fn test_create_download_folder_imported_history_event_details() {
let history_item = sonarr_history_item();
let history_item = sonarr_history_item(SonarrHistoryEventType::DownloadFolderImported);
let SonarrHistoryItem {
source_title, data, ..
source_title,
data,
event_type,
..
} = history_item.clone();
let SonarrHistoryData {
dropped_path,
@@ -86,76 +80,79 @@ mod tests {
..
} = data;
let expected_vec = vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Dropped Path: ".bold().secondary(),
dropped_path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Imported Path: ".bold().secondary(),
imported_path.unwrap_or_default().secondary(),
]),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!(
"Dropped Path: {}",
dropped_path.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Imported Path: {}",
imported_path.unwrap_or_default().trim_start()
)),
];
let history_details_vec = create_download_folder_imported_history_event_details(history_item);
let history_details_vec = create_history_event_details(history_item);
assert_eq!(expected_vec, history_details_vec);
}
#[test]
fn test_create_download_failed_history_event_details() {
let history_item = sonarr_history_item();
let history_item = sonarr_history_item(SonarrHistoryEventType::DownloadFailed);
let SonarrHistoryItem {
source_title, data, ..
source_title,
data,
event_type,
..
} = history_item.clone();
let SonarrHistoryData { message, .. } = data;
let expected_vec = vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Message: ".bold().secondary(),
message.unwrap_or_default().secondary(),
]),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!(
"Message: {}",
message.unwrap_or_default().trim_start()
)),
];
let history_details_vec = create_download_failed_history_event_details(history_item);
let history_details_vec = create_history_event_details(history_item);
assert_eq!(expected_vec, history_details_vec);
}
#[test]
fn test_create_episode_file_deleted_history_event_details() {
let history_item = sonarr_history_item();
let history_item = sonarr_history_item(SonarrHistoryEventType::EpisodeFileDeleted);
let SonarrHistoryItem {
source_title, data, ..
source_title,
data,
event_type,
..
} = history_item.clone();
let SonarrHistoryData { reason, .. } = data;
let expected_vec = vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Reason: ".bold().secondary(),
reason.unwrap_or_default().secondary(),
]),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!(
"Reason: {}",
reason.unwrap_or_default().trim_start()
)),
];
let history_details_vec = create_episode_file_deleted_history_event_details(history_item);
let history_details_vec = create_history_event_details(history_item);
assert_eq!(expected_vec, history_details_vec);
}
#[test]
fn test_create_episode_file_renamed_history_event_details() {
let history_item = sonarr_history_item();
let history_item = sonarr_history_item(SonarrHistoryEventType::EpisodeFileRenamed);
let SonarrHistoryItem {
source_title, data, ..
source_title,
data,
event_type,
..
} = history_item.clone();
let SonarrHistoryData {
source_path,
@@ -165,54 +162,55 @@ mod tests {
..
} = data;
let expected_vec = vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![
"Source Path: ".bold().secondary(),
source_path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Source Relative Path: ".bold().secondary(),
source_relative_path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Destination Path: ".bold().secondary(),
path.unwrap_or_default().secondary(),
]),
Line::from(vec![
"Destination Relative Path: ".bold().secondary(),
relative_path.unwrap_or_default().secondary(),
]),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(format!(
"Source Path: {}",
source_path.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Source Relative Path: {}",
source_relative_path.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Destination Path: {}",
path.unwrap_or_default().trim_start()
)),
Line::from(format!(
"Destination Relative Path: {}",
relative_path.unwrap_or_default().trim_start()
)),
];
let history_details_vec = create_episode_file_renamed_history_event_details(history_item);
let history_details_vec = create_history_event_details(history_item);
assert_eq!(expected_vec, history_details_vec);
}
#[test]
fn test_create_no_data_history_event_details() {
let history_item = sonarr_history_item();
let SonarrHistoryItem { source_title, .. } = history_item.clone();
let history_item = sonarr_history_item(SonarrHistoryEventType::Unknown);
let SonarrHistoryItem {
source_title,
event_type,
..
} = history_item.clone();
let expected_vec = vec![
Line::from(vec![
"Source Title: ".bold().secondary(),
source_title.text.secondary(),
]),
Line::from(vec![String::new().secondary()]),
Line::from(vec!["No additional data available".bold().secondary()]),
Line::from(format!("Source Title: {}", source_title.text.trim_start())),
Line::from(format!("Event Type: {event_type}")),
Line::from(String::new()),
Line::from("No additional data available"),
];
let history_details_vec = create_no_data_history_event_details(history_item);
let history_details_vec = create_history_event_details(history_item);
assert_eq!(expected_vec, history_details_vec);
}
fn sonarr_history_item() -> SonarrHistoryItem {
fn sonarr_history_item(event_type: SonarrHistoryEventType) -> SonarrHistoryItem {
SonarrHistoryItem {
source_title: "test.source.title".into(),
source_title: "\ntest.source.title".into(),
event_type,
data: sonarr_history_data(),
..SonarrHistoryItem::default()
}
@@ -220,21 +218,21 @@ mod tests {
fn sonarr_history_data() -> SonarrHistoryData {
SonarrHistoryData {
dropped_path: Some("/dropped/test".into()),
imported_path: Some("/imported/test".into()),
indexer: Some("Test Indexer".into()),
release_group: Some("test release group".into()),
series_match_type: Some("test match type".into()),
nzb_info_url: Some("test url".into()),
download_client_name: Some("test download client".into()),
age: Some("1".into()),
dropped_path: Some("\n/dropped/test".into()),
imported_path: Some("\n/imported/test".into()),
indexer: Some("\nTest Indexer".into()),
release_group: Some("\ntest release group".into()),
series_match_type: Some("\ntest match type".into()),
nzb_info_url: Some("\ntest url".into()),
download_client_name: Some("\ntest download client".into()),
age: Some("\n1".into()),
published_date: Some(Utc::now()),
message: Some("test message".into()),
reason: Some("test reason".into()),
source_path: Some("/source/path".into()),
source_relative_path: Some("/relative/source/path".into()),
path: Some("/path".into()),
relative_path: Some("/relative/path".into()),
message: Some("\ntest message".into()),
reason: Some("\ntest reason".into()),
source_path: Some("\n/source/path".into()),
source_relative_path: Some("\n/relative/source/path".into()),
path: Some("\n/path".into()),
relative_path: Some("\n/relative/path".into()),
}
}
}