Files
managarr/src/models/readarr_models_tests.rs
T

1263 lines
36 KiB
Rust

#[cfg(test)]
mod tests {
use chrono::Utc;
use pretty_assertions::{assert_eq, assert_str_eq};
use serde::de::DeserializeOwned;
use serde_json::{Value, json};
use crate::models::readarr_models::{
AddAuthorSearchResult, BlocklistItem, BlocklistResponse, Book, BookFile, DownloadRecord,
DownloadsResponse, Edition, MediaInfo, MonitorType, NewItemMonitorType,
ReadarrHistoryEventType, ReadarrHistoryItem, ReadarrHistoryWrapper, ReadarrRelease,
ReadarrTask, ReadarrTaskName,
};
use crate::models::servarr_models::{
DiskSpace, DownloadStatus, HostConfig, Indexer, IndexerSettings, IndexerTestResult, Log,
LogResponse, MetadataProfile, QualityProfile, QueueEvent, RootFolder, SecurityConfig,
SystemStatus, Tag, Update,
};
use crate::models::{
Serdeable,
readarr_models::{Author, AuthorStatistics, AuthorStatus, Ratings, ReadarrSerdeable},
};
use crate::network::readarr_network::readarr_network_test_utils::test_utils::{
ADD_AUTHOR_SEARCH_RESULT_JSON, AUTHOR_JSON, download_record,
};
#[test]
fn test_author_status_default() {
assert_eq!(AuthorStatus::default(), AuthorStatus::Continuing);
}
#[test]
fn test_new_item_monitor_type_display() {
assert_str_eq!(NewItemMonitorType::All.to_string(), "all");
assert_str_eq!(NewItemMonitorType::None.to_string(), "none");
assert_str_eq!(NewItemMonitorType::New.to_string(), "new");
}
#[test]
fn test_new_item_monitor_type_to_display_str() {
assert_str_eq!(NewItemMonitorType::All.to_display_str(), "All Books");
assert_str_eq!(NewItemMonitorType::None.to_display_str(), "No New Books");
assert_str_eq!(NewItemMonitorType::New.to_display_str(), "New Books");
}
#[test]
fn test_monitor_type_display() {
assert_str_eq!(MonitorType::All.to_string(), "all");
assert_str_eq!(MonitorType::Future.to_string(), "future");
assert_str_eq!(MonitorType::Missing.to_string(), "missing");
assert_str_eq!(MonitorType::Existing.to_string(), "existing");
assert_str_eq!(MonitorType::First.to_string(), "first");
assert_str_eq!(MonitorType::Latest.to_string(), "latest");
assert_str_eq!(MonitorType::None.to_string(), "none");
assert_str_eq!(MonitorType::Unknown.to_string(), "unknown");
}
#[test]
fn test_monitor_type_to_display_str() {
assert_str_eq!(MonitorType::All.to_display_str(), "All Books");
assert_str_eq!(MonitorType::Future.to_display_str(), "Future Books");
assert_str_eq!(MonitorType::Missing.to_display_str(), "Missing Books");
assert_str_eq!(MonitorType::Existing.to_display_str(), "Existing Books");
assert_str_eq!(MonitorType::First.to_display_str(), "First Book");
assert_str_eq!(MonitorType::Latest.to_display_str(), "Latest Book");
assert_str_eq!(MonitorType::None.to_display_str(), "None");
assert_str_eq!(MonitorType::Unknown.to_display_str(), "Unknown");
}
#[test]
fn test_readarr_serdeable_from() {
let readarr_serdeable = ReadarrSerdeable::Value(json!({}));
let serdeable: Serdeable = Serdeable::from(readarr_serdeable.clone());
assert_eq!(serdeable, Serdeable::Readarr(readarr_serdeable));
}
#[test]
fn test_readarr_serdeable_from_unit() {
let readarr_serdeable = ReadarrSerdeable::from(());
assert_eq!(readarr_serdeable, ReadarrSerdeable::Value(json!({})));
}
#[test]
fn test_readarr_serdeable_from_value() {
let value = json!({"test": "test"});
let readarr_serdeable: ReadarrSerdeable = value.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Value(value));
}
#[test]
fn test_readarr_serdeable_from_authors() {
let authors = vec![Author {
id: 1,
..Author::default()
}];
let readarr_serdeable: ReadarrSerdeable = authors.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Authors(authors));
}
#[test]
fn test_author_deserialization() {
let author_json = json!({
"id": 1,
"authorName": "Test Author",
"foreignAuthorId": "test-foreign-id",
"status": "continuing",
"overview": "Test overview",
"authorType": "Person",
"disambiguation": "American Novelist",
"path": "/nfs/books/Test Author",
"rootFolderPath": "/nfs/books/",
"qualityProfileId": 1,
"metadataProfileId": 1,
"monitored": true,
"monitorNewItems": "all",
"genres": ["Fantasy", "Fiction"],
"tags": [1, 2],
"ratings": {
"votes": 100,
"value": 4.5,
"popularity": 450.0
},
"statistics": {
"bookCount": 14,
"bookFileCount": 5,
"totalBookCount": 14,
"availableBookCount": 5,
"sizeOnDisk": 51783488,
"percentOfBooks": 35.71
}
});
let author: Author = serde_json::from_value(author_json).unwrap();
assert_eq!(author.id, 1);
assert_str_eq!(author.author_name.text, "Test Author");
assert_str_eq!(author.foreign_author_id, "test-foreign-id");
assert_eq!(author.status, AuthorStatus::Continuing);
assert_some_eq_x!(&author.overview, "Test overview");
assert_some_eq_x!(&author.author_type, "Person");
assert_some_eq_x!(&author.disambiguation, "American Novelist");
assert_str_eq!(author.path, "/nfs/books/Test Author");
assert_some_eq_x!(&author.root_folder_path, "/nfs/books/");
assert_eq!(author.quality_profile_id, 1);
assert_eq!(author.metadata_profile_id, 1);
assert!(author.monitored);
assert_eq!(author.monitor_new_items, NewItemMonitorType::All);
assert_eq!(author.genres, vec!["Fantasy", "Fiction"]);
assert_eq!(author.tags.len(), 2);
assert_some!(&author.ratings);
assert_some!(&author.statistics);
let ratings = author.ratings.unwrap();
assert_eq!(ratings.votes, 100);
assert_eq!(ratings.value, 4.5);
assert_some_eq_x!(ratings.popularity, 450.0);
let stats = author.statistics.unwrap();
assert_eq!(stats.book_count, 14);
assert_eq!(stats.book_file_count, 5);
assert_eq!(stats.total_book_count, 14);
assert_eq!(stats.available_book_count, 5);
assert_eq!(stats.size_on_disk, 51783488);
assert_eq!(stats.percent_of_books, 35.71);
}
#[test]
fn test_author_status_deserialization() {
assert_eq!(
serde_json::from_str::<AuthorStatus>("\"continuing\"").unwrap(),
AuthorStatus::Continuing
);
assert_eq!(
serde_json::from_str::<AuthorStatus>("\"ended\"").unwrap(),
AuthorStatus::Ended
);
assert_eq!(
serde_json::from_str::<AuthorStatus>("\"deleted\"").unwrap(),
AuthorStatus::Deleted
);
}
#[test]
fn test_ratings_equality() {
let ratings1 = Ratings {
votes: 100,
value: 4.5,
popularity: Some(450.0),
};
let ratings2 = Ratings {
votes: 100,
value: 4.5,
popularity: Some(450.0),
};
let ratings3 = Ratings {
votes: 50,
value: 3.0,
popularity: None,
};
assert_eq!(ratings1, ratings2);
assert_ne!(ratings1, ratings3);
}
#[test]
fn test_author_statistics_equality() {
let stats1 = AuthorStatistics {
book_count: 14,
book_file_count: 5,
total_book_count: 14,
available_book_count: 5,
size_on_disk: 51783488,
percent_of_books: 35.71,
};
let stats2 = AuthorStatistics {
book_count: 14,
book_file_count: 5,
total_book_count: 14,
available_book_count: 5,
size_on_disk: 51783488,
percent_of_books: 35.71,
};
let stats3 = AuthorStatistics::default();
assert_eq!(stats1, stats2);
assert_ne!(stats1, stats3);
}
#[test]
fn test_author_with_optional_fields_none() {
let author_json = json!({
"id": 1,
"authorName": "Test Author",
"foreignAuthorId": "",
"status": "continuing",
"path": "",
"qualityProfileId": 1,
"metadataProfileId": 1,
"monitored": false,
"monitorNewItems": "all",
"genres": [],
"tags": []
});
let author: Author = serde_json::from_value(author_json).unwrap();
assert_none!(&author.overview);
assert_none!(&author.author_type);
assert_none!(&author.disambiguation);
assert_none!(&author.root_folder_path);
assert_eq!(author.monitor_new_items, NewItemMonitorType::All);
assert_none!(&author.ratings);
assert_none!(&author.statistics);
}
#[test]
fn test_readarr_serdeable_from_author() {
let author = Author {
id: 1,
..Author::default()
};
let readarr_serdeable: ReadarrSerdeable = author.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Author(author));
}
#[test]
fn test_readarr_serdeable_from_blocklist_response() {
let blocklist_response = BlocklistResponse {
records: vec![BlocklistItem {
id: 1,
..BlocklistItem::default()
}],
};
let readarr_serdeable: ReadarrSerdeable = blocklist_response.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::BlocklistResponse(blocklist_response)
);
}
#[test]
fn test_readarr_serdeable_from_disk_spaces() {
let disk_spaces = vec![DiskSpace {
path: Some("/path".to_owned()),
free_space: 1,
total_space: 1,
}];
let readarr_serdeable: ReadarrSerdeable = disk_spaces.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::DiskSpaces(disk_spaces));
}
#[test]
fn test_readarr_serdeable_from_downloads_response() {
let downloads_response = DownloadsResponse {
records: vec![DownloadRecord {
id: 1,
..DownloadRecord::default()
}],
};
let readarr_serdeable: ReadarrSerdeable = downloads_response.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::DownloadsResponse(downloads_response)
);
}
#[test]
fn test_readarr_serdeable_from_readarr_history_wrapper() {
let history_wrapper = ReadarrHistoryWrapper {
records: vec![ReadarrHistoryItem {
id: 1,
..ReadarrHistoryItem::default()
}],
};
let readarr_serdeable: ReadarrSerdeable = history_wrapper.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::ReadarrHistoryWrapper(history_wrapper)
);
}
#[test]
fn test_readarr_serdeable_from_readarr_history_items() {
let history_items = vec![ReadarrHistoryItem {
id: 1,
..ReadarrHistoryItem::default()
}];
let readarr_serdeable: ReadarrSerdeable = history_items.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::ReadarrHistoryItems(history_items)
);
}
#[test]
fn test_readarr_serdeable_from_indexers() {
let indexers = vec![Indexer {
id: 1,
..Indexer::default()
}];
let readarr_serdeable: ReadarrSerdeable = indexers.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Indexers(indexers));
}
#[test]
fn test_readarr_serdeable_from_indexer_settings() {
let indexer_settings = IndexerSettings {
id: 1,
..IndexerSettings::default()
};
let readarr_serdeable: ReadarrSerdeable = indexer_settings.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::IndexerSettings(indexer_settings)
);
}
#[test]
fn test_readarr_serdeable_from_indexer_test_results() {
let indexer_test_results = vec![IndexerTestResult {
id: 1,
..IndexerTestResult::default()
}];
let readarr_serdeable: ReadarrSerdeable = indexer_test_results.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::IndexerTestResults(indexer_test_results)
);
}
#[test]
fn test_readarr_serdeable_from_log_response() {
let log_response = LogResponse {
records: vec![Log {
level: "info".to_owned(),
..Log::default()
}],
};
let readarr_serdeable: ReadarrSerdeable = log_response.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::LogResponse(log_response)
);
}
#[test]
fn test_readarr_serdeable_from_metadata_profiles() {
let metadata_profiles = vec![MetadataProfile {
id: 1,
name: "Standard".to_owned(),
}];
let readarr_serdeable: ReadarrSerdeable = metadata_profiles.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::MetadataProfiles(metadata_profiles)
);
}
#[test]
fn test_readarr_serdeable_from_host_config() {
let host_config = HostConfig {
port: 8787,
..HostConfig::default()
};
let readarr_serdeable: ReadarrSerdeable = host_config.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::HostConfig(host_config));
}
#[test]
fn test_readarr_serdeable_from_quality_profiles() {
let quality_profiles = vec![QualityProfile {
id: 1,
name: "Any".to_owned(),
}];
let readarr_serdeable: ReadarrSerdeable = quality_profiles.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::QualityProfiles(quality_profiles)
);
}
#[test]
fn test_readarr_serdeable_from_queue_events() {
let queue_events = vec![QueueEvent {
trigger: "test".to_owned(),
..QueueEvent::default()
}];
let readarr_serdeable: ReadarrSerdeable = queue_events.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::QueueEvents(queue_events)
);
}
#[test]
fn test_readarr_serdeable_from_root_folders() {
let root_folders = vec![RootFolder {
id: 1,
path: "/nfs/books".to_owned(),
accessible: true,
free_space: 1000000,
unmapped_folders: None,
}];
let readarr_serdeable: ReadarrSerdeable = root_folders.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::RootFolders(root_folders)
);
}
#[test]
fn test_readarr_serdeable_from_releases() {
let releases = vec![ReadarrRelease {
guid: "test".to_owned(),
..ReadarrRelease::default()
}];
let readarr_serdeable: ReadarrSerdeable = releases.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Releases(releases));
}
#[test]
fn test_readarr_serdeable_from_security_config() {
let security_config = SecurityConfig {
api_key: "test-key".to_owned(),
..SecurityConfig::default()
};
let readarr_serdeable: ReadarrSerdeable = security_config.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::SecurityConfig(security_config)
);
}
#[test]
fn test_readarr_serdeable_from_system_status() {
let system_status = SystemStatus {
version: "1.0.0".to_owned(),
start_time: Utc::now(),
};
let readarr_serdeable: ReadarrSerdeable = system_status.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::SystemStatus(system_status)
);
}
#[test]
fn test_readarr_serdeable_from_tags() {
let tags = vec![Tag {
id: 1,
label: "fantasy".to_owned(),
}];
let readarr_serdeable: ReadarrSerdeable = tags.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Tags(tags));
}
#[test]
fn test_readarr_serdeable_from_add_author_search_results() {
let search_results = vec![AddAuthorSearchResult {
foreign_author_id: "test-id".to_owned(),
..AddAuthorSearchResult::default()
}];
let readarr_serdeable: ReadarrSerdeable = search_results.clone().into();
assert_eq!(
readarr_serdeable,
ReadarrSerdeable::AddAuthorSearchResults(search_results)
);
}
#[test]
fn test_readarr_serdeable_from_books() {
let books = vec![Book {
id: 1,
..Book::default()
}];
let readarr_serdeable: ReadarrSerdeable = books.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Books(books));
}
#[test]
fn test_readarr_serdeable_from_book() {
let book = Book {
id: 1,
..Book::default()
};
let readarr_serdeable: ReadarrSerdeable = book.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Book(book));
}
#[test]
fn test_readarr_serdeable_from_editions() {
let editions = vec![Edition {
id: 1,
..Edition::default()
}];
let readarr_serdeable: ReadarrSerdeable = editions.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Editions(editions));
}
#[test]
fn test_readarr_serdeable_from_book_files() {
let book_files = vec![BookFile {
id: 1,
media_info: Some(MediaInfo {
audio_channels: 2,
..MediaInfo::default()
}),
..BookFile::default()
}];
let readarr_serdeable: ReadarrSerdeable = book_files.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::BookFiles(book_files));
}
#[test]
fn test_readarr_serdeable_from_tasks() {
let tasks = vec![ReadarrTask {
name: "test".to_owned(),
..ReadarrTask::default()
}];
let readarr_serdeable: ReadarrSerdeable = tasks.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Tasks(tasks));
}
#[test]
fn test_readarr_serdeable_from_updates() {
let updates = vec![Update {
version: "test".to_owned(),
..Update::default()
}];
let readarr_serdeable: ReadarrSerdeable = updates.clone().into();
assert_eq!(readarr_serdeable, ReadarrSerdeable::Updates(updates));
}
#[test]
fn test_author_status_display() {
assert_str_eq!(AuthorStatus::Continuing.to_string(), "continuing");
assert_str_eq!(AuthorStatus::Ended.to_string(), "ended");
assert_str_eq!(AuthorStatus::Deleted.to_string(), "deleted");
}
#[test]
fn test_author_status_to_display_str() {
assert_str_eq!(AuthorStatus::Continuing.to_display_str(), "Continuing");
assert_str_eq!(AuthorStatus::Ended.to_display_str(), "Ended");
assert_str_eq!(AuthorStatus::Deleted.to_display_str(), "Deleted");
}
#[test]
fn test_readarr_history_event_type_display() {
assert_str_eq!(ReadarrHistoryEventType::Unknown.to_string(), "unknown");
assert_str_eq!(ReadarrHistoryEventType::Grabbed.to_string(), "grabbed");
assert_str_eq!(
ReadarrHistoryEventType::AuthorFolderImported.to_string(),
"authorFolderImported"
);
assert_str_eq!(
ReadarrHistoryEventType::BookImportIncomplete.to_string(),
"bookImportIncomplete"
);
assert_str_eq!(
ReadarrHistoryEventType::DownloadIgnored.to_string(),
"downloadIgnored"
);
assert_str_eq!(
ReadarrHistoryEventType::DownloadImported.to_string(),
"downloadImported"
);
assert_str_eq!(
ReadarrHistoryEventType::DownloadFailed.to_string(),
"downloadFailed"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileDeleted.to_string(),
"bookFileDeleted"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileImported.to_string(),
"bookFileImported"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileRenamed.to_string(),
"bookFileRenamed"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileRetagged.to_string(),
"bookFileRetagged"
);
}
#[test]
fn test_readarr_history_event_type_to_display_str() {
assert_str_eq!(ReadarrHistoryEventType::Unknown.to_display_str(), "Unknown");
assert_str_eq!(ReadarrHistoryEventType::Grabbed.to_display_str(), "Grabbed");
assert_str_eq!(
ReadarrHistoryEventType::AuthorFolderImported.to_display_str(),
"Author Folder Imported"
);
assert_str_eq!(
ReadarrHistoryEventType::BookImportIncomplete.to_display_str(),
"Book Import Incomplete"
);
assert_str_eq!(
ReadarrHistoryEventType::DownloadIgnored.to_display_str(),
"Download Ignored"
);
assert_str_eq!(
ReadarrHistoryEventType::DownloadImported.to_display_str(),
"Download Imported"
);
assert_str_eq!(
ReadarrHistoryEventType::DownloadFailed.to_display_str(),
"Download Failed"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileDeleted.to_display_str(),
"Book File Deleted"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileImported.to_display_str(),
"Book File Imported"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileRenamed.to_display_str(),
"Book File Renamed"
);
assert_str_eq!(
ReadarrHistoryEventType::BookFileRetagged.to_display_str(),
"Book File Retagged"
);
}
#[test]
fn test_readarr_history_event_type_deserialization() {
assert_eq!(
deserialize_history_event_type(json!("unknown")),
ReadarrHistoryEventType::Unknown
);
assert_eq!(
deserialize_history_event_type(json!("grabbed")),
ReadarrHistoryEventType::Grabbed
);
assert_eq!(
deserialize_history_event_type(json!("authorFolderImported")),
ReadarrHistoryEventType::AuthorFolderImported
);
assert_eq!(
deserialize_history_event_type(json!("bookImportIncomplete")),
ReadarrHistoryEventType::BookImportIncomplete
);
assert_eq!(
deserialize_history_event_type(json!("downloadIgnored")),
ReadarrHistoryEventType::DownloadIgnored
);
assert_eq!(
deserialize_history_event_type(json!("downloadImported")),
ReadarrHistoryEventType::DownloadImported
);
assert_eq!(
deserialize_history_event_type(json!("downloadFailed")),
ReadarrHistoryEventType::DownloadFailed
);
assert_eq!(
deserialize_history_event_type(json!("bookFileDeleted")),
ReadarrHistoryEventType::BookFileDeleted
);
assert_eq!(
deserialize_history_event_type(json!("bookFileImported")),
ReadarrHistoryEventType::BookFileImported
);
assert_eq!(
deserialize_history_event_type(json!("bookFileRenamed")),
ReadarrHistoryEventType::BookFileRenamed
);
assert_eq!(
deserialize_history_event_type(json!("bookFileRetagged")),
ReadarrHistoryEventType::BookFileRetagged
);
}
#[test]
fn test_readarr_history_event_type_deserialization_falls_back_to_unknown() {
assert_eq!(
deserialize_history_event_type(json!("bookImportPartiallyComplete")),
ReadarrHistoryEventType::Unknown
);
assert_eq!(
deserialize_history_event_type(json!(2)),
ReadarrHistoryEventType::Unknown
);
assert_eq!(
deserialize_history_event_type(json!(11)),
ReadarrHistoryEventType::Unknown
);
assert_eq!(
deserialize_history_event_type(json!(null)),
ReadarrHistoryEventType::Unknown
);
assert_eq!(
deserialize_history_event_type(json!({ "id": 2 })),
ReadarrHistoryEventType::Unknown
);
}
#[test]
fn test_readarr_history_event_type_serialization() {
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::Unknown),
"unknown"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::Grabbed),
"grabbed"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::AuthorFolderImported),
"authorFolderImported"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::BookImportIncomplete),
"bookImportIncomplete"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::DownloadIgnored),
"downloadIgnored"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::DownloadImported),
"downloadImported"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::DownloadFailed),
"downloadFailed"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::BookFileDeleted),
"bookFileDeleted"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::BookFileImported),
"bookFileImported"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::BookFileRenamed),
"bookFileRenamed"
);
assert_str_eq!(
serialize_history_event_type(ReadarrHistoryEventType::BookFileRetagged),
"bookFileRetagged"
);
}
#[test]
fn test_readarr_task_name_display() {
assert_str_eq!(
ReadarrTaskName::ApplicationUpdateCheck.to_string(),
"ApplicationUpdateCheck"
);
assert_str_eq!(ReadarrTaskName::Backup.to_string(), "Backup");
assert_str_eq!(ReadarrTaskName::CheckHealth.to_string(), "CheckHealth");
assert_str_eq!(ReadarrTaskName::Housekeeping.to_string(), "Housekeeping");
assert_str_eq!(
ReadarrTaskName::ImportListSync.to_string(),
"ImportListSync"
);
assert_str_eq!(
ReadarrTaskName::MessagingCleanup.to_string(),
"MessagingCleanup"
);
assert_str_eq!(ReadarrTaskName::RefreshAuthor.to_string(), "RefreshAuthor");
assert_str_eq!(
ReadarrTaskName::RefreshMonitoredDownloads.to_string(),
"RefreshMonitoredDownloads"
);
assert_str_eq!(ReadarrTaskName::RescanFolders.to_string(), "RescanFolders");
assert_str_eq!(ReadarrTaskName::RssSync.to_string(), "RssSync");
}
#[test]
fn test_book_deserialization() {
let book_json = json!({
"id": 1,
"title": "The Name of the Wind",
"authorId": 3,
"foreignBookId": "test-foreign-book-id",
"monitored": true,
"anyEditionOk": true,
"pageCount": 662,
"releaseDate": "2007-03-27T00:00:00Z",
"grabbed": false,
"ratings": {
"votes": 100,
"value": 4.5,
"popularity": 450.0
},
"statistics": {
"bookFileCount": 1,
"totalBookCount": 1,
"sizeOnDisk": 51783488,
"percentOfBooks": 100.0
}
});
let book: Book = serde_json::from_value(book_json).unwrap();
assert_eq!(book.id, 1);
assert_str_eq!(book.title.text, "The Name of the Wind");
assert_eq!(book.author_id, 3);
assert_str_eq!(book.foreign_book_id, "test-foreign-book-id");
assert!(book.monitored);
assert!(book.any_edition_ok);
assert_some_eq_x!(book.page_count, 662);
assert_some!(&book.release_date);
assert!(!book.grabbed);
assert_some!(&book.ratings);
let stats = book.statistics.unwrap();
assert_eq!(stats.book_file_count, 1);
assert_eq!(stats.total_book_count, 1);
assert_eq!(stats.size_on_disk, 51783488);
assert_eq!(stats.percent_of_books, 100.0);
}
#[test]
fn test_book_with_optional_fields_none() {
let book_json = json!({
"id": 1,
"title": "The Name of the Wind",
"authorId": 3,
"foreignBookId": "",
"monitored": false,
"grabbed": false
});
let book: Book = serde_json::from_value(book_json).unwrap();
assert!(!book.any_edition_ok);
assert_none!(&book.page_count);
assert_none!(&book.release_date);
assert_none!(&book.ratings);
assert_none!(&book.statistics);
}
#[test]
fn test_book_deserialization_defaults_grabbed_when_absent() {
let book_json = json!({
"id": 1,
"title": "The Name of the Wind",
"authorId": 3,
"foreignBookId": "test-foreign-book-id",
"monitored": true
});
let book: Book = serde_json::from_value(book_json).unwrap();
assert!(!book.grabbed);
assert!(book.monitored);
}
#[test]
fn test_edition_deserialization() {
let edition_json = json!({
"id": 106,
"bookId": 1,
"foreignEditionId": "test-foreign-edition-id",
"monitored": true,
"isEbook": false,
"title": "The Name of the Wind",
"language": "eng",
"overview": "Test overview",
"format": "Hardcover",
"publisher": "DAW Books",
"pageCount": 662,
"releaseDate": "2007-03-27T00:00:00Z",
"isbn13": "9780756404079",
"asin": "0756404070",
"ratings": {
"votes": 100,
"value": 4.5,
"popularity": 450.0
}
});
let edition: Edition = serde_json::from_value(edition_json).unwrap();
assert_eq!(edition.id, 106);
assert_eq!(edition.book_id, 1);
assert_str_eq!(edition.foreign_edition_id, "test-foreign-edition-id");
assert!(edition.monitored);
assert!(!edition.is_ebook);
assert_str_eq!(edition.title, "The Name of the Wind");
assert_some_eq_x!(&edition.language, "eng");
assert_some_eq_x!(&edition.overview, "Test overview");
assert_some_eq_x!(&edition.format, "Hardcover");
assert_some_eq_x!(&edition.publisher, "DAW Books");
assert_some_eq_x!(edition.page_count, 662);
assert_some!(&edition.release_date);
assert_some_eq_x!(&edition.isbn13, "9780756404079");
assert_some_eq_x!(&edition.asin, "0756404070");
assert_some!(&edition.ratings);
}
#[test]
fn test_edition_with_optional_fields_none() {
let edition_json = json!({
"id": 106,
"bookId": 1,
"foreignEditionId": "",
"monitored": false,
"isEbook": true,
"title": ""
});
let edition: Edition = serde_json::from_value(edition_json).unwrap();
assert_none!(&edition.language);
assert_none!(&edition.overview);
assert_none!(&edition.format);
assert_none!(&edition.publisher);
assert_none!(&edition.page_count);
assert_none!(&edition.release_date);
assert_none!(&edition.isbn13);
assert_none!(&edition.asin);
assert_none!(&edition.ratings);
}
#[test]
fn test_media_info_deserialization() {
let media_info_json = json!({
"audioChannels": 2,
"audioBitRate": "99 kbps",
"audioCodec": "AAC",
"audioBits": "",
"audioSampleRate": "44.1kHz"
});
let media_info: MediaInfo = serde_json::from_value(media_info_json).unwrap();
assert_eq!(media_info.audio_channels, 2);
assert_some_eq_x!(&media_info.audio_bit_rate, "99 kbps");
assert_some_eq_x!(&media_info.audio_codec, "AAC");
assert_some_eq_x!(&media_info.audio_bits, "");
assert_some_eq_x!(&media_info.audio_sample_rate, "44.1kHz");
}
#[test]
fn test_download_record_deserialization() {
let download_record_json = json!({
"title": "Test Download",
"status": "downloading",
"id": 1,
"bookId": 2,
"authorId": 3,
"size": 3543348019.0,
"sizeleft": 1771674009.5,
"outputPath": "/nfs/books/Test Author",
"downloadClient": "transmission"
});
let download_record: DownloadRecord = serde_json::from_value(download_record_json).unwrap();
assert_str_eq!(download_record.title, "Test Download");
assert_eq!(download_record.status, DownloadStatus::Downloading);
assert_eq!(download_record.id, 1);
assert_some!(&download_record.book_id);
assert_some!(&download_record.author_id);
assert_eq!(download_record.size, 3543348019.0);
assert_eq!(download_record.sizeleft, 1771674009.5);
assert_some!(&download_record.output_path);
assert!(download_record.indexer.is_empty());
assert_some_eq_x!(&download_record.download_client, "transmission");
}
#[test]
fn test_add_author_search_result_deserialization() {
let search_result_json = json!({
"foreignAuthorId": "test-foreign-id",
"authorName": "Test Author",
"status": "continuing",
"ended": false,
"overview": "Test overview",
"authorType": "Person",
"disambiguation": "American Novelist",
"genres": ["Fantasy", "Fiction"],
"ratings": {
"votes": 100,
"value": 4.5,
"popularity": 450.0
}
});
let search_result: AddAuthorSearchResult = serde_json::from_value(search_result_json).unwrap();
assert_str_eq!(search_result.foreign_author_id, "test-foreign-id");
assert_str_eq!(search_result.author_name.text, "Test Author");
assert_eq!(search_result.status, AuthorStatus::Continuing);
assert!(!search_result.ended);
assert_some_eq_x!(&search_result.overview, "Test overview");
assert_some_eq_x!(&search_result.author_type, "Person");
assert_some_eq_x!(&search_result.disambiguation, "American Novelist");
assert_eq!(search_result.genres, vec!["Fantasy", "Fiction"]);
assert_some!(&search_result.ratings);
let ratings = search_result.ratings.unwrap();
assert_eq!(ratings.votes, 100);
assert_eq!(ratings.value, 4.5);
}
#[test]
fn test_add_author_search_result_with_optional_fields_none() {
let search_result_json = json!({
"foreignAuthorId": "test-foreign-id",
"authorName": "Test Author",
"status": "ended",
"genres": []
});
let search_result: AddAuthorSearchResult = serde_json::from_value(search_result_json).unwrap();
assert_str_eq!(search_result.foreign_author_id, "test-foreign-id");
assert_str_eq!(search_result.author_name.text, "Test Author");
assert_eq!(search_result.status, AuthorStatus::Ended);
assert!(!search_result.ended);
assert_none!(&search_result.overview);
assert_none!(&search_result.author_type);
assert_none!(&search_result.disambiguation);
assert!(search_result.genres.is_empty());
assert_none!(&search_result.ratings);
}
#[test]
fn test_author_status_deserialization_falls_back_to_default() {
let expected = Author {
status: AuthorStatus::default(),
..serde_json::from_str(AUTHOR_JSON).unwrap()
};
assert_eq!(
deserialize_with_field::<Author>(AUTHOR_JSON, "status", json!(2)),
expected
);
assert_eq!(
deserialize_with_field::<Author>(AUTHOR_JSON, "status", json!("notAThing")),
expected
);
}
#[test]
fn test_author_monitor_new_items_deserialization_falls_back_to_default() {
let expected = Author {
monitor_new_items: NewItemMonitorType::default(),
..serde_json::from_str(AUTHOR_JSON).unwrap()
};
assert_eq!(
deserialize_with_field::<Author>(AUTHOR_JSON, "monitorNewItems", json!(2)),
expected
);
assert_eq!(
deserialize_with_field::<Author>(AUTHOR_JSON, "monitorNewItems", json!("notAThing")),
expected
);
}
#[test]
fn test_add_author_search_result_status_deserialization_falls_back_to_default() {
let expected = AddAuthorSearchResult {
status: AuthorStatus::default(),
..serde_json::from_str(ADD_AUTHOR_SEARCH_RESULT_JSON).unwrap()
};
assert_eq!(
deserialize_with_field::<AddAuthorSearchResult>(
ADD_AUTHOR_SEARCH_RESULT_JSON,
"status",
json!(2)
),
expected
);
assert_eq!(
deserialize_with_field::<AddAuthorSearchResult>(
ADD_AUTHOR_SEARCH_RESULT_JSON,
"status",
json!("notAThing")
),
expected
);
}
#[test]
fn test_download_record_status_deserialization_falls_back_to_default() {
let download_record_json = serde_json::to_string(&download_record()).unwrap();
let expected = DownloadRecord {
status: DownloadStatus::default(),
..download_record()
};
assert_eq!(
deserialize_with_field::<DownloadRecord>(&download_record_json, "status", json!(2)),
expected
);
assert_eq!(
deserialize_with_field::<DownloadRecord>(&download_record_json, "status", json!("notAThing")),
expected
);
}
#[test]
fn test_readarr_task_task_name_deserialization_falls_back_to_default() {
let task = ReadarrTask {
name: "Backup".to_owned(),
task_name: ReadarrTaskName::Backup,
..ReadarrTask::default()
};
let task_json = serde_json::to_string(&task).unwrap();
let expected = ReadarrTask {
task_name: ReadarrTaskName::default(),
..task
};
assert_eq!(
deserialize_with_field::<ReadarrTask>(&task_json, "taskName", json!(2)),
expected
);
assert_eq!(
deserialize_with_field::<ReadarrTask>(&task_json, "taskName", json!("notAThing")),
expected
);
}
fn deserialize_with_field<T: DeserializeOwned>(json: &str, field: &str, value: Value) -> T {
let mut fixture_json: Value = serde_json::from_str(json).unwrap();
fixture_json[field] = value;
serde_json::from_value(fixture_json).unwrap()
}
fn deserialize_history_event_type(event_type: Value) -> ReadarrHistoryEventType {
let history_item_json = json!({
"id": 1,
"authorId": 1,
"bookId": 1,
"sourceTitle": "Test Source Title",
"date": "2024-01-01T00:00:00Z",
"eventType": event_type
});
serde_json::from_value::<ReadarrHistoryItem>(history_item_json)
.unwrap()
.event_type
}
fn serialize_history_event_type(event_type: ReadarrHistoryEventType) -> String {
let history_item = ReadarrHistoryItem {
event_type,
..ReadarrHistoryItem::default()
};
serde_json::to_value(history_item).unwrap()["eventType"]
.as_str()
.unwrap()
.to_owned()
}
}