feat(readarr): fetch data on tick for the active block
Give dispatch_by_readarr_block a real match so each view requests what it needs, and refresh the shared metadata on first render and on every poll tick. Until now the Readarr tab rendered but never fetched anything. Guard the conditional arms the way the other servarrs do: the manual author search only fetches when no releases are cached, book history only when the books table is populated, and the manual book search only when the book details modal exists with no cached releases. Add the selection id helpers the arms read from, named to avoid colliding with the equivalents the other servarrs already define on App. Book edition details gets no arm on purpose. There is no endpoint to fetch a single edition, and the popup is fully populated before it opens.
This commit is contained in:
2 files changed
+892
-6
No files matched your search
+202
-2
@@ -1,5 +1,8 @@
|
||||
use super::App;
|
||||
use crate::models::servarr_data::readarr::readarr_data::ActiveReadarrBlock;
|
||||
use crate::{
|
||||
models::servarr_data::readarr::readarr_data::ActiveReadarrBlock,
|
||||
network::readarr_network::ReadarrEvent,
|
||||
};
|
||||
|
||||
pub mod readarr_context_clues;
|
||||
|
||||
@@ -10,12 +13,179 @@ mod readarr_tests;
|
||||
impl App<'_> {
|
||||
pub(super) async fn dispatch_by_readarr_block(
|
||||
&mut self,
|
||||
_active_readarr_block: &ActiveReadarrBlock,
|
||||
active_readarr_block: &ActiveReadarrBlock,
|
||||
) {
|
||||
match active_readarr_block {
|
||||
ActiveReadarrBlock::Authors => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetQualityProfiles.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetMetadataProfiles.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetTags.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::ListAuthors.into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::Blocklist => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetBlocklist.into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::Downloads => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetDownloads(500).into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::AuthorDetails => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetBooks(self.extract_author_id().await).into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::AuthorHistory => {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
ReadarrEvent::GetAuthorHistory(self.extract_author_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::ManualAuthorSearch => {
|
||||
if self.data.readarr_data.author_releases.is_empty() {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
ReadarrEvent::GetAuthorReleases(self.extract_author_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
ActiveReadarrBlock::BookDetails => {
|
||||
let book_id = self.extract_book_id().await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetBookEditions(book_id).into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetBookFiles(book_id).into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetDownloads(500).into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::BookHistory => {
|
||||
if !self.data.readarr_data.books.is_empty() {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
ReadarrEvent::GetBookHistory(
|
||||
self.extract_author_id().await,
|
||||
self.extract_book_id().await,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
ActiveReadarrBlock::ManualBookSearch => {
|
||||
match self.data.readarr_data.book_details_modal.as_ref() {
|
||||
Some(book_details_modal) if book_details_modal.book_releases.is_empty() => {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
ReadarrEvent::GetBookReleases(self.extract_book_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
ActiveReadarrBlock::AddAuthorSearchResults => {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
ReadarrEvent::SearchNewAuthor(self.extract_add_new_author_search_query().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::History => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetHistory(500).into())
|
||||
.await
|
||||
}
|
||||
ActiveReadarrBlock::RootFolders => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetRootFolders.into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::Indexers => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetTags.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetIndexers.into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::AllIndexerSettingsPrompt => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetAllIndexerSettings.into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::TestIndexer => {
|
||||
self
|
||||
.dispatch_network_event(
|
||||
ReadarrEvent::TestIndexer(self.extract_readarr_indexer_id().await).into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::TestAllIndexers => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::TestAllIndexers.into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::System => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetTasks.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetQueuedEvents.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetLogs(500).into())
|
||||
.await;
|
||||
}
|
||||
ActiveReadarrBlock::SystemUpdates => {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetUpdates.into())
|
||||
.await;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.check_for_readarr_prompt_action().await;
|
||||
self.reset_tick_count();
|
||||
}
|
||||
|
||||
async fn extract_add_new_author_search_query(&self) -> String {
|
||||
self
|
||||
.data
|
||||
.readarr_data
|
||||
.add_author_search
|
||||
.as_ref()
|
||||
.expect("Add author search is empty")
|
||||
.text
|
||||
.clone()
|
||||
}
|
||||
|
||||
async fn extract_author_id(&self) -> i64 {
|
||||
self.data.readarr_data.authors.current_selection().id
|
||||
}
|
||||
|
||||
async fn extract_book_id(&self) -> i64 {
|
||||
self.data.readarr_data.books.current_selection().id
|
||||
}
|
||||
|
||||
async fn extract_readarr_indexer_id(&self) -> i64 {
|
||||
self.data.readarr_data.indexers.current_selection().id
|
||||
}
|
||||
|
||||
async fn check_for_readarr_prompt_action(&mut self) {
|
||||
if self.data.readarr_data.prompt_confirm {
|
||||
self.data.readarr_data.prompt_confirm = false;
|
||||
@@ -28,6 +198,7 @@ impl App<'_> {
|
||||
|
||||
pub(super) async fn readarr_on_tick(&mut self, active_readarr_block: ActiveReadarrBlock) {
|
||||
if self.is_first_render {
|
||||
self.refresh_readarr_metadata().await;
|
||||
self.dispatch_by_readarr_block(&active_readarr_block).await;
|
||||
self.is_first_render = false;
|
||||
return;
|
||||
@@ -35,6 +206,7 @@ impl App<'_> {
|
||||
|
||||
if self.should_refresh {
|
||||
self.dispatch_by_readarr_block(&active_readarr_block).await;
|
||||
self.refresh_readarr_metadata().await;
|
||||
}
|
||||
|
||||
if self.is_routing {
|
||||
@@ -44,5 +216,33 @@ impl App<'_> {
|
||||
self.dispatch_by_readarr_block(&active_readarr_block).await;
|
||||
}
|
||||
}
|
||||
|
||||
if self.tick_count.is_multiple_of(self.tick_until_poll) {
|
||||
self.refresh_readarr_metadata().await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_readarr_metadata(&mut self) {
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetQualityProfiles.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetMetadataProfiles.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetTags.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetRootFolders.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetDownloads(500).into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetDiskSpace.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(ReadarrEvent::GetStatus.into())
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,506 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::app::App;
|
||||
use crate::models::readarr_models::{Author, Book, ReadarrRelease};
|
||||
use crate::models::servarr_data::readarr::modals::BookDetailsModal;
|
||||
use crate::models::servarr_data::readarr::readarr_data::ActiveReadarrBlock;
|
||||
use pretty_assertions::assert_eq;
|
||||
use crate::models::servarr_models::Indexer;
|
||||
use crate::network::NetworkEvent;
|
||||
use crate::network::readarr_network::ReadarrEvent;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_readarr_block_authors() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::Authors)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetMetadataProfiles.into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetTags.into());
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::ListAuthors.into());
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_readarr_block_author_details() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::AuthorDetails)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetBooks(1).into());
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_blocklist_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::Blocklist)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetBlocklist.into());
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_author_history_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::AuthorHistory)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetAuthorHistory(1).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_author_search_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::ManualAuthorSearch)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetAuthorReleases(1).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_author_search_block_author_releases_non_empty() {
|
||||
let mut app = App::test_default();
|
||||
app
|
||||
.data
|
||||
.readarr_data
|
||||
.author_releases
|
||||
.set_items(vec![ReadarrRelease::default()]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::ManualAuthorSearch)
|
||||
.await;
|
||||
|
||||
assert!(!app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_book_details_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
app.data.readarr_data.books.set_items(vec![Book {
|
||||
id: 2,
|
||||
..Book::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::BookDetails)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetBookEditions(2).into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetBookFiles(2).into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_book_history_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
app.data.readarr_data.books.set_items(vec![Book {
|
||||
id: 2,
|
||||
..Book::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::BookHistory)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetBookHistory(1, 2).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_book_history_block_no_op_when_books_table_is_empty() {
|
||||
let (tx, _) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::BookHistory)
|
||||
.await;
|
||||
|
||||
assert!(!app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_book_search_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
app.data.readarr_data.books.set_items(vec![Book {
|
||||
id: 2,
|
||||
..Book::default()
|
||||
}]);
|
||||
app.data.readarr_data.book_details_modal = Some(BookDetailsModal::default());
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::ManualBookSearch)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetBookReleases(2).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_book_search_block_is_loading() {
|
||||
let mut app = App {
|
||||
is_loading: true,
|
||||
..App::test_default()
|
||||
};
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::ManualBookSearch)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_manual_book_search_block_book_releases_non_empty() {
|
||||
let mut app = App::test_default();
|
||||
let mut book_details_modal = BookDetailsModal::default();
|
||||
book_details_modal
|
||||
.book_releases
|
||||
.set_items(vec![ReadarrRelease::default()]);
|
||||
app.data.readarr_data.book_details_modal = Some(book_details_modal);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::ManualBookSearch)
|
||||
.await;
|
||||
|
||||
assert!(!app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_book_edition_details_block_does_not_dispatch() {
|
||||
let mut app = App::test_default_fully_populated();
|
||||
app.data.readarr_data.prompt_confirm = false;
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::BookEditionDetails)
|
||||
.await;
|
||||
|
||||
assert!(!app.is_loading);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_downloads_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::Downloads)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_readarr_block_add_author_search_results() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.add_author_search = Some("test author".into());
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::AddAuthorSearchResults)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::SearchNewAuthor("test author".to_owned()).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_history_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::History)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetHistory(500).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_root_folders_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::RootFolders)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_indexers_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::Indexers)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetTags.into());
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetIndexers.into());
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_all_indexer_settings_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::AllIndexerSettingsPrompt)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetAllIndexerSettings.into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_test_indexer_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.indexers.set_items(vec![Indexer {
|
||||
id: 3,
|
||||
..Indexer::default()
|
||||
}]);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::TestIndexer)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::TestIndexer(3).into()
|
||||
);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_test_all_indexers_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::TestAllIndexers)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::TestAllIndexers.into()
|
||||
);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_system_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::System)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetTasks.into());
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetQueuedEvents.into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetLogs(500).into());
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_system_updates_block() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
|
||||
app
|
||||
.dispatch_by_readarr_block(&ActiveReadarrBlock::SystemUpdates)
|
||||
.await;
|
||||
|
||||
assert!(app.is_loading);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetUpdates.into());
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_dispatch_by_readarr_block_resets_the_tick_count() {
|
||||
@@ -55,21 +553,93 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_first_render() {
|
||||
async fn test_check_for_readarr_prompt_action() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.data.readarr_data.prompt_confirm_action = Some(ReadarrEvent::GetStatus);
|
||||
|
||||
app.check_for_readarr_prompt_action().await;
|
||||
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetStatus.into());
|
||||
assert!(app.should_refresh);
|
||||
assert_eq!(app.data.readarr_data.prompt_confirm_action, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_refresh_metadata() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.is_routing = true;
|
||||
|
||||
app.refresh_readarr_metadata().await;
|
||||
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetMetadataProfiles.into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetTags.into());
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetDiskSpace.into());
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetStatus.into());
|
||||
assert!(app.is_loading);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_first_render() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.is_first_render = true;
|
||||
|
||||
app.readarr_on_tick(ActiveReadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetMetadataProfiles.into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetTags.into());
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetDiskSpace.into());
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetStatus.into());
|
||||
assert!(app.is_loading);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert!(!app.is_first_render);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_routing() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.is_routing = true;
|
||||
app.should_refresh = true;
|
||||
app.is_first_render = false;
|
||||
@@ -77,14 +647,19 @@ mod tests {
|
||||
|
||||
app.readarr_on_tick(ActiveReadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert!(!app.cancellation_token.is_cancelled());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_routing_while_long_request_is_running_should_cancel_request() {
|
||||
let (tx, _) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.is_routing = true;
|
||||
app.should_refresh = false;
|
||||
app.is_first_render = false;
|
||||
@@ -97,16 +672,127 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_should_refresh() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.should_refresh = true;
|
||||
app.is_first_render = false;
|
||||
app.tick_count = 1;
|
||||
|
||||
app.readarr_on_tick(ActiveReadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert!(app.should_refresh);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_should_refresh_does_not_cancel_prompt_requests() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.is_loading = true;
|
||||
app.is_routing = true;
|
||||
app.should_refresh = true;
|
||||
app.is_first_render = false;
|
||||
app.tick_count = 1;
|
||||
|
||||
app.readarr_on_tick(ActiveReadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
assert!(app.should_refresh);
|
||||
assert!(!app.data.readarr_data.prompt_confirm);
|
||||
assert!(!app.cancellation_token.is_cancelled());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_readarr_on_tick_network_tick_frequency() {
|
||||
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.prompt_confirm = true;
|
||||
app.network_tx = Some(tx);
|
||||
app.is_first_render = false;
|
||||
app.tick_count = 2;
|
||||
app.tick_until_poll = 2;
|
||||
|
||||
app.readarr_on_tick(ActiveReadarrBlock::Downloads).await;
|
||||
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetQualityProfiles.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetMetadataProfiles.into()
|
||||
);
|
||||
assert_eq!(rx.recv().await.unwrap(), ReadarrEvent::GetTags.into());
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetRootFolders.into()
|
||||
);
|
||||
assert_eq!(
|
||||
rx.recv().await.unwrap(),
|
||||
ReadarrEvent::GetDownloads(500).into()
|
||||
);
|
||||
assert!(app.is_loading);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_add_new_author_search_query() {
|
||||
let app = App::test_default_fully_populated();
|
||||
|
||||
let query = app.extract_add_new_author_search_query().await;
|
||||
|
||||
assert_str_eq!(query, "Test Author");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic(expected = "Add author search is empty")]
|
||||
async fn test_extract_add_new_author_search_query_panics_when_the_query_is_not_set() {
|
||||
let app = App::test_default();
|
||||
|
||||
app.extract_add_new_author_search_query().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_author_id() {
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.authors.set_items(vec![Author {
|
||||
id: 1,
|
||||
..Author::default()
|
||||
}]);
|
||||
|
||||
assert_eq!(app.extract_author_id().await, 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_book_id() {
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.books.set_items(vec![Book {
|
||||
id: 2,
|
||||
..Book::default()
|
||||
}]);
|
||||
|
||||
assert_eq!(app.extract_book_id().await, 2);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_extract_readarr_indexer_id() {
|
||||
let mut app = App::test_default();
|
||||
app.data.readarr_data.indexers.set_items(vec![Indexer {
|
||||
id: 3,
|
||||
..Indexer::default()
|
||||
}]);
|
||||
|
||||
assert_eq!(app.extract_readarr_indexer_id().await, 3);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user