diff --git a/.cargo-husky/hooks/pre-commit b/.cargo-husky/hooks/pre-commit index 91a6fe1..cb8a69e 100755 --- a/.cargo-husky/hooks/pre-commit +++ b/.cargo-husky/hooks/pre-commit @@ -7,8 +7,5 @@ echo "Running pre-push hook:" echo "Executing: cargo fmt" cargo fmt -echo "Executing: make lint" -make lint - -echo "Executing: cargo test" -cargo test +echo "Executing: cargo clippy --all" +cargo clippy --all diff --git a/.cargo-husky/hooks/pre-push b/.cargo-husky/hooks/pre-push index 1160efc..c976c2f 100755 --- a/.cargo-husky/hooks/pre-push +++ b/.cargo-husky/hooks/pre-push @@ -7,8 +7,8 @@ echo "Running pre-push hook:" echo "Executing: cargo fmt --check" cargo fmt --check -echo "Executing: make lint" -make lint +echo "Executing: cargo clippy --all" +cargo clippy --all -echo "Executing: cargo test" -cargo test +echo "Executing: cargo test --all" +cargo test --all diff --git a/.helix/config.toml b/.helix/config.toml new file mode 100644 index 0000000..68c2069 --- /dev/null +++ b/.helix/config.toml @@ -0,0 +1,5 @@ +[keys.normal.backspace] +b = ":sh zellij run -x '4%%' --width '92%%' -f -n Build -- just build" +r = ":sh zellij run -x '3%%' -y '8%%' --width '95%%' --height '90%%' -fc -n 'Run' -- just run" +t = ":sh zellij run -x '4%%' --width '92%%' -f -n Tests -- just test" +l = ":sh zellij run -x '4%%' --width '92%%' -f -n Lint -- just lint" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 729d9b5..b10dbe0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,8 @@ cz commit 1. Clone this repo 2. Run `cargo test` to set up hooks 3. Make changes -4. Run the application using `make run` or `cargo run` +4. Run the application using `just run` or `just run` + - Install `just` (`cargo install just`) if you haven't already to use the [justfile](./justfile) in this project. 5. Commit changes. This will trigger pre-commit hooks that will run format, test and lint. If there are errors or warnings from Clippy, please fix them. 6. Push your code to a new branch named after the feature/bug/etc. you're adding. This will trigger pre-push hooks that will run lint and test. 7. Create a PR diff --git a/Cargo.lock b/Cargo.lock index f838a4e..ccbfb24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,12 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "assertables" +version = "9.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59051ec02907378a67b0ba1b8631121f5388c8dbbb3cec8c749d8f93c2c3c211" + [[package]] name = "async-trait" version = "0.1.89" @@ -181,6 +187,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "2.10.0" @@ -1211,6 +1232,17 @@ dependencies = [ "rustversion", ] +[[package]] +name = "insta" +version = "1.44.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5c943d4415edd8153251b6f197de5eb1640e56d84e8d9159bea190421c73698" +dependencies = [ + "console", + "once_cell", + "similar", +] + [[package]] name = "instability" version = "0.3.10" @@ -1382,6 +1414,7 @@ version = "0.6.3" dependencies = [ "anyhow", "assert_cmd", + "assertables", "async-trait", "backtrace", "bimap", @@ -1401,6 +1434,7 @@ dependencies = [ "human-panic", "indicatif", "indoc", + "insta", "itertools 0.14.0", "log", "log4rs", @@ -1408,8 +1442,8 @@ dependencies = [ "mockall", "mockito", "openssl", - "paste", "pretty_assertions", + "proptest", "ratatui", "regex", "reqwest", @@ -1837,9 +1871,9 @@ dependencies = [ [[package]] name = "os_info" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c39b5918402d564846d5aba164c09a66cc88d232179dfd3e3c619a25a268392" +checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" dependencies = [ "android_system_properties", "log", @@ -1989,6 +2023,31 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.42" @@ -2033,6 +2092,15 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core", +] + [[package]] name = "ratatui" version = "0.29.0" @@ -2274,6 +2342,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "ryu" version = "1.0.20" @@ -2922,6 +3002,12 @@ dependencies = [ "unsafe-any-ors", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.22" diff --git a/Cargo.toml b/Cargo.toml index 23768cc..d39823f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ documentation = "https://github.com/Dark-Alex-17/managarr" repository = "https://github.com/Dark-Alex-17/managarr" homepage = "https://github.com/Dark-Alex-17/managarr" readme = "README.md" -edition = "2021" +edition = "2024" license = "MIT" rust-version = "1.89.0" exclude = [".github", "CONTRIBUTING.md", "*.log", "tags"] @@ -63,7 +63,6 @@ managarr-tree-widget = "0.24.0" indicatif = "0.17.9" derive_setters = "0.1.6" deunicode = "1.6.0" -paste = "1.0.15" openssl = { version = "0.10.70", features = ["vendored"] } veil = "0.2.0" validate_theme_derive = "0.1.0" @@ -74,8 +73,11 @@ assert_cmd = "2.0.16" mockall = "0.13.0" mockito = "1.0.0" pretty_assertions = "1.3.0" +proptest = "1.6.0" rstest = "0.25.0" serial_test = "3.2.0" +assertables = "9.8.2" +insta = "1.41.1" [dev-dependencies.cargo-husky] version = "1" diff --git a/Makefile b/Makefile deleted file mode 100644 index 31fce58..0000000 --- a/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -#!make -VERSION := latest -IMG_NAME := darkalex17/managarr -IMAGE := ${IMG_NAME}:${VERSION} - -default: run - -.PHONY: test test-cov build run lint lint-fix fmt analyze sonar release delete-tag - -test: - @cargo test --all - -## Run all tests with coverage - `cargo install cargo-tarpaulin` -test-cov: - @cargo tarpaulin - -build: test - @cargo build --release - -docker: - @DOCKER_BUILDKIT=1 docker build --rm -t ${IMAGE} . - -run: - @CARGO_INCREMENTAL=1 cargo fmt && make lint && cargo run - -lint: - @find . | grep '\.\/src\/.*\.rs$$' | xargs touch && CARGO_INCREMENTAL=0 cargo clippy --all-targets --workspace - -lint-fix: - @cargo fix - -fmt: - @cargo fmt - -minimal-versions: - @cargo +nightly update -Zdirect-minimal-versions - -## Analyze for unsafe usage - `cargo install cargo-geiger` -analyze: - @cargo geiger - -release: - @git tag -a ${V} -m "Release ${V}" && git push origin ${V} - -delete-tag: - @git tag -d ${V} && git push --delete origin ${V} - diff --git a/codecov.yml b/codecov.yml index 960aad7..2076d3b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -12,4 +12,3 @@ coverage: ignore: - "**/*_tests.rs" - - "src/ui" diff --git a/justfile b/justfile new file mode 100644 index 0000000..c64cf55 --- /dev/null +++ b/justfile @@ -0,0 +1,91 @@ +VERSION := "latest" +IMG_NAME := "darkalex17/managarr" +IMAGE := "{{IMG_NAME}}:{{VERSION}}" + + +# List all recipes +default: + @just --list + +# Format all files +[group: 'style'] +fmt: + @cargo fmt --all + +alias clippy := lint +# Run Clippy to inspect all files +[group: 'style'] +lint: + @cargo clippy --all + +alias clippy-fix := lint-fix +# Automatically fix clippy issues where possible +[group: 'style'] +lint-fix: + @cargo fix + +# Analyze the project for unsafe usage +[group: 'style'] +@analyze: + #!/usr/bin/env bash + cargo geiger -h > /dev/null 2>&1 | cargo install cargo-geiger + cargo geiger + +# Run all tests +[group: 'test'] +test: + @cargo test --all + +# Run all tests with coverage +[group:'test'] +@test-cov: + #!/usr/bin/env bash + cargo tarpaulin -h > /dev/null 2>&1 || cargo install cargo-tarpaulin + cargo tarpaulin + +# Run all doc tests +[group: 'test'] +doctest: + @cargo test --all --doc + +# Run all proptests +[group: 'test'] +proptest: + @cargo test proptest + +alias test-snapshots := snapshot-tests +# Run all snapshot tests +[group: 'test'] +snapshot-tests: + @cargo test snapshot + +alias review := snapshot-review +# Review snapshot test changes +[group: 'test'] +@snapshot-review: + #!/usr/bin/env bash + cargo insta -h > /dev/null 2>&1 || cargo install cargo-insta + cargo insta review + +alias clean-orphaned-snapshots := snapshot-delete-unreferenced +# Delete any unreferenced snapshots +[group: 'test'] +@snapshot-delete-unreferenced: + #!/usr/bin/env bash + cargo insta -h > /dev/null 2>&1 || cargo install cargo-insta + cargo insta test --unreferenced=delete + +# Build and run the binary for the current system +run: + @cargo run + +# Build the project for the current system architecture +[group: 'build'] +[arg('build_type', pattern="debug|release")] +build build_type='debug': + @cargo build {{ if build_type == "release" { "--release" } else { "" } }} + +# Build the docker image +[group: 'build'] +build-docker: + @DOCKER_BUILDKIT=1 docker build --rm -t {{IMAGE}} diff --git a/proptest-regressions/handlers/handler_proptest.txt b/proptest-regressions/handlers/handler_proptest.txt new file mode 100644 index 0000000..d088279 --- /dev/null +++ b/proptest-regressions/handlers/handler_proptest.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 56330c025ad79db641d0eb9f429ab74e95822e1fb015b58f0e158ea674cd42a1 # shrinks to list_size = 1, page_ops = 1 diff --git a/proptest-regressions/handlers/table_handler_tests.txt b/proptest-regressions/handlers/table_handler_tests.txt new file mode 100644 index 0000000..4d42bee --- /dev/null +++ b/proptest-regressions/handlers/table_handler_tests.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc fb4b58aa3015a125fc33a78dfaf27981db4191247151b327a351fc445e07c231 # shrinks to input = "j" +cc d6ec17d4d3f635f0a095ade650a316d26abc1f9fe2b6d9cf67bf2f8b4ebedb60 # shrinks to backspace_count = 0 +cc cd46ee46e18cf86c940fb89c7206f0b482909880b8f2eabe3dd20682b9912c8a # shrinks to input = "h" diff --git a/proptest-regressions/ui/ui_property_tests.txt b/proptest-regressions/ui/ui_property_tests.txt new file mode 100644 index 0000000..621f11a --- /dev/null +++ b/proptest-regressions/ui/ui_property_tests.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 24ae243412a324cb46c36cb4f629ddd4c9326b1479d1186d9b5545ac5e86dbba # shrinks to num_scroll_attempts = 0 +cc c06a1cc1e4740b2498c50d7be64715bf09ef3ac4cf3bb3642f960578a3e06c74 # shrinks to is_loading = false, num_items = 1 +cc 930207899afea2d389c7fa3974e31c2eb1803e71bcbd8179246c795903905ec7 # shrinks to parent_width = 20, parent_height = 12, percent_x = 1, percent_y = 1 diff --git a/src/app/app_tests.rs b/src/app/app_tests.rs index bda0636..b9a8a85 100644 --- a/src/app/app_tests.rs +++ b/src/app/app_tests.rs @@ -7,12 +7,12 @@ mod tests { use serial_test::serial; use tokio::sync::mpsc; - use crate::app::{interpolate_env_vars, App, AppConfig, Data, ServarrConfig}; + use crate::app::{App, AppConfig, Data, ServarrConfig, interpolate_env_vars}; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}; use crate::models::{HorizontallyScrollableText, TabRoute}; - use crate::network::radarr_network::RadarrEvent; use crate::network::NetworkEvent; + use crate::network::radarr_network::RadarrEvent; use tokio_util::sync::CancellationToken; #[test] @@ -69,9 +69,9 @@ mod tests { CancellationToken::new(), ); - assert!(app.navigation_stack.is_empty()); + assert_is_empty!(app.navigation_stack); assert_eq!(app.get_current_route(), ActiveSonarrBlock::default().into()); - assert!(app.network_tx.is_some()); + assert_some!(app.network_tx); assert!(!app.cancellation_token.is_cancelled()); assert!(app.is_first_render); assert_eq!(app.error, HorizontallyScrollableText::default()); @@ -91,8 +91,8 @@ mod tests { fn test_app_default() { let app = App::default(); - assert!(app.navigation_stack.is_empty()); - assert!(app.network_tx.is_none()); + assert_is_empty!(app.navigation_stack); + assert_none!(app.network_tx); assert!(!app.cancellation_token.is_cancelled()); assert!(app.is_first_render); assert_eq!(app.error, HorizontallyScrollableText::default()); @@ -326,23 +326,23 @@ mod tests { fn test_app_config_default() { let app_config = AppConfig::default(); - assert!(app_config.radarr.is_none()); - assert!(app_config.sonarr.is_none()); + assert_none!(app_config.radarr); + assert_none!(app_config.sonarr); } #[test] fn test_servarr_config_default() { let servarr_config = ServarrConfig::default(); - assert_eq!(servarr_config.name, None); - assert_eq!(servarr_config.host, Some("localhost".to_string())); - assert_eq!(servarr_config.port, None); - assert_eq!(servarr_config.uri, None); - assert_eq!(servarr_config.weight, None); - assert_eq!(servarr_config.api_token, Some(String::new())); - assert_eq!(servarr_config.api_token_file, None); - assert_eq!(servarr_config.ssl_cert_path, None); - assert_eq!(servarr_config.custom_headers, None); + assert_none!(servarr_config.name); + assert_some_eq_x!(&servarr_config.host, "localhost"); + assert_none!(servarr_config.port); + assert_none!(servarr_config.uri); + assert_none!(servarr_config.weight); + assert_some_eq_x!(&servarr_config.api_token, ""); + assert_none!(servarr_config.api_token_file); + assert_none!(servarr_config.ssl_cert_path); + assert_none!(servarr_config.custom_headers); } #[test] @@ -367,11 +367,11 @@ mod tests { assert!(custom.is_object()); let obj = custom.as_object().unwrap(); - assert_eq!(obj.get("x-api-key").unwrap(), "abc123"); - assert_eq!(obj.get("header-1").unwrap(), "test"); + assert_some_eq_x!(obj.get("x-api-key"), "abc123"); + assert_some_eq_x!(obj.get("header-1"), "test"); - assert!(obj.get("X-Api-Key").is_none()); - assert!(obj.get("HEADER-1").is_none()); + assert_none!(obj.get("X-Api-Key")); + assert_none!(obj.get("HEADER-1")); } #[test] @@ -392,7 +392,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.host, Some("localhost".to_string())); + assert_some_eq_x!(&config.host, "localhost"); unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION") }; } @@ -407,7 +407,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.host, Some("www.example.com".to_string())); + assert_some_eq_x!(&config.host, "www.example.com"); unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION_NO_OVERWRITE") }; } @@ -419,7 +419,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.port, None); + assert_none!(config.port); } #[test] @@ -440,7 +440,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.custom_headers, Some(expected_custom_headers)); + assert_some_eq_x!(&config.custom_headers, &expected_custom_headers); unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_HEADER_OPTION") }; } @@ -467,7 +467,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.custom_headers, Some(expected_custom_headers)); + assert_some_eq_x!(&config.custom_headers, &expected_custom_headers); unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_HEADER_OPTION_NO_OVERWRITE") }; } @@ -479,7 +479,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.custom_headers, None); + assert_none!(config.custom_headers); } #[test] @@ -493,7 +493,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.port, Some(1)); + assert_some_eq_x!(config.port, 1); unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION_U16") }; } @@ -508,7 +508,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.port, Some(1234)); + assert_some_eq_x!(config.port, 1234); unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION_U16_UNUSED") }; } @@ -520,9 +520,9 @@ mod tests { "#; let result: Result = serde_yaml::from_str(yaml_data); - assert!(result.is_err()); + assert_err!(&result); let err = result.unwrap_err().to_string(); - assert!(err.contains("invalid digit found in string")); + assert_contains!(err, "invalid digit found in string"); } #[test] @@ -533,7 +533,7 @@ mod tests { let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap(); - assert_eq!(config.port, None); + assert_none!(config.port); } #[test] @@ -597,7 +597,9 @@ mod tests { let ssl_cert_path = "/some/path".to_owned(); let mut custom_headers = HeaderMap::new(); custom_headers.insert("X-Custom-Header", "value".parse().unwrap()); - let expected_str = format!("ServarrConfig {{ name: Some(\"{name}\"), host: Some(\"{host}\"), port: Some({port}), uri: Some(\"{uri}\"), weight: Some({weight}), api_token: Some(\"***********\"), api_token_file: Some(\"{api_token_file}\"), ssl_cert_path: Some(\"{ssl_cert_path}\"), custom_headers: Some({{\"x-custom-header\": \"value\"}}) }}"); + let expected_str = format!( + "ServarrConfig {{ name: Some(\"{name}\"), host: Some(\"{host}\"), port: Some({port}), uri: Some(\"{uri}\"), weight: Some({weight}), api_token: Some(\"***********\"), api_token_file: Some(\"{api_token_file}\"), ssl_cert_path: Some(\"{ssl_cert_path}\"), custom_headers: Some({{\"x-custom-header\": \"value\"}}) }}" + ); let servarr_config = ServarrConfig { name: Some(name), host: Some(host), diff --git a/src/app/context_clues.rs b/src/app/context_clues.rs index b4a03ab..f58f901 100644 --- a/src/app/context_clues.rs +++ b/src/app/context_clues.rs @@ -1,7 +1,7 @@ -use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS}; +use crate::app::App; +use crate::app::key_binding::{DEFAULT_KEYBINDINGS, KeyBinding}; use crate::app::radarr::radarr_context_clues::RadarrContextClueProvider; use crate::app::sonarr::sonarr_context_clues::SonarrContextClueProvider; -use crate::app::App; use crate::models::Route; #[cfg(test)] diff --git a/src/app/context_clues_tests.rs b/src/app/context_clues_tests.rs index d5be326..ff435ad 100644 --- a/src/app/context_clues_tests.rs +++ b/src/app/context_clues_tests.rs @@ -1,239 +1,237 @@ #[cfg(test)] mod test { - use pretty_assertions::{assert_eq, assert_str_eq}; - use crate::app::context_clues::{ - ContextClueProvider, ServarrContextClueProvider, BARE_POPUP_CONTEXT_CLUES, - BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, - INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SERVARR_CONTEXT_CLUES, - SYSTEM_CONTEXT_CLUES, + BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, + ContextClueProvider, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, + ROOT_FOLDERS_CONTEXT_CLUES, SERVARR_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, + ServarrContextClueProvider, }; - use crate::app::{key_binding::DEFAULT_KEYBINDINGS, App}; + use crate::app::{App, key_binding::DEFAULT_KEYBINDINGS}; + use crate::models::servarr_data::ActiveKeybindingBlock; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; - use crate::models::servarr_data::ActiveKeybindingBlock; #[test] fn test_servarr_context_clues() { let mut servarr_context_clues_iter = SERVARR_CONTEXT_CLUES.iter(); - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.up); - assert_str_eq!(*description, "scroll up"); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.down); - assert_str_eq!(*description, "scroll down"); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.left); - assert_str_eq!(*description, "previous tab"); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.right); - assert_str_eq!(*description, "next tab"); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.pg_up); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.pg_up.desc); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.pg_down); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.pg_down.desc); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.next_servarr); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.next_servarr.desc); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.previous_servarr); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.previous_servarr.desc); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.quit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.quit.desc); - - let (key_binding, description) = servarr_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.help); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.help.desc); - assert_eq!(servarr_context_clues_iter.next(), None); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.up, "scroll up") + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.down, "scroll down") + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.left, "previous tab") + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.right, "next tab") + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.pg_up, DEFAULT_KEYBINDINGS.pg_up.desc) + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.pg_down, + DEFAULT_KEYBINDINGS.pg_down.desc + ) + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.next_servarr, + DEFAULT_KEYBINDINGS.next_servarr.desc + ) + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.previous_servarr, + DEFAULT_KEYBINDINGS.previous_servarr.desc + ) + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.quit, DEFAULT_KEYBINDINGS.quit.desc) + ); + assert_some_eq_x!( + servarr_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.help, DEFAULT_KEYBINDINGS.help.desc) + ); + assert_none!(servarr_context_clues_iter.next()); } #[test] fn test_bare_popup_context_clues() { let mut bare_popup_context_clues_iter = BARE_POPUP_CONTEXT_CLUES.iter(); - let (key_binding, description) = bare_popup_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(bare_popup_context_clues_iter.next(), None); + assert_some_eq_x!( + bare_popup_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(bare_popup_context_clues_iter.next()); } #[test] fn test_downloads_context_clues() { let mut downloads_context_clues_iter = DOWNLOADS_CONTEXT_CLUES.iter(); - let (key_binding, description) = downloads_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = downloads_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc); - - let (key_binding, description) = downloads_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, "update downloads"); - assert_eq!(downloads_context_clues_iter.next(), None); + assert_some_eq_x!( + downloads_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + downloads_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc) + ); + assert_some_eq_x!( + downloads_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, "update downloads") + ); + assert_none!(downloads_context_clues_iter.next()); } #[test] fn test_blocklist_context_clues() { let mut blocklist_context_clues_iter = BLOCKLIST_CONTEXT_CLUES.iter(); - let (key_binding, description) = blocklist_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = blocklist_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = blocklist_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = blocklist_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc); - - let (key_binding, description) = blocklist_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.clear); - assert_str_eq!(*description, "clear blocklist"); - assert_eq!(blocklist_context_clues_iter.next(), None); + assert_some_eq_x!( + blocklist_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + blocklist_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + blocklist_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + blocklist_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc) + ); + assert_some_eq_x!( + blocklist_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.clear, "clear blocklist") + ); + assert_none!(blocklist_context_clues_iter.next()); } #[test] fn test_confirmation_prompt_context_clues() { let mut confirmation_prompt_context_clues_iter = CONFIRMATION_PROMPT_CONTEXT_CLUES.iter(); - let (key_binding, description) = confirmation_prompt_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.confirm); - assert_str_eq!(*description, "submit"); - - let (key_binding, description) = confirmation_prompt_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel"); - assert_eq!(confirmation_prompt_context_clues_iter.next(), None); + assert_some_eq_x!( + confirmation_prompt_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.confirm, "submit") + ); + assert_some_eq_x!( + confirmation_prompt_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel") + ); + assert_none!(confirmation_prompt_context_clues_iter.next()); } #[test] fn test_root_folders_context_clues() { let mut root_folders_context_clues_iter = ROOT_FOLDERS_CONTEXT_CLUES.iter(); - let (key_binding, description) = root_folders_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.add); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.add.desc); - - let (key_binding, description) = root_folders_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc); - - let (key_binding, description) = root_folders_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - assert_eq!(root_folders_context_clues_iter.next(), None); + assert_some_eq_x!( + root_folders_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc) + ); + assert_some_eq_x!( + root_folders_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc) + ); + assert_some_eq_x!( + root_folders_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_none!(root_folders_context_clues_iter.next()); } #[test] fn test_indexers_context_clues() { let mut indexers_context_clues_iter = INDEXERS_CONTEXT_CLUES.iter(); - let (key_binding, description) = indexers_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "edit indexer"); - - let (key_binding, description) = indexers_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.settings); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.settings.desc); - - let (key_binding, description) = indexers_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc); - - let (key_binding, description) = indexers_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.test); - assert_str_eq!(*description, "test indexer"); - - let (key_binding, description) = indexers_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.test_all); - assert_str_eq!(*description, "test all indexers"); - - let (key_binding, description) = indexers_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - assert_eq!(indexers_context_clues_iter.next(), None); + assert_some_eq_x!( + indexers_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "edit indexer") + ); + assert_some_eq_x!( + indexers_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.settings, + DEFAULT_KEYBINDINGS.settings.desc + ) + ); + assert_some_eq_x!( + indexers_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc) + ); + assert_some_eq_x!( + indexers_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.test, "test indexer") + ); + assert_some_eq_x!( + indexers_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.test_all, "test all indexers") + ); + assert_some_eq_x!( + indexers_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_none!(indexers_context_clues_iter.next()); } #[test] fn test_system_context_clues() { let mut system_context_clues_iter = SYSTEM_CONTEXT_CLUES.iter(); - let (key_binding, description) = system_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.tasks); - assert_str_eq!(*description, "open tasks"); - - let (key_binding, description) = system_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.events); - assert_str_eq!(*description, "open events"); - - let (key_binding, description) = system_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.logs); - assert_str_eq!(*description, "open logs"); - - let (key_binding, description) = system_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, "open updates"); - - let (key_binding, description) = system_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - assert_eq!(system_context_clues_iter.next(), None); + assert_some_eq_x!( + system_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.tasks, "open tasks") + ); + assert_some_eq_x!( + system_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.events, "open events") + ); + assert_some_eq_x!( + system_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.logs, "open logs") + ); + assert_some_eq_x!( + system_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, "open updates") + ); + assert_some_eq_x!( + system_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_none!(system_context_clues_iter.next()); } #[test] @@ -243,10 +241,9 @@ mod test { let context_clues = ServarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!( + assert_some_eq_x!( + context_clues, &crate::app::radarr::radarr_context_clues::SYSTEM_TASKS_CONTEXT_CLUES, - context_clues.unwrap() ); } @@ -257,10 +254,9 @@ mod test { let context_clues = ServarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!( + assert_some_eq_x!( + context_clues, &crate::app::sonarr::sonarr_context_clues::SYSTEM_TASKS_CONTEXT_CLUES, - context_clues.unwrap() ); } @@ -271,6 +267,6 @@ mod test { let context_clues = ServarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_none()); + assert_none!(context_clues); } } diff --git a/src/app/key_binding_tests.rs b/src/app/key_binding_tests.rs index a5357f3..7db6501 100644 --- a/src/app/key_binding_tests.rs +++ b/src/app/key_binding_tests.rs @@ -3,7 +3,7 @@ mod test { use pretty_assertions::{assert_eq, assert_str_eq}; use rstest::rstest; - use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS}; + use crate::app::key_binding::{DEFAULT_KEYBINDINGS, KeyBinding}; use crate::event::Key; use crate::matches_key; diff --git a/src/app/mod.rs b/src/app/mod.rs index 2eb28e6..efb05b8 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Error, Result}; +use anyhow::{Error, Result, anyhow}; use colored::Colorize; use itertools::Itertools; use log::{debug, error}; @@ -21,7 +21,6 @@ use crate::models::{HorizontallyScrollableText, Route, TabRoute, TabState}; use crate::network::NetworkEvent; #[cfg(test)] -#[path = "app_tests.rs"] mod app_tests; pub mod context_clues; pub mod key_binding; @@ -57,42 +56,43 @@ impl App<'_> { let mut server_tabs = Vec::new(); if let Some(radarr_configs) = config.radarr { - let mut idx = 0; - for radarr_config in radarr_configs { + let mut unnamed_idx = 0; + let radarr_tabs = radarr_configs.into_iter().map(|radarr_config| { let name = if let Some(name) = radarr_config.name.clone() { name } else { - idx += 1; - format!("Radarr {idx}") + unnamed_idx += 1; + format!("Radarr {unnamed_idx}") }; - server_tabs.push(TabRoute { + TabRoute { title: name, route: ActiveRadarrBlock::Movies.into(), contextual_help: None, config: Some(radarr_config), - }); - } + } + }); + server_tabs.extend(radarr_tabs); } if let Some(sonarr_configs) = config.sonarr { - let mut idx = 0; - - for sonarr_config in sonarr_configs { + let mut unnamed_idx = 0; + let sonarr_tabs = sonarr_configs.into_iter().map(|sonarr_config| { let name = if let Some(name) = sonarr_config.name.clone() { name } else { - idx += 1; - format!("Sonarr {idx}") + unnamed_idx += 1; + format!("Sonarr {unnamed_idx}") }; - server_tabs.push(TabRoute { + TabRoute { title: name, route: ActiveSonarrBlock::Series.into(), contextual_help: None, config: Some(sonarr_config), - }); - } + } + }); + server_tabs.extend(sonarr_tabs); } let weight_sorted_tabs = server_tabs @@ -132,12 +132,12 @@ impl App<'_> { self.is_loading = true; } - if let Some(network_tx) = &self.network_tx { - if let Err(e) = network_tx.send(action).await { - self.is_loading = false; - error!("Failed to send event. {e:?}"); - self.handle_error(anyhow!(e)); - } + if let Some(network_tx) = &self.network_tx + && let Err(e) = network_tx.send(action).await + { + self.is_loading = false; + error!("Failed to send event. {e:?}"); + self.handle_error(anyhow!(e)); } } @@ -203,10 +203,14 @@ impl App<'_> { } pub fn get_current_route(&self) -> Route { - *self - .navigation_stack - .last() - .unwrap_or(&self.server_tabs.tabs.first().unwrap().route) + *self.navigation_stack.last().unwrap_or( + &self + .server_tabs + .tabs + .first() + .expect("At least one server tab must exist") + .route, + ) } } @@ -254,6 +258,30 @@ impl App<'_> { ..App::default() } } + + pub fn test_default_fully_populated() -> Self { + App { + data: Data { + radarr_data: RadarrData::test_default_fully_populated(), + sonarr_data: SonarrData::test_default_fully_populated(), + }, + server_tabs: TabState::new(vec![ + TabRoute { + title: "Radarr".to_owned(), + route: ActiveRadarrBlock::Movies.into(), + contextual_help: None, + config: Some(ServarrConfig::default()), + }, + TabRoute { + title: "Sonarr".to_owned(), + route: ActiveSonarrBlock::Series.into(), + contextual_help: None, + config: Some(ServarrConfig::default()), + }, + ]), + ..App::default() + } + } } #[derive(Default)] @@ -477,15 +505,15 @@ where fn interpolate_env_vars(s: &str) -> String { let result = s.to_string(); - let scrubbing_regex = Regex::new(r#"[\s\{\}!\$^\(\)\[\]\\\|`'"]+"#).unwrap(); - let var_regex = Regex::new(r"\$\{(.*?)\}").unwrap(); + let scrubbing_regex = Regex::new(r#"[\s{}!$^()\[\]\\|`'"]+"#).unwrap(); + let var_regex = Regex::new(r"\$\{(.*?)}").unwrap(); var_regex .replace_all(s, |caps: ®ex::Captures<'_>| { - if let Some(mat) = caps.get(1) { - if let Ok(value) = std::env::var(mat.as_str()) { - return scrubbing_regex.replace_all(&value, "").to_string(); - } + if let Some(mat) = caps.get(1) + && let Ok(value) = std::env::var(mat.as_str()) + { + return scrubbing_regex.replace_all(&value, "").to_string(); } scrubbing_regex.replace_all(&result, "").to_string() diff --git a/src/app/radarr/radarr_context_clues.rs b/src/app/radarr/radarr_context_clues.rs index 68d2823..04f17aa 100644 --- a/src/app/radarr/radarr_context_clues.rs +++ b/src/app/radarr/radarr_context_clues.rs @@ -1,13 +1,13 @@ +use crate::app::App; use crate::app::context_clues::{ - ContextClue, ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, + BARE_POPUP_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, ContextClue, ContextClueProvider, }; use crate::app::key_binding::DEFAULT_KEYBINDINGS; -use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, ADD_MOVIE_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_INDEXER_BLOCKS, + ADD_MOVIE_BLOCKS, ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_MOVIE_BLOCKS, INDEXER_SETTINGS_BLOCKS, MOVIE_DETAILS_BLOCKS, }; -use crate::models::Route; #[cfg(test)] #[path = "radarr_context_clues_tests.rs"] diff --git a/src/app/radarr/radarr_context_clues_tests.rs b/src/app/radarr/radarr_context_clues_tests.rs index b98c5b5..d5fbca9 100644 --- a/src/app/radarr/radarr_context_clues_tests.rs +++ b/src/app/radarr/radarr_context_clues_tests.rs @@ -1,126 +1,118 @@ #[cfg(test)] mod tests { + use crate::app::App; use crate::app::context_clues::{ - ContextClue, ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, - CONFIRMATION_PROMPT_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, + BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, + ContextClue, ContextClueProvider, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, }; use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::radarr::radarr_context_clues::{ - RadarrContextClueProvider, ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, COLLECTIONS_CONTEXT_CLUES, - COLLECTION_DETAILS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES, - MOVIE_DETAILS_CONTEXT_CLUES, SYSTEM_TASKS_CONTEXT_CLUES, + ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, COLLECTION_DETAILS_CONTEXT_CLUES, + COLLECTIONS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES, + MOVIE_DETAILS_CONTEXT_CLUES, RadarrContextClueProvider, SYSTEM_TASKS_CONTEXT_CLUES, }; - use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; - use pretty_assertions::{assert_eq, assert_str_eq}; + use pretty_assertions::assert_eq; use rstest::rstest; #[test] fn test_library_context_clues() { let mut library_context_clues_iter = LIBRARY_CONTEXT_CLUES.iter(); - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.add); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.add.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.toggle_monitoring); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.toggle_monitoring.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, "update all"); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = library_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel filter"); - assert_eq!(library_context_clues_iter.next(), None); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.toggle_monitoring, + DEFAULT_KEYBINDINGS.toggle_monitoring.desc + ) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, "update all") + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + library_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel filter") + ); + assert_none!(library_context_clues_iter.next()); } #[test] fn test_collections_context_clues() { let mut collections_context_clues = COLLECTIONS_CONTEXT_CLUES.iter(); - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, "update all"); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = collections_context_clues.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel filter"); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc) + ); + assert_some_eq_x!( + collections_context_clues.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.update, "update all") + ); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + collections_context_clues.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel filter") + ); assert_eq!(collections_context_clues.next(), None); } @@ -128,30 +120,32 @@ mod tests { fn test_movie_details_context_clues() { let mut movie_details_context_clues_iter = MOVIE_DETAILS_CONTEXT_CLUES.iter(); - let (key_binding, description) = movie_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = movie_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.update.desc); - - let (key_binding, description) = movie_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = movie_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = movie_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); + assert_some_eq_x!( + movie_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + movie_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, DEFAULT_KEYBINDINGS.update.desc) + ); + assert_some_eq_x!( + movie_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + movie_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + movie_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); assert_eq!(movie_details_context_clues_iter.next(), None); } @@ -159,41 +153,40 @@ mod tests { fn test_manual_movie_search_context_clues() { let mut manual_movie_search_context_clues_iter = MANUAL_MOVIE_SEARCH_CONTEXT_CLUES.iter(); - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.update.desc); - - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, DEFAULT_KEYBINDINGS.update.desc) + ); + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + manual_movie_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); assert_eq!(manual_movie_search_context_clues_iter.next(), None); } @@ -202,15 +195,14 @@ mod tests { let mut add_movie_search_results_context_clues_iter = ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES.iter(); - let (key_binding, description) = add_movie_search_results_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = add_movie_search_results_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "edit search"); + assert_some_eq_x!( + add_movie_search_results_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + add_movie_search_results_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "edit search") + ); assert_eq!(add_movie_search_results_context_clues_iter.next(), None); } @@ -218,15 +210,14 @@ mod tests { fn test_system_tasks_context_clues() { let mut system_tasks_context_clues_iter = SYSTEM_TASKS_CONTEXT_CLUES.iter(); - let (key_binding, description) = system_tasks_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "start task"); - - let (key_binding, description) = system_tasks_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); + assert_some_eq_x!( + system_tasks_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "start task") + ); + assert_some_eq_x!( + system_tasks_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); assert_eq!(system_tasks_context_clues_iter.next(), None); } @@ -234,20 +225,18 @@ mod tests { fn test_collection_details_context_clues() { let mut collection_details_context_clues_iter = COLLECTION_DETAILS_CONTEXT_CLUES.iter(); - let (key_binding, description) = collection_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "show overview/add movie"); - - let (key_binding, description) = collection_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, "edit collection"); - - let (key_binding, description) = collection_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); + assert_some_eq_x!( + collection_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "show overview/add movie") + ); + assert_some_eq_x!( + collection_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, "edit collection") + ); + assert_some_eq_x!( + collection_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); assert_eq!(collection_details_context_clues_iter.next(), None); } @@ -283,8 +272,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&BARE_POPUP_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &BARE_POPUP_CONTEXT_CLUES); } #[rstest] @@ -306,8 +294,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(expected_context_clues, context_clues.unwrap()); + assert_some_eq_x!(context_clues, expected_context_clues); } #[rstest] @@ -329,8 +316,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -352,8 +338,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -379,8 +364,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -405,8 +389,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -428,8 +411,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -446,11 +428,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!( - &ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, - context_clues.unwrap() - ); + assert_some_eq_x!(context_clues, &ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES); } #[test] @@ -461,8 +439,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&COLLECTION_DETAILS_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &COLLECTION_DETAILS_CONTEXT_CLUES); } #[test] @@ -474,8 +451,7 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(&SYSTEM_TASKS_CONTEXT_CLUES, context_clues.unwrap()); + assert_some_eq_x!(context_clues, &SYSTEM_TASKS_CONTEXT_CLUES); } #[rstest] @@ -498,7 +474,6 @@ mod tests { let context_clues = RadarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(expected_context_clues, context_clues.unwrap()); + assert_some_eq_x!(context_clues, expected_context_clues); } } diff --git a/src/app/radarr/radarr_tests.rs b/src/app/radarr/radarr_tests.rs index 9218162..e4d1f9b 100644 --- a/src/app/radarr/radarr_tests.rs +++ b/src/app/radarr/radarr_tests.rs @@ -3,15 +3,15 @@ mod tests { use pretty_assertions::assert_eq; use tokio::sync::mpsc; - use crate::app::radarr::ActiveRadarrBlock; use crate::app::App; + use crate::app::radarr::ActiveRadarrBlock; use crate::models::radarr_models::{ AddMovieBody, AddMovieOptions, Collection, CollectionMovie, Credit, Movie, RadarrRelease, }; use crate::models::servarr_data::radarr::modals::MovieDetailsModal; use crate::models::servarr_models::Indexer; - use crate::network::radarr_network::RadarrEvent; use crate::network::NetworkEvent; + use crate::network::radarr_network::RadarrEvent; #[tokio::test] async fn test_dispatch_by_blocklist_block() { diff --git a/src/app/sonarr/mod.rs b/src/app/sonarr/mod.rs index c0c5eca..e9c3de7 100644 --- a/src/app/sonarr/mod.rs +++ b/src/app/sonarr/mod.rs @@ -94,16 +94,15 @@ impl App<'_> { .await; } ActiveSonarrBlock::ManualEpisodeSearch => { - if let Some(season_details_modal) = self.data.sonarr_data.season_details_modal.as_ref() { - if let Some(episode_details_modal) = season_details_modal.episode_details_modal.as_ref() { - if episode_details_modal.episode_releases.is_empty() { - self - .dispatch_network_event( - SonarrEvent::GetEpisodeReleases(self.extract_episode_id().await).into(), - ) - .await; - } - } + if let Some(season_details_modal) = self.data.sonarr_data.season_details_modal.as_ref() + && let Some(episode_details_modal) = season_details_modal.episode_details_modal.as_ref() + && episode_details_modal.episode_releases.is_empty() + { + self + .dispatch_network_event( + SonarrEvent::GetEpisodeReleases(self.extract_episode_id().await).into(), + ) + .await; } } ActiveSonarrBlock::Downloads => { diff --git a/src/app/sonarr/sonarr_context_clues.rs b/src/app/sonarr/sonarr_context_clues.rs index 28b642a..2a58a81 100644 --- a/src/app/sonarr/sonarr_context_clues.rs +++ b/src/app/sonarr/sonarr_context_clues.rs @@ -1,12 +1,12 @@ use crate::app::context_clues::{ - ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, + BARE_POPUP_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, ContextClueProvider, }; -use crate::app::{context_clues::ContextClue, key_binding::DEFAULT_KEYBINDINGS, App}; +use crate::app::{App, context_clues::ContextClue, key_binding::DEFAULT_KEYBINDINGS}; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, ADD_SERIES_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_SERIES_BLOCKS, + ADD_SERIES_BLOCKS, ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, EDIT_SERIES_BLOCKS, EPISODE_DETAILS_BLOCKS, INDEXER_SETTINGS_BLOCKS, SEASON_DETAILS_BLOCKS, SERIES_DETAILS_BLOCKS, }; -use crate::models::Route; #[cfg(test)] #[path = "sonarr_context_clues_tests.rs"] diff --git a/src/app/sonarr/sonarr_context_clues_tests.rs b/src/app/sonarr/sonarr_context_clues_tests.rs index 2560111..30b953d 100644 --- a/src/app/sonarr/sonarr_context_clues_tests.rs +++ b/src/app/sonarr/sonarr_context_clues_tests.rs @@ -1,14 +1,15 @@ #[cfg(test)] mod tests { use crate::app::context_clues::{ - ContextClue, ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, - CONFIRMATION_PROMPT_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, + BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, + ContextClue, ContextClueProvider, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES, }; use crate::app::sonarr::sonarr_context_clues::{ - SonarrContextClueProvider, SELECTABLE_EPISODE_DETAILS_CONTEXT_CLUES, + SELECTABLE_EPISODE_DETAILS_CONTEXT_CLUES, SonarrContextClueProvider, }; use crate::app::{ + App, key_binding::DEFAULT_KEYBINDINGS, sonarr::sonarr_context_clues::{ ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES, EPISODE_DETAILS_CONTEXT_CLUES, @@ -17,12 +18,10 @@ mod tests { SEASON_HISTORY_CONTEXT_CLUES, SERIES_CONTEXT_CLUES, SERIES_DETAILS_CONTEXT_CLUES, SERIES_HISTORY_CONTEXT_CLUES, SYSTEM_TASKS_CONTEXT_CLUES, }, - App, }; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_data::sonarr::modals::{EpisodeDetailsModal, SeasonDetailsModal}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}; - use pretty_assertions::{assert_eq, assert_str_eq}; use rstest::rstest; #[test] @@ -30,417 +29,422 @@ mod tests { let mut add_series_search_results_context_clues_iter = ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES.iter(); - let (key_binding, description) = add_series_search_results_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = add_series_search_results_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "edit search"); - assert_eq!(add_series_search_results_context_clues_iter.next(), None); + assert_some_eq_x!( + add_series_search_results_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + add_series_search_results_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "edit search") + ); + assert_none!(add_series_search_results_context_clues_iter.next()); } #[test] fn test_series_context_clues() { let mut series_context_clues_iter = SERIES_CONTEXT_CLUES.iter(); - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.add); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.add.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.toggle_monitoring); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.toggle_monitoring.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.delete.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, "update all"); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = series_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel filter"); - assert_eq!(series_context_clues_iter.next(), None); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.toggle_monitoring, + DEFAULT_KEYBINDINGS.toggle_monitoring.desc + ) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, "update all") + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + series_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel filter") + ); + assert_none!(series_context_clues_iter.next()); } #[test] fn test_series_history_context_clues() { let mut series_history_context_clues_iter = SERIES_HISTORY_CONTEXT_CLUES.iter(); - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.update.desc); - - let (key_binding, description) = series_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel filter/close"); - assert_eq!(series_history_context_clues_iter.next(), None); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, DEFAULT_KEYBINDINGS.update.desc) + ); + assert_some_eq_x!( + series_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel filter/close") + ); + assert_none!(series_history_context_clues_iter.next()); } #[test] fn test_history_context_clues() { let mut history_context_clues_iter = HISTORY_CONTEXT_CLUES.iter(); - let (key_binding, description) = history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc); - - let (key_binding, description) = history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel filter"); - assert_eq!(history_context_clues_iter.next(), None); + assert_some_eq_x!( + history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc) + ); + assert_some_eq_x!( + history_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel filter") + ); + assert_none!(history_context_clues_iter.next()); } #[test] fn test_series_details_context_clues() { let mut series_details_context_clues_iter = SERIES_DETAILS_CONTEXT_CLUES.iter(); - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.edit); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.edit.desc); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.toggle_monitoring); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.toggle_monitoring.desc); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "season details"); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.update); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.update.desc); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = series_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(series_details_context_clues_iter.next(), None); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc) + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.toggle_monitoring, + DEFAULT_KEYBINDINGS.toggle_monitoring.desc + ) + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "season details") + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.update, DEFAULT_KEYBINDINGS.update.desc) + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + series_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(series_details_context_clues_iter.next()); } #[test] fn test_season_details_context_clues() { let mut season_details_context_clues_iter = SEASON_DETAILS_CONTEXT_CLUES.iter(); - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.toggle_monitoring); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.toggle_monitoring.desc); - - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "episode details"); - - let (key_binding, description) = season_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete); - assert_str_eq!(*description, "delete episode"); - - assert_eq!(season_details_context_clues_iter.next(), None); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.toggle_monitoring, + DEFAULT_KEYBINDINGS.toggle_monitoring.desc + ) + ); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "episode details") + ); + assert_some_eq_x!( + season_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.delete, "delete episode") + ); + assert_none!(season_details_context_clues_iter.next()); } #[test] fn test_season_history_context_clues() { let mut season_history_context_clues_iter = SEASON_HISTORY_CONTEXT_CLUES.iter(); - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.search.desc); - - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.filter); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.filter.desc); - - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = season_history_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, "cancel filter/close"); - assert_eq!(season_history_context_clues_iter.next(), None); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc) + ); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.filter, DEFAULT_KEYBINDINGS.filter.desc) + ); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + season_history_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, "cancel filter/close") + ); + assert_none!(season_history_context_clues_iter.next()); } #[test] fn test_manual_season_search_context_clues() { let mut manual_season_search_context_clues_iter = MANUAL_SEASON_SEARCH_CONTEXT_CLUES.iter(); - let (key_binding, description) = manual_season_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = manual_season_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = manual_season_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = manual_season_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = manual_season_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(manual_season_search_context_clues_iter.next(), None); + assert_some_eq_x!( + manual_season_search_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + manual_season_search_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + manual_season_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + manual_season_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + manual_season_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(manual_season_search_context_clues_iter.next()); } #[test] fn test_manual_episode_search_context_clues() { let mut manual_episode_search_context_clues_iter = MANUAL_EPISODE_SEARCH_CONTEXT_CLUES.iter(); - let (key_binding, description) = manual_episode_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = manual_episode_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = manual_episode_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc); - - let (key_binding, description) = manual_episode_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = manual_episode_search_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(manual_episode_search_context_clues_iter.next(), None); + assert_some_eq_x!( + manual_episode_search_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + manual_episode_search_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + manual_episode_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc) + ); + assert_some_eq_x!( + manual_episode_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + manual_episode_search_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(manual_episode_search_context_clues_iter.next()); } #[test] fn test_episode_details_context_clues() { let mut episode_details_context_clues_iter = EPISODE_DETAILS_CONTEXT_CLUES.iter(); - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(episode_details_context_clues_iter.next(), None); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(episode_details_context_clues_iter.next()); } #[test] fn test_selectable_episode_details_context_clues() { let mut episode_details_context_clues_iter = SELECTABLE_EPISODE_DETAILS_CONTEXT_CLUES.iter(); - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.refresh); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc); - - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.auto_search); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.auto_search.desc); - - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "details"); - - let (key_binding, description) = episode_details_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(episode_details_context_clues_iter.next(), None); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.refresh, + DEFAULT_KEYBINDINGS.refresh.desc + ) + ); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &( + DEFAULT_KEYBINDINGS.auto_search, + DEFAULT_KEYBINDINGS.auto_search.desc + ) + ); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "details") + ); + assert_some_eq_x!( + episode_details_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(episode_details_context_clues_iter.next()); } #[test] fn test_system_tasks_context_clues() { let mut system_tasks_context_clues_iter = SYSTEM_TASKS_CONTEXT_CLUES.iter(); - let (key_binding, description) = system_tasks_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit); - assert_str_eq!(*description, "start task"); - - let (key_binding, description) = system_tasks_context_clues_iter.next().unwrap(); - - assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc); - assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc); - assert_eq!(system_tasks_context_clues_iter.next(), None); + assert_some_eq_x!( + system_tasks_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.submit, "start task") + ); + assert_some_eq_x!( + system_tasks_context_clues_iter.next(), + &(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc) + ); + assert_none!(system_tasks_context_clues_iter.next()); } #[test] @@ -470,8 +474,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(expected_context_clues, context_clues.unwrap()); + assert_some_eq_x!(context_clues, expected_context_clues); } #[rstest] @@ -495,8 +498,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(expected_context_clues, context_clues.unwrap()); + assert_some_eq_x!(context_clues, expected_context_clues); } #[rstest] @@ -524,8 +526,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(expected_context_clues, context_clues.unwrap()); + assert_some_eq_x!(context_clues, expected_context_clues); } #[rstest] @@ -544,8 +545,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(context_clues.unwrap(), &BARE_POPUP_CONTEXT_CLUES); + assert_some_eq_x!(context_clues, &BARE_POPUP_CONTEXT_CLUES); } #[rstest] @@ -567,8 +567,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -593,8 +592,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -614,8 +612,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -638,8 +635,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES); + assert_some_eq_x!(context_clues, &CONFIRMATION_PROMPT_CONTEXT_CLUES); } #[rstest] @@ -655,11 +651,7 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!( - context_clues.unwrap(), - &ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES - ); + assert_some_eq_x!(context_clues, &ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES); } #[test] @@ -669,8 +661,7 @@ mod tests { app.push_navigation_stack(ActiveSonarrBlock::SystemTasks.into()); let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(context_clues.unwrap(), &SYSTEM_TASKS_CONTEXT_CLUES); + assert_some_eq_x!(context_clues, &SYSTEM_TASKS_CONTEXT_CLUES); } #[rstest] @@ -693,7 +684,6 @@ mod tests { let context_clues = SonarrContextClueProvider::get_context_clues(&mut app); - assert!(context_clues.is_some()); - assert_eq!(expected_context_clues, context_clues.unwrap()); + assert_some_eq_x!(context_clues, expected_context_clues); } } diff --git a/src/app/sonarr/sonarr_tests.rs b/src/app/sonarr/sonarr_tests.rs index 904379f..bbf008e 100644 --- a/src/app/sonarr/sonarr_tests.rs +++ b/src/app/sonarr/sonarr_tests.rs @@ -16,7 +16,7 @@ mod tests { }, sonarr_models::{Season, Series, SonarrRelease}, }, - network::{sonarr_network::SonarrEvent, NetworkEvent}, + network::{NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] diff --git a/src/cli/cli_tests.rs b/src/cli/cli_tests.rs index 0109905..7232497 100644 --- a/src/cli/cli_tests.rs +++ b/src/cli/cli_tests.rs @@ -2,16 +2,18 @@ mod tests { use std::sync::Arc; - use clap::{error::ErrorKind, CommandFactory}; + use clap::{CommandFactory, error::ErrorKind}; use mockall::predicate::eq; use rstest::rstest; use serde_json::json; use tokio::sync::Mutex; use crate::{ + Cli, app::App, cli::{handle_command, mutex_flags_or_option, radarr::RadarrCommand, sonarr::SonarrCommand}, models::{ + Serdeable, radarr_models::{ BlocklistItem as RadarrBlocklistItem, BlocklistResponse as RadarrBlocklistResponse, RadarrSerdeable, @@ -20,12 +22,10 @@ mod tests { BlocklistItem as SonarrBlocklistItem, BlocklistResponse as SonarrBlocklistResponse, SonarrSerdeable, }, - Serdeable, }, network::{ - radarr_network::RadarrEvent, sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent, + MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent, sonarr_network::SonarrEvent, }, - Cli, }; use pretty_assertions::assert_eq; @@ -33,7 +33,7 @@ mod tests { fn test_servarr_subcommand_requires_subcommand(#[values("radarr", "sonarr")] subcommand: &str) { let result = Cli::command().try_get_matches_from(["managarr", subcommand]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand @@ -45,21 +45,21 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "all-indexer-settings"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_sonarr_subcommand_delegates_to_sonarr() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "series"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_completions_requires_argument() { let result = Cli::command().try_get_matches_from(["managarr", "completions"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand @@ -70,7 +70,7 @@ mod tests { fn test_completions_invalid_argument() { let result = Cli::command().try_get_matches_from(["managarr", "completions", "test"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -78,7 +78,7 @@ mod tests { fn test_completions_satisfied_with_argument() { let result = Cli::command().try_get_matches_from(["managarr", "completions", "bash"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[rstest] @@ -141,7 +141,7 @@ mod tests { let result = handle_command(&app_arc, clear_blocklist_command, &mut mock_network).await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -172,6 +172,6 @@ mod tests { let result = handle_command(&app_arc, clear_blocklist_command, &mut mock_network).await; - assert!(result.is_ok()); + assert_ok!(&result); } } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 4a658a2..8d0c6d2 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use anyhow::Result; -use clap::Subcommand; +use clap::{Subcommand, command}; use clap_complete::Shell; use radarr::{RadarrCliHandler, RadarrCommand}; use sonarr::{SonarrCliHandler, SonarrCommand}; diff --git a/src/cli/radarr/add_command_handler.rs b/src/cli/radarr/add_command_handler.rs index e4b9f3f..f0e73bf 100644 --- a/src/cli/radarr/add_command_handler.rs +++ b/src/cli/radarr/add_command_handler.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use anyhow::Result; -use clap::{ArgAction, Subcommand}; +use clap::{ArgAction, Subcommand, arg, command}; use tokio::sync::Mutex; use super::RadarrCommand; @@ -10,7 +10,7 @@ use crate::{ app::App, cli::{CliCommandHandler, Command}, models::radarr_models::{AddMovieBody, AddMovieOptions, MinimumAvailability, MovieMonitor}, - network::{radarr_network::RadarrEvent, NetworkTrait}, + network::{NetworkTrait, radarr_network::RadarrEvent}, }; #[cfg(test)] diff --git a/src/cli/radarr/add_command_handler_tests.rs b/src/cli/radarr/add_command_handler_tests.rs index 3309a11..bf18652 100644 --- a/src/cli/radarr/add_command_handler_tests.rs +++ b/src/cli/radarr/add_command_handler_tests.rs @@ -1,14 +1,14 @@ #[cfg(test)] mod tests { - use clap::{error::ErrorKind, CommandFactory, Parser}; + use clap::{CommandFactory, Parser, error::ErrorKind}; use crate::{ + Cli, cli::{ - radarr::{add_command_handler::RadarrAddCommand, RadarrCommand}, Command, + radarr::{RadarrCommand, add_command_handler::RadarrAddCommand}, }, models::radarr_models::{MinimumAvailability, MovieMonitor}, - Cli, }; use pretty_assertions::assert_eq; @@ -32,7 +32,7 @@ mod tests { fn test_add_movie_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "add", "movie"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -52,7 +52,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -72,7 +72,7 @@ mod tests { "/test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -92,7 +92,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -117,7 +117,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -136,7 +136,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -156,7 +156,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -177,7 +177,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -207,10 +207,11 @@ mod tests { "1", ]); - assert!(result.is_ok()); - if let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + assert_ok!(&result); + let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type") + }; + assert_eq!(add_command, expected_args); } #[test] @@ -243,10 +244,11 @@ mod tests { "2", ]); - assert!(result.is_ok()); - if let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + assert_ok!(&result); + let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type") + }; + assert_eq!(add_command, expected_args); } #[test] @@ -285,10 +287,11 @@ mod tests { "--no-search-for-movie", ]); - assert!(result.is_ok()); - if let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + assert_ok!(&result); + let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type") + }; + assert_eq!(add_command, expected_args); } #[test] @@ -296,7 +299,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "add", "root-folder"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -318,18 +321,19 @@ mod tests { "/nfs/test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type") + }; + assert_eq!(add_command, expected_args); } #[test] fn test_add_tag_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "add", "tag"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -344,11 +348,12 @@ mod tests { let result = Cli::try_parse_from(["managarr", "radarr", "add", "tag", "--name", "test"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type") + }; + assert_eq!(add_command, expected_args); } } @@ -357,12 +362,12 @@ mod tests { use crate::{ app::App, - cli::{radarr::add_command_handler::RadarrAddCommandHandler, CliCommandHandler}, + cli::{CliCommandHandler, radarr::add_command_handler::RadarrAddCommandHandler}, models::{ - radarr_models::{AddMovieBody, AddMovieOptions, RadarrSerdeable}, Serdeable, + radarr_models::{AddMovieBody, AddMovieOptions, RadarrSerdeable}, }, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; use super::*; @@ -416,7 +421,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -447,7 +452,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -474,7 +479,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/radarr/delete_command_handler.rs b/src/cli/radarr/delete_command_handler.rs index 9fdb83c..ba9e878 100644 --- a/src/cli/radarr/delete_command_handler.rs +++ b/src/cli/radarr/delete_command_handler.rs @@ -8,7 +8,7 @@ use crate::{ app::App, cli::{CliCommandHandler, Command}, models::radarr_models::DeleteMovieParams, - network::{radarr_network::RadarrEvent, NetworkTrait}, + network::{NetworkTrait, radarr_network::RadarrEvent}, }; use super::RadarrCommand; diff --git a/src/cli/radarr/delete_command_handler_tests.rs b/src/cli/radarr/delete_command_handler_tests.rs index 3c47b50..d50705c 100644 --- a/src/cli/radarr/delete_command_handler_tests.rs +++ b/src/cli/radarr/delete_command_handler_tests.rs @@ -1,13 +1,13 @@ #[cfg(test)] mod tests { use crate::{ - cli::{ - radarr::{delete_command_handler::RadarrDeleteCommand, RadarrCommand}, - Command, - }, Cli, + cli::{ + Command, + radarr::{RadarrCommand, delete_command_handler::RadarrDeleteCommand}, + }, }; - use clap::{error::ErrorKind, CommandFactory, Parser}; + use clap::{CommandFactory, Parser, error::ErrorKind}; use pretty_assertions::assert_eq; #[test] @@ -30,7 +30,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "delete", "blocklist-item"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -52,12 +52,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -65,7 +66,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "delete", "download"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -85,19 +86,20 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] fn test_delete_indexer_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "delete", "indexer"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -117,19 +119,20 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] fn test_delete_movie_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "delete", "movie"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -147,12 +150,13 @@ mod tests { let result = Cli::try_parse_from(["managarr", "radarr", "delete", "movie", "--movie-id", "1"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -174,12 +178,13 @@ mod tests { "--add-list-exclusion", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -187,7 +192,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "delete", "root-folder"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -207,19 +212,20 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] fn test_delete_tag_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "delete", "tag"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -232,12 +238,13 @@ mod tests { let result = Cli::try_parse_from(["managarr", "radarr", "delete", "tag", "--tag-id", "1"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } } @@ -251,14 +258,14 @@ mod tests { use crate::{ app::App, cli::{ - radarr::delete_command_handler::{RadarrDeleteCommand, RadarrDeleteCommandHandler}, CliCommandHandler, + radarr::delete_command_handler::{RadarrDeleteCommand, RadarrDeleteCommandHandler}, }, models::{ - radarr_models::{DeleteMovieParams, RadarrSerdeable}, Serdeable, + radarr_models::{DeleteMovieParams, RadarrSerdeable}, }, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; #[tokio::test] @@ -289,7 +296,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -315,7 +322,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -341,7 +348,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -375,7 +382,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -401,7 +408,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -427,7 +434,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/radarr/edit_command_handler.rs b/src/cli/radarr/edit_command_handler.rs index f786697..e2383f2 100644 --- a/src/cli/radarr/edit_command_handler.rs +++ b/src/cli/radarr/edit_command_handler.rs @@ -6,15 +6,15 @@ use tokio::sync::Mutex; use crate::{ app::App, - cli::{mutex_flags_or_default, mutex_flags_or_option, CliCommandHandler, Command}, + cli::{CliCommandHandler, Command, mutex_flags_or_default, mutex_flags_or_option}, models::{ + Serdeable, radarr_models::{ EditCollectionParams, EditMovieParams, IndexerSettings, MinimumAvailability, RadarrSerdeable, }, servarr_models::EditIndexerParams, - Serdeable, }, - network::{radarr_network::RadarrEvent, NetworkTrait}, + network::{NetworkTrait, radarr_network::RadarrEvent}, }; use super::RadarrCommand; diff --git a/src/cli/radarr/edit_command_handler_tests.rs b/src/cli/radarr/edit_command_handler_tests.rs index f811691..02a697a 100644 --- a/src/cli/radarr/edit_command_handler_tests.rs +++ b/src/cli/radarr/edit_command_handler_tests.rs @@ -1,13 +1,13 @@ #[cfg(test)] mod tests { use crate::{ - cli::{ - radarr::{edit_command_handler::RadarrEditCommand, RadarrCommand}, - Command, - }, Cli, + cli::{ + Command, + radarr::{RadarrCommand, edit_command_handler::RadarrEditCommand}, + }, }; - use clap::{error::ErrorKind, CommandFactory, Parser}; + use clap::{CommandFactory, Parser, error::ErrorKind}; use pretty_assertions::assert_eq; #[test] @@ -42,7 +42,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "edit", "all-indexer-settings"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -60,7 +60,7 @@ mod tests { "--disable-allow-hardcoded-subs", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -75,7 +75,7 @@ mod tests { "--disable-prefer-indexer-flags", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -99,7 +99,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -126,11 +126,12 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -168,11 +169,12 @@ mod tests { "test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -180,7 +182,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "edit", "collection"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -198,7 +200,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -218,7 +220,7 @@ mod tests { "--disable-monitoring", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -235,7 +237,7 @@ mod tests { "--disable-search-on-add", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -252,7 +254,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -270,7 +272,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -298,11 +300,12 @@ mod tests { "/test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -334,18 +337,19 @@ mod tests { "--search-on-add", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] fn test_edit_indexer_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "edit", "indexer"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -363,7 +367,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -383,7 +387,7 @@ mod tests { "--disable-rss", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -400,7 +404,7 @@ mod tests { "--disable-automatic-search", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -417,7 +421,7 @@ mod tests { "--disable-interactive-search", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -435,7 +439,7 @@ mod tests { "--clear-tags", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -453,7 +457,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -487,11 +491,12 @@ mod tests { "Test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -526,11 +531,12 @@ mod tests { "2", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -578,18 +584,19 @@ mod tests { "25", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] fn test_edit_movie_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "edit", "movie"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -607,7 +614,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -627,7 +634,7 @@ mod tests { "--disable-monitoring", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -645,7 +652,7 @@ mod tests { "--clear-tags", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -669,7 +676,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -686,7 +693,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -714,11 +721,12 @@ mod tests { "/nfs/test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -747,11 +755,12 @@ mod tests { "2", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -787,11 +796,12 @@ mod tests { "2", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } } @@ -805,18 +815,18 @@ mod tests { use crate::{ app::App, cli::{ - radarr::edit_command_handler::{RadarrEditCommand, RadarrEditCommandHandler}, CliCommandHandler, + radarr::edit_command_handler::{RadarrEditCommand, RadarrEditCommandHandler}, }, models::{ + Serdeable, radarr_models::{ EditCollectionParams, EditMovieParams, IndexerSettings, MinimumAvailability, RadarrSerdeable, }, servarr_models::EditIndexerParams, - Serdeable, }, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; #[tokio::test] @@ -887,7 +897,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -958,12 +968,12 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] - async fn test_handle_edit_all_indexer_settings_command_unprovided_values_default_to_previous_values( - ) { + async fn test_handle_edit_all_indexer_settings_command_unprovided_values_default_to_previous_values() + { let expected_edit_all_indexer_settings = IndexerSettings { allow_hardcoded_subs: true, availability_delay: 2, @@ -1030,7 +1040,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1072,7 +1082,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1114,7 +1124,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1156,7 +1166,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1210,7 +1220,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1264,7 +1274,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1318,7 +1328,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1361,7 +1371,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1404,7 +1414,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -1447,7 +1457,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/radarr/get_command_handler.rs b/src/cli/radarr/get_command_handler.rs index a1188b3..7233146 100644 --- a/src/cli/radarr/get_command_handler.rs +++ b/src/cli/radarr/get_command_handler.rs @@ -1,13 +1,13 @@ use std::sync::Arc; use anyhow::Result; -use clap::Subcommand; +use clap::{Subcommand, command}; use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{radarr_network::RadarrEvent, NetworkTrait}, + network::{NetworkTrait, radarr_network::RadarrEvent}, }; use super::RadarrCommand; diff --git a/src/cli/radarr/get_command_handler_tests.rs b/src/cli/radarr/get_command_handler_tests.rs index 6a3fec5..e0652fd 100644 --- a/src/cli/radarr/get_command_handler_tests.rs +++ b/src/cli/radarr/get_command_handler_tests.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod tests { - use clap::error::ErrorKind; use clap::CommandFactory; + use clap::error::ErrorKind; - use crate::cli::radarr::get_command_handler::RadarrGetCommand; - use crate::cli::radarr::RadarrCommand; - use crate::cli::Command; use crate::Cli; + use crate::cli::Command; + use crate::cli::radarr::RadarrCommand; + use crate::cli::radarr::get_command_handler::RadarrGetCommand; use pretty_assertions::assert_eq; #[test] @@ -27,7 +27,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "all-indexer-settings"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -35,7 +35,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "host-config"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -43,7 +43,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "movie-details"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -61,7 +61,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -69,7 +69,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "movie-history"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -87,7 +87,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -95,7 +95,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "security-config"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -103,7 +103,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "get", "system-status"]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -117,11 +117,11 @@ mod tests { use crate::{ app::App, cli::{ - radarr::get_command_handler::{RadarrGetCommand, RadarrGetCommandHandler}, CliCommandHandler, + radarr::get_command_handler::{RadarrGetCommand, RadarrGetCommandHandler}, }, - models::{radarr_models::RadarrSerdeable, Serdeable}, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + models::{Serdeable, radarr_models::RadarrSerdeable}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; #[tokio::test] @@ -149,7 +149,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -172,7 +172,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -198,7 +198,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -224,7 +224,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -247,7 +247,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -270,7 +270,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/radarr/list_command_handler.rs b/src/cli/radarr/list_command_handler.rs index ccf3076..4e613c9 100644 --- a/src/cli/radarr/list_command_handler.rs +++ b/src/cli/radarr/list_command_handler.rs @@ -1,13 +1,13 @@ use std::sync::Arc; use anyhow::Result; -use clap::Subcommand; +use clap::{Subcommand, command}; use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{radarr_network::RadarrEvent, NetworkTrait}, + network::{NetworkTrait, radarr_network::RadarrEvent}, }; use super::RadarrCommand; diff --git a/src/cli/radarr/list_command_handler_tests.rs b/src/cli/radarr/list_command_handler_tests.rs index fb7e2d6..ba5f810 100644 --- a/src/cli/radarr/list_command_handler_tests.rs +++ b/src/cli/radarr/list_command_handler_tests.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod tests { - use clap::error::ErrorKind; use clap::CommandFactory; + use clap::error::ErrorKind; - use crate::cli::radarr::list_command_handler::RadarrListCommand; - use crate::cli::radarr::RadarrCommand; - use crate::cli::Command; use crate::Cli; + use crate::cli::Command; + use crate::cli::radarr::RadarrCommand; + use crate::cli::radarr::list_command_handler::RadarrListCommand; use pretty_assertions::assert_eq; #[test] @@ -43,7 +43,7 @@ mod tests { ) { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "list", subcommand]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -51,7 +51,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "list", "movie-credits"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -63,7 +63,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "list", "downloads", "--count"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -72,7 +72,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "list", "logs", "--events"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -88,11 +88,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::List(credits_command))) = result.unwrap().command { - assert_eq!(credits_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::List(credits_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(credits_command, expected_args); } #[test] @@ -100,11 +102,13 @@ mod tests { let expected_args = RadarrListCommand::Downloads { count: 500 }; let result = Cli::try_parse_from(["managarr", "radarr", "list", "downloads"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::List(refresh_command))) = result.unwrap().command { - assert_eq!(refresh_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::List(refresh_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(refresh_command, expected_args); } #[test] @@ -115,11 +119,13 @@ mod tests { }; let result = Cli::try_parse_from(["managarr", "radarr", "list", "logs"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::List(refresh_command))) = result.unwrap().command { - assert_eq!(refresh_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::List(refresh_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(refresh_command, expected_args); } } @@ -135,8 +141,8 @@ mod tests { use crate::{ app::App, cli::radarr::list_command_handler::{RadarrListCommand, RadarrListCommandHandler}, - models::{radarr_models::RadarrSerdeable, Serdeable}, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + models::{Serdeable, radarr_models::RadarrSerdeable}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; #[rstest] @@ -172,7 +178,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -198,7 +204,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -224,7 +230,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -252,7 +258,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/radarr/mod.rs b/src/cli/radarr/mod.rs index 11b4d9e..f13a587 100644 --- a/src/cli/radarr/mod.rs +++ b/src/cli/radarr/mod.rs @@ -13,8 +13,8 @@ use crate::app::App; use crate::cli::CliCommandHandler; use crate::models::radarr_models::{RadarrReleaseDownloadBody, RadarrTaskName}; -use crate::network::radarr_network::RadarrEvent; use crate::network::NetworkTrait; +use crate::network::radarr_network::RadarrEvent; use anyhow::Result; use super::Command; diff --git a/src/cli/radarr/radarr_command_tests.rs b/src/cli/radarr/radarr_command_tests.rs index 90a7efe..af2f15f 100644 --- a/src/cli/radarr/radarr_command_tests.rs +++ b/src/cli/radarr/radarr_command_tests.rs @@ -1,11 +1,11 @@ #[cfg(test)] mod tests { - use clap::error::ErrorKind; use clap::CommandFactory; + use clap::error::ErrorKind; - use crate::cli::radarr::RadarrCommand; - use crate::cli::Command; use crate::Cli; + use crate::cli::Command; + use crate::cli::radarr::RadarrCommand; use pretty_assertions::assert_eq; #[test] @@ -28,7 +28,7 @@ mod tests { ) { let result = Cli::command().try_get_matches_from(["managarr", "radarr", subcommand]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -43,7 +43,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -62,7 +62,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -81,7 +81,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -102,14 +102,14 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_manual_search_requires_movie_id() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "manual-search"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -126,14 +126,14 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_search_new_movie_requires_query() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "search-new-movie"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -150,14 +150,14 @@ mod tests { "halo", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_start_task_requires_task_name() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "start-task"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -174,7 +174,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -188,14 +188,14 @@ mod tests { "application-check-update", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_test_indexer_requires_indexer_id() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "test-indexer"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -212,7 +212,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -220,7 +220,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "toggle-movie-monitoring"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -237,7 +237,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -245,7 +245,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "trigger-automatic-search"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -262,7 +262,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -276,22 +276,22 @@ mod tests { use crate::{ app::App, cli::{ - radarr::{ - add_command_handler::RadarrAddCommand, delete_command_handler::RadarrDeleteCommand, - edit_command_handler::RadarrEditCommand, get_command_handler::RadarrGetCommand, - list_command_handler::RadarrListCommand, refresh_command_handler::RadarrRefreshCommand, - RadarrCliHandler, RadarrCommand, - }, CliCommandHandler, + radarr::{ + RadarrCliHandler, RadarrCommand, add_command_handler::RadarrAddCommand, + delete_command_handler::RadarrDeleteCommand, edit_command_handler::RadarrEditCommand, + get_command_handler::RadarrGetCommand, list_command_handler::RadarrListCommand, + refresh_command_handler::RadarrRefreshCommand, + }, }, models::{ + Serdeable, radarr_models::{ BlocklistItem, BlocklistResponse, IndexerSettings, RadarrReleaseDownloadBody, RadarrSerdeable, RadarrTaskName, }, - Serdeable, }, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; #[tokio::test] @@ -324,7 +324,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -357,7 +357,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -382,7 +382,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -409,7 +409,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -436,7 +436,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -461,7 +461,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -483,7 +483,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -509,7 +509,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -538,7 +538,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -565,7 +565,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -594,7 +594,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -666,7 +666,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -695,7 +695,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -721,7 +721,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -747,7 +747,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/radarr/refresh_command_handler.rs b/src/cli/radarr/refresh_command_handler.rs index d871be4..2ea5c69 100644 --- a/src/cli/radarr/refresh_command_handler.rs +++ b/src/cli/radarr/refresh_command_handler.rs @@ -7,7 +7,7 @@ use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{radarr_network::RadarrEvent, NetworkTrait}, + network::{NetworkTrait, radarr_network::RadarrEvent}, }; use super::RadarrCommand; diff --git a/src/cli/radarr/refresh_command_handler_tests.rs b/src/cli/radarr/refresh_command_handler_tests.rs index b363b2b..9173138 100644 --- a/src/cli/radarr/refresh_command_handler_tests.rs +++ b/src/cli/radarr/refresh_command_handler_tests.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod tests { - use clap::error::ErrorKind; use clap::CommandFactory; + use clap::error::ErrorKind; - use crate::cli::radarr::refresh_command_handler::RadarrRefreshCommand; - use crate::cli::radarr::RadarrCommand; - use crate::cli::Command; use crate::Cli; + use crate::cli::Command; + use crate::cli::radarr::RadarrCommand; + use crate::cli::radarr::refresh_command_handler::RadarrRefreshCommand; use pretty_assertions::assert_eq; #[test] @@ -31,14 +31,14 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "refresh", subcommand]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_refresh_movie_requires_movie_id() { let result = Cli::command().try_get_matches_from(["managarr", "radarr", "refresh", "movie"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -51,13 +51,13 @@ mod tests { let result = Cli::try_parse_from(["managarr", "radarr", "refresh", "movie", "--movie-id", "1"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Radarr(RadarrCommand::Refresh(refresh_command))) = - result.unwrap().command - { - assert_eq!(refresh_command, expected_args); - } + let Some(Command::Radarr(RadarrCommand::Refresh(refresh_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(refresh_command, expected_args); } } @@ -73,8 +73,8 @@ mod tests { use crate::{ app::App, cli::radarr::refresh_command_handler::{RadarrRefreshCommand, RadarrRefreshCommandHandler}, - models::{radarr_models::RadarrSerdeable, Serdeable}, - network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent}, + models::{Serdeable, radarr_models::RadarrSerdeable}, + network::{MockNetworkTrait, NetworkEvent, radarr_network::RadarrEvent}, }; #[rstest] @@ -102,7 +102,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -128,7 +128,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/add_command_handler.rs b/src/cli/sonarr/add_command_handler.rs index 9bf0dc6..14117e9 100644 --- a/src/cli/sonarr/add_command_handler.rs +++ b/src/cli/sonarr/add_command_handler.rs @@ -10,7 +10,7 @@ use crate::{ app::App, cli::{CliCommandHandler, Command}, models::sonarr_models::{AddSeriesBody, AddSeriesOptions, SeriesMonitor, SeriesType}, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; #[cfg(test)] diff --git a/src/cli/sonarr/add_command_handler_tests.rs b/src/cli/sonarr/add_command_handler_tests.rs index 94d65cd..6558ea7 100644 --- a/src/cli/sonarr/add_command_handler_tests.rs +++ b/src/cli/sonarr/add_command_handler_tests.rs @@ -1,14 +1,14 @@ #[cfg(test)] mod tests { - use clap::{error::ErrorKind, CommandFactory, Parser}; + use clap::{CommandFactory, Parser, error::ErrorKind}; use pretty_assertions::assert_eq; use crate::{ - cli::{ - sonarr::{add_command_handler::SonarrAddCommand, SonarrCommand}, - Command, - }, Cli, + cli::{ + Command, + sonarr::{SonarrCommand, add_command_handler::SonarrAddCommand}, + }, }; #[test] @@ -34,7 +34,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "add", "root-folder"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -56,18 +56,19 @@ mod tests { "/nfs/test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(add_command, expected_args); } #[test] fn test_add_series_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "add", "series"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -91,7 +92,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -115,7 +116,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -139,7 +140,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -163,7 +164,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -187,7 +188,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -216,7 +217,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -239,7 +240,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -263,7 +264,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -288,7 +289,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -325,10 +326,11 @@ mod tests { "1", ]); - assert!(result.is_ok()); - if let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + assert_ok!(&result); + let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(add_command, expected_args); } #[test] @@ -368,10 +370,11 @@ mod tests { "2", ]); - assert!(result.is_ok()); - if let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + assert_ok!(&result); + let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(add_command, expected_args); } #[test] @@ -418,17 +421,18 @@ mod tests { "--no-search-for-series", ]); - assert!(result.is_ok()); - if let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + assert_ok!(&result); + let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(add_command, expected_args); } #[test] fn test_add_tag_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "add", "tag"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -443,11 +447,12 @@ mod tests { let result = Cli::try_parse_from(["managarr", "sonarr", "add", "tag", "--name", "test"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command { - assert_eq!(add_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Add(add_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(add_command, expected_args); } } @@ -456,14 +461,14 @@ mod tests { use crate::{ app::App, - cli::{sonarr::add_command_handler::SonarrAddCommandHandler, CliCommandHandler}, + cli::{CliCommandHandler, sonarr::add_command_handler::SonarrAddCommandHandler}, models::{ + Serdeable, sonarr_models::{ AddSeriesBody, AddSeriesOptions, SeriesMonitor, SeriesType, SonarrSerdeable, }, - Serdeable, }, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; use super::*; @@ -501,7 +506,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -554,7 +559,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -581,7 +586,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/delete_command_handler.rs b/src/cli/sonarr/delete_command_handler.rs index a497305..d123e5f 100644 --- a/src/cli/sonarr/delete_command_handler.rs +++ b/src/cli/sonarr/delete_command_handler.rs @@ -8,7 +8,7 @@ use crate::{ app::App, cli::{CliCommandHandler, Command}, models::sonarr_models::DeleteSeriesParams, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/delete_command_handler_tests.rs b/src/cli/sonarr/delete_command_handler_tests.rs index fdae4c4..38a39d7 100644 --- a/src/cli/sonarr/delete_command_handler_tests.rs +++ b/src/cli/sonarr/delete_command_handler_tests.rs @@ -1,13 +1,13 @@ #[cfg(test)] mod tests { use crate::{ - cli::{ - sonarr::{delete_command_handler::SonarrDeleteCommand, SonarrCommand}, - Command, - }, Cli, + cli::{ + Command, + sonarr::{SonarrCommand, delete_command_handler::SonarrDeleteCommand}, + }, }; - use clap::{error::ErrorKind, CommandFactory, Parser}; + use clap::{CommandFactory, Parser, error::ErrorKind}; use pretty_assertions::assert_eq; #[test] @@ -30,7 +30,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "blocklist-item"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -52,12 +52,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -65,7 +66,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "download"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -85,12 +86,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -98,7 +100,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "episode-file"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -118,19 +120,20 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] fn test_delete_indexer_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "indexer"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -150,12 +153,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -163,7 +167,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "root-folder"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -183,19 +187,20 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] fn test_delete_series_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "series"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -213,12 +218,13 @@ mod tests { let result = Cli::try_parse_from(["managarr", "sonarr", "delete", "series", "--series-id", "1"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] @@ -240,19 +246,20 @@ mod tests { "--add-list-exclusion", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } #[test] fn test_delete_tag_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "delete", "tag"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -265,12 +272,13 @@ mod tests { let result = Cli::try_parse_from(["managarr", "sonarr", "delete", "tag", "--tag-id", "1"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command - { - assert_eq!(delete_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Delete(delete_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(delete_command, expected_args); } } @@ -284,14 +292,14 @@ mod tests { use crate::{ app::App, cli::{ - sonarr::delete_command_handler::{SonarrDeleteCommand, SonarrDeleteCommandHandler}, CliCommandHandler, + sonarr::delete_command_handler::{SonarrDeleteCommand, SonarrDeleteCommandHandler}, }, models::{ - sonarr_models::{DeleteSeriesParams, SonarrSerdeable}, Serdeable, + sonarr_models::{DeleteSeriesParams, SonarrSerdeable}, }, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -322,7 +330,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -348,7 +356,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -374,7 +382,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -400,7 +408,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -426,7 +434,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -460,7 +468,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -486,7 +494,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/download_command_handler.rs b/src/cli/sonarr/download_command_handler.rs index f990ab2..0e860ec 100644 --- a/src/cli/sonarr/download_command_handler.rs +++ b/src/cli/sonarr/download_command_handler.rs @@ -8,7 +8,7 @@ use crate::{ app::App, cli::{CliCommandHandler, Command}, models::sonarr_models::SonarrReleaseDownloadBody, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/download_command_handler_tests.rs b/src/cli/sonarr/download_command_handler_tests.rs index f0a32b0..8ff625f 100644 --- a/src/cli/sonarr/download_command_handler_tests.rs +++ b/src/cli/sonarr/download_command_handler_tests.rs @@ -1,11 +1,11 @@ #[cfg(test)] mod tests { use crate::{ - cli::{ - sonarr::{download_command_handler::SonarrDownloadCommand, SonarrCommand}, - Command, - }, Cli, + cli::{ + Command, + sonarr::{SonarrCommand, download_command_handler::SonarrDownloadCommand}, + }, }; use clap::CommandFactory; use pretty_assertions::assert_eq; @@ -41,7 +41,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -61,7 +61,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -81,7 +81,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -103,7 +103,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -121,7 +121,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -143,7 +143,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -165,7 +165,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -187,7 +187,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -211,7 +211,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -227,7 +227,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -247,7 +247,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -267,7 +267,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -289,7 +289,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -303,14 +303,14 @@ mod tests { use crate::{ app::App, cli::{ - sonarr::download_command_handler::{SonarrDownloadCommand, SonarrDownloadCommandHandler}, CliCommandHandler, + sonarr::download_command_handler::{SonarrDownloadCommand, SonarrDownloadCommandHandler}, }, models::{ - sonarr_models::{SonarrReleaseDownloadBody, SonarrSerdeable}, Serdeable, + sonarr_models::{SonarrReleaseDownloadBody, SonarrSerdeable}, }, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -345,7 +345,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -382,7 +382,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -417,7 +417,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/edit_command_handler.rs b/src/cli/sonarr/edit_command_handler.rs index 7d06313..6ba16ca 100644 --- a/src/cli/sonarr/edit_command_handler.rs +++ b/src/cli/sonarr/edit_command_handler.rs @@ -6,13 +6,13 @@ use tokio::sync::Mutex; use crate::{ app::App, - cli::{mutex_flags_or_option, CliCommandHandler, Command}, + cli::{CliCommandHandler, Command, mutex_flags_or_option}, models::{ + Serdeable, servarr_models::EditIndexerParams, sonarr_models::{EditSeriesParams, IndexerSettings, SeriesType, SonarrSerdeable}, - Serdeable, }, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/edit_command_handler_tests.rs b/src/cli/sonarr/edit_command_handler_tests.rs index bc6ef89..58cc2ac 100644 --- a/src/cli/sonarr/edit_command_handler_tests.rs +++ b/src/cli/sonarr/edit_command_handler_tests.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod tests { use crate::cli::{ - sonarr::{edit_command_handler::SonarrEditCommand, SonarrCommand}, Command, + sonarr::{SonarrCommand, edit_command_handler::SonarrEditCommand}, }; #[test] @@ -20,10 +20,10 @@ mod tests { } mod cli { - use crate::{models::sonarr_models::SeriesType, Cli}; + use crate::{Cli, models::sonarr_models::SeriesType}; use super::*; - use clap::{error::ErrorKind, CommandFactory, Parser}; + use clap::{CommandFactory, Parser, error::ErrorKind}; use pretty_assertions::assert_eq; use rstest::rstest; @@ -32,7 +32,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "edit", "all-indexer-settings"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -57,7 +57,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -78,11 +78,12 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -108,18 +109,19 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] fn test_edit_indexer_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "edit", "indexer"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -137,7 +139,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -157,7 +159,7 @@ mod tests { "--disable-rss", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -174,7 +176,7 @@ mod tests { "--disable-automatic-search", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -191,7 +193,7 @@ mod tests { "--disable-interactive-search", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -209,7 +211,7 @@ mod tests { "--clear-tags", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -227,7 +229,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -261,11 +263,12 @@ mod tests { "Test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -300,11 +303,12 @@ mod tests { "2", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -352,18 +356,19 @@ mod tests { "25", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] fn test_edit_series_requires_arguments() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "edit", "series"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -381,7 +386,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -401,7 +406,7 @@ mod tests { "--disable-monitoring", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -418,7 +423,7 @@ mod tests { "--disable-season-folders", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -436,7 +441,7 @@ mod tests { "--clear-tags", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); } @@ -461,7 +466,7 @@ mod tests { flag, ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -478,7 +483,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -509,11 +514,12 @@ mod tests { "/nfs/test", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -545,11 +551,12 @@ mod tests { "2", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } #[test] @@ -591,11 +598,12 @@ mod tests { "2", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command { - assert_eq!(edit_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Edit(edit_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(edit_command, expected_args); } } @@ -609,15 +617,15 @@ mod tests { use crate::{ app::App, cli::{ - sonarr::edit_command_handler::{SonarrEditCommand, SonarrEditCommandHandler}, CliCommandHandler, + sonarr::edit_command_handler::{SonarrEditCommand, SonarrEditCommandHandler}, }, models::{ + Serdeable, servarr_models::EditIndexerParams, sonarr_models::{EditSeriesParams, IndexerSettings, SeriesType, SonarrSerdeable}, - Serdeable, }, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -674,7 +682,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -728,7 +736,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -776,7 +784,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -824,7 +832,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -872,7 +880,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/get_command_handler.rs b/src/cli/sonarr/get_command_handler.rs index c6b9ffe..19fe351 100644 --- a/src/cli/sonarr/get_command_handler.rs +++ b/src/cli/sonarr/get_command_handler.rs @@ -7,7 +7,7 @@ use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/get_command_handler_tests.rs b/src/cli/sonarr/get_command_handler_tests.rs index 202b174..b8e4a8a 100644 --- a/src/cli/sonarr/get_command_handler_tests.rs +++ b/src/cli/sonarr/get_command_handler_tests.rs @@ -1,10 +1,10 @@ #[cfg(test)] mod tests { - use crate::cli::{ - sonarr::{get_command_handler::SonarrGetCommand, SonarrCommand}, - Command, - }; use crate::Cli; + use crate::cli::{ + Command, + sonarr::{SonarrCommand, get_command_handler::SonarrGetCommand}, + }; use clap::CommandFactory; use pretty_assertions::assert_eq; @@ -28,7 +28,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "get", "all-indexer-settings"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -36,7 +36,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "get", "system-status"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -44,7 +44,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "get", "episode-details"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -62,7 +62,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -70,7 +70,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "get", "host-config"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -78,7 +78,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "get", "security-config"]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -86,7 +86,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "get", "series-details"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -104,7 +104,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -118,11 +118,11 @@ mod tests { use crate::{ app::App, cli::{ - sonarr::get_command_handler::{SonarrGetCommand, SonarrGetCommandHandler}, CliCommandHandler, + sonarr::get_command_handler::{SonarrGetCommand, SonarrGetCommandHandler}, }, - models::{sonarr_models::SonarrSerdeable, Serdeable}, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + models::{Serdeable, sonarr_models::SonarrSerdeable}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -150,7 +150,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -176,7 +176,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -199,7 +199,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -222,7 +222,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -248,7 +248,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -271,7 +271,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/list_command_handler.rs b/src/cli/sonarr/list_command_handler.rs index 5a9ecda..a2dbfeb 100644 --- a/src/cli/sonarr/list_command_handler.rs +++ b/src/cli/sonarr/list_command_handler.rs @@ -7,7 +7,7 @@ use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/list_command_handler_tests.rs b/src/cli/sonarr/list_command_handler_tests.rs index 94c755c..2c51b0f 100644 --- a/src/cli/sonarr/list_command_handler_tests.rs +++ b/src/cli/sonarr/list_command_handler_tests.rs @@ -1,10 +1,10 @@ #[cfg(test)] mod tests { - use crate::cli::{ - sonarr::{list_command_handler::SonarrListCommand, SonarrCommand}, - Command, - }; use crate::Cli; + use crate::cli::{ + Command, + sonarr::{SonarrCommand, list_command_handler::SonarrListCommand}, + }; use clap::CommandFactory; use pretty_assertions::assert_eq; @@ -19,7 +19,7 @@ mod tests { mod cli { use super::*; - use clap::{error::ErrorKind, Parser}; + use clap::{Parser, error::ErrorKind}; use pretty_assertions::assert_eq; use rstest::rstest; @@ -42,14 +42,14 @@ mod tests { ) { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", subcommand]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_list_episodes_requires_series_id() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "episodes"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -61,7 +61,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "episode-files"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -73,7 +73,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "episode-history"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -92,13 +92,14 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(episode_history_command))) = + let Some(Command::Sonarr(SonarrCommand::List(episode_history_command))) = result.unwrap().command - { - assert_eq!(episode_history_command, expected_args); - } + else { + panic!("Unexpected command type"); + }; + assert_eq!(episode_history_command, expected_args); } #[test] @@ -106,7 +107,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "downloads", "--count"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -115,12 +116,13 @@ mod tests { let expected_args = SonarrListCommand::Downloads { count: 500 }; let result = Cli::try_parse_from(["managarr", "sonarr", "list", "downloads"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(downloads_command))) = result.unwrap().command - { - assert_eq!(downloads_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::List(downloads_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(downloads_command, expected_args); } #[test] @@ -128,7 +130,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "history", "--events"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -137,11 +139,13 @@ mod tests { let expected_args = SonarrListCommand::History { events: 500 }; let result = Cli::try_parse_from(["managarr", "sonarr", "list", "history"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(history_command))) = result.unwrap().command { - assert_eq!(history_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::List(history_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(history_command, expected_args); } #[test] @@ -149,7 +153,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "logs", "--events"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -161,11 +165,12 @@ mod tests { }; let result = Cli::try_parse_from(["managarr", "sonarr", "list", "logs"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(logs_command))) = result.unwrap().command { - assert_eq!(logs_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::List(logs_command))) = result.unwrap().command else { + panic!("Unexpected command type"); + }; + assert_eq!(logs_command, expected_args); } #[test] @@ -174,12 +179,13 @@ mod tests { let result = Cli::try_parse_from(["managarr", "sonarr", "list", "episodes", "--series-id", "1"]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(episodes_command))) = result.unwrap().command - { - assert_eq!(episodes_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::List(episodes_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(episodes_command, expected_args); } #[test] @@ -194,13 +200,14 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(episode_files_command))) = + let Some(Command::Sonarr(SonarrCommand::List(episode_files_command))) = result.unwrap().command - { - assert_eq!(episode_files_command, expected_args); - } + else { + panic!("Unexpected command type"); + }; + assert_eq!(episode_files_command, expected_args); } #[test] @@ -214,7 +221,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -232,7 +239,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -252,7 +259,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -260,7 +267,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "series-history"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -279,11 +286,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::List(series_command))) = result.unwrap().command { - assert_eq!(series_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::List(series_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(series_command, expected_args); } } @@ -296,10 +305,10 @@ mod tests { use serde_json::json; use tokio::sync::Mutex; - use crate::cli::sonarr::list_command_handler::{SonarrListCommand, SonarrListCommandHandler}; use crate::cli::CliCommandHandler; - use crate::models::sonarr_models::SonarrSerdeable; + use crate::cli::sonarr::list_command_handler::{SonarrListCommand, SonarrListCommandHandler}; use crate::models::Serdeable; + use crate::models::sonarr_models::SonarrSerdeable; use crate::network::sonarr_network::SonarrEvent; use crate::{ app::App, @@ -339,7 +348,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -365,7 +374,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -391,7 +400,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -417,7 +426,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -443,7 +452,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -471,7 +480,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -497,7 +506,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -523,7 +532,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -553,7 +562,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/manual_search_command_handler.rs b/src/cli/sonarr/manual_search_command_handler.rs index b2972bf..22dafa2 100644 --- a/src/cli/sonarr/manual_search_command_handler.rs +++ b/src/cli/sonarr/manual_search_command_handler.rs @@ -7,7 +7,7 @@ use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/manual_search_command_handler_tests.rs b/src/cli/sonarr/manual_search_command_handler_tests.rs index 453c5fc..ddcb3fc 100644 --- a/src/cli/sonarr/manual_search_command_handler_tests.rs +++ b/src/cli/sonarr/manual_search_command_handler_tests.rs @@ -1,10 +1,10 @@ #[cfg(test)] mod tests { - use crate::cli::{ - sonarr::{manual_search_command_handler::SonarrManualSearchCommand, SonarrCommand}, - Command, - }; use crate::Cli; + use crate::cli::{ + Command, + sonarr::{SonarrCommand, manual_search_command_handler::SonarrManualSearchCommand}, + }; use clap::CommandFactory; use pretty_assertions::assert_eq; @@ -36,7 +36,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -54,7 +54,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -74,7 +74,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -82,7 +82,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "manual-search", "episode"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -100,7 +100,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -114,13 +114,13 @@ mod tests { use crate::{ app::App, cli::{ + CliCommandHandler, sonarr::manual_search_command_handler::{ SonarrManualSearchCommand, SonarrManualSearchCommandHandler, }, - CliCommandHandler, }, - models::{sonarr_models::SonarrSerdeable, Serdeable}, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + models::{Serdeable, sonarr_models::SonarrSerdeable}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -149,7 +149,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -182,7 +182,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/mod.rs b/src/cli/sonarr/mod.rs index ddc9f43..2a3c3c3 100644 --- a/src/cli/sonarr/mod.rs +++ b/src/cli/sonarr/mod.rs @@ -18,7 +18,7 @@ use trigger_automatic_search_command_handler::{ use crate::{ app::App, models::sonarr_models::SonarrTaskName, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::{CliCommandHandler, Command}; diff --git a/src/cli/sonarr/refresh_command_handler.rs b/src/cli/sonarr/refresh_command_handler.rs index 9daa179..c4a3f8d 100644 --- a/src/cli/sonarr/refresh_command_handler.rs +++ b/src/cli/sonarr/refresh_command_handler.rs @@ -6,7 +6,7 @@ use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/refresh_command_handler_tests.rs b/src/cli/sonarr/refresh_command_handler_tests.rs index 01d0c2e..e861c51 100644 --- a/src/cli/sonarr/refresh_command_handler_tests.rs +++ b/src/cli/sonarr/refresh_command_handler_tests.rs @@ -2,11 +2,11 @@ mod tests { use pretty_assertions::assert_eq; - use crate::cli::{ - sonarr::{refresh_command_handler::SonarrRefreshCommand, SonarrCommand}, - Command, - }; use crate::Cli; + use crate::cli::{ + Command, + sonarr::{SonarrCommand, refresh_command_handler::SonarrRefreshCommand}, + }; use clap::CommandFactory; #[test] @@ -20,7 +20,7 @@ mod tests { mod cli { use super::*; - use clap::{error::ErrorKind, Parser}; + use clap::{Parser, error::ErrorKind}; use pretty_assertions::assert_eq; use rstest::rstest; @@ -31,14 +31,14 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "refresh", subcommand]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_refresh_series_requires_series_id() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "refresh", "series"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -57,13 +57,13 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); - if let Some(Command::Sonarr(SonarrCommand::Refresh(refresh_command))) = - result.unwrap().command - { - assert_eq!(refresh_command, expected_args); - } + let Some(Command::Sonarr(SonarrCommand::Refresh(refresh_command))) = result.unwrap().command + else { + panic!("Unexpected command type"); + }; + assert_eq!(refresh_command, expected_args); } } @@ -77,11 +77,11 @@ mod tests { use crate::{app::App, cli::sonarr::refresh_command_handler::SonarrRefreshCommandHandler}; use crate::{ - cli::{sonarr::refresh_command_handler::SonarrRefreshCommand, CliCommandHandler}, + cli::{CliCommandHandler, sonarr::refresh_command_handler::SonarrRefreshCommand}, network::sonarr_network::SonarrEvent, }; use crate::{ - models::{sonarr_models::SonarrSerdeable, Serdeable}, + models::{Serdeable, sonarr_models::SonarrSerdeable}, network::{MockNetworkTrait, NetworkEvent}, }; @@ -109,7 +109,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -135,7 +135,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/sonarr_command_tests.rs b/src/cli/sonarr/sonarr_command_tests.rs index 838ef30..ac48082 100644 --- a/src/cli/sonarr/sonarr_command_tests.rs +++ b/src/cli/sonarr/sonarr_command_tests.rs @@ -1,10 +1,10 @@ #[cfg(test)] mod tests { - use crate::cli::{ - sonarr::{list_command_handler::SonarrListCommand, SonarrCommand}, - Command, - }; use crate::Cli; + use crate::cli::{ + Command, + sonarr::{SonarrCommand, list_command_handler::SonarrListCommand}, + }; use clap::CommandFactory; use pretty_assertions::assert_eq; @@ -29,7 +29,7 @@ mod tests { ) { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", subcommand]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -37,7 +37,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "mark-history-item-as-failed"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -54,14 +54,14 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_search_new_series_requires_query() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "search-new-series"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -78,14 +78,14 @@ mod tests { "halo", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_start_task_requires_task_name() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "start-task"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -102,7 +102,7 @@ mod tests { "test", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); } @@ -116,14 +116,14 @@ mod tests { "application-update-check", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] fn test_test_indexer_requires_indexer_id() { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "test-indexer"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -140,7 +140,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -148,7 +148,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "toggle-episode-monitoring"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -165,7 +165,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -178,7 +178,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -195,7 +195,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -214,7 +214,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -222,7 +222,7 @@ mod tests { let result = Cli::command().try_get_matches_from(["managarr", "sonarr", "toggle-series-monitoring"]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -239,7 +239,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -253,25 +253,25 @@ mod tests { use crate::{ app::App, cli::{ + CliCommandHandler, sonarr::{ - add_command_handler::SonarrAddCommand, delete_command_handler::SonarrDeleteCommand, + SonarrCliHandler, SonarrCommand, add_command_handler::SonarrAddCommand, + delete_command_handler::SonarrDeleteCommand, download_command_handler::SonarrDownloadCommand, edit_command_handler::SonarrEditCommand, get_command_handler::SonarrGetCommand, list_command_handler::SonarrListCommand, manual_search_command_handler::SonarrManualSearchCommand, refresh_command_handler::SonarrRefreshCommand, trigger_automatic_search_command_handler::SonarrTriggerAutomaticSearchCommand, - SonarrCliHandler, SonarrCommand, }, - CliCommandHandler, }, models::{ + Serdeable, sonarr_models::{ BlocklistItem, BlocklistResponse, IndexerSettings, Series, SonarrReleaseDownloadBody, SonarrSerdeable, SonarrTaskName, }, - Serdeable, }, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -304,7 +304,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -334,7 +334,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -361,7 +361,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -390,7 +390,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -426,7 +426,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -484,12 +484,12 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] - async fn test_sonarr_cli_handler_delegates_manual_search_commands_to_the_manual_search_command_handler( - ) { + async fn test_sonarr_cli_handler_delegates_manual_search_commands_to_the_manual_search_command_handler() + { let expected_episode_id = 1; let mut mock_network = MockNetworkTrait::new(); mock_network @@ -512,12 +512,12 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] - async fn test_sonarr_cli_handler_delegates_trigger_automatic_search_commands_to_the_trigger_automatic_search_command_handler( - ) { + async fn test_sonarr_cli_handler_delegates_trigger_automatic_search_commands_to_the_trigger_automatic_search_command_handler() + { let expected_episode_id = 1; let mut mock_network = MockNetworkTrait::new(); mock_network @@ -542,7 +542,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -564,7 +564,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -586,7 +586,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -612,7 +612,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -639,7 +639,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -666,7 +666,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -691,7 +691,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -713,7 +713,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -743,7 +743,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -776,7 +776,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -805,7 +805,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/cli/sonarr/trigger_automatic_search_command_handler.rs b/src/cli/sonarr/trigger_automatic_search_command_handler.rs index 27853f3..89bf285 100644 --- a/src/cli/sonarr/trigger_automatic_search_command_handler.rs +++ b/src/cli/sonarr/trigger_automatic_search_command_handler.rs @@ -7,7 +7,7 @@ use tokio::sync::Mutex; use crate::{ app::App, cli::{CliCommandHandler, Command}, - network::{sonarr_network::SonarrEvent, NetworkTrait}, + network::{NetworkTrait, sonarr_network::SonarrEvent}, }; use super::SonarrCommand; diff --git a/src/cli/sonarr/trigger_automatic_search_command_handler_tests.rs b/src/cli/sonarr/trigger_automatic_search_command_handler_tests.rs index 4ebeb56..c0054af 100644 --- a/src/cli/sonarr/trigger_automatic_search_command_handler_tests.rs +++ b/src/cli/sonarr/trigger_automatic_search_command_handler_tests.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod tests { - use crate::cli::{ - sonarr::{ - trigger_automatic_search_command_handler::SonarrTriggerAutomaticSearchCommand, SonarrCommand, - }, - Command, - }; use crate::Cli; + use crate::cli::{ + Command, + sonarr::{ + SonarrCommand, trigger_automatic_search_command_handler::SonarrTriggerAutomaticSearchCommand, + }, + }; use clap::CommandFactory; use pretty_assertions::assert_eq; @@ -36,7 +36,7 @@ mod tests { "series", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -54,7 +54,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -68,7 +68,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -86,7 +86,7 @@ mod tests { "1", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -106,7 +106,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } #[test] @@ -118,7 +118,7 @@ mod tests { "episode", ]); - assert!(result.is_err()); + assert_err!(&result); assert_eq!( result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument @@ -136,7 +136,7 @@ mod tests { "1", ]); - assert!(result.is_ok()); + assert_ok!(&result); } } @@ -150,13 +150,13 @@ mod tests { use crate::{ app::App, cli::{ + CliCommandHandler, sonarr::trigger_automatic_search_command_handler::{ SonarrTriggerAutomaticSearchCommand, SonarrTriggerAutomaticSearchCommandHandler, }, - CliCommandHandler, }, - models::{sonarr_models::SonarrSerdeable, Serdeable}, - network::{sonarr_network::SonarrEvent, MockNetworkTrait, NetworkEvent}, + models::{Serdeable, sonarr_models::SonarrSerdeable}, + network::{MockNetworkTrait, NetworkEvent, sonarr_network::SonarrEvent}, }; #[tokio::test] @@ -186,7 +186,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -220,7 +220,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } #[tokio::test] @@ -250,7 +250,7 @@ mod tests { .handle() .await; - assert!(result.is_ok()); + assert_ok!(&result); } } } diff --git a/src/event/input_event.rs b/src/event/input_event.rs index 9626979..cfded37 100644 --- a/src/event/input_event.rs +++ b/src/event/input_event.rs @@ -28,14 +28,14 @@ impl Events { let timeout = tick_rate .checked_sub(last_tick.elapsed()) .unwrap_or_else(|| Duration::from_secs(0)); - if event::poll(timeout).unwrap() { - if let CrosstermEvent::Key(key_event) = event::read().unwrap() { - // Only process the key event if it's a press event - // Source: https://ratatui.rs/faq/ Why am I getting duplicate key events on Windows? - if key_event.kind == KeyEventKind::Press { - let key = Key::from(key_event); - tx.send(InputEvent::KeyEvent(key)).unwrap(); - } + if event::poll(timeout).unwrap() + && let CrosstermEvent::Key(key_event) = event::read().unwrap() + { + // Only process the key event if it's a press event + // Source: https://ratatui.rs/faq/ Why am I getting duplicate key events on Windows? + if key_event.kind == KeyEventKind::Press { + let key = Key::from(key_event); + tx.send(InputEvent::KeyEvent(key)).unwrap(); } } diff --git a/src/handlers/handler_proptest.rs b/src/handlers/handler_proptest.rs new file mode 100644 index 0000000..83fe8d6 --- /dev/null +++ b/src/handlers/handler_proptest.rs @@ -0,0 +1,221 @@ +#[cfg(test)] +mod property_tests { + use proptest::prelude::*; + + use crate::app::App; + use crate::handlers::handler_test_utils::test_utils::proptest_helpers::*; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; + use crate::models::stateful_table::StatefulTable; + use crate::models::radarr_models::Movie; + use crate::models::{Scrollable, Paginated}; + + proptest! { + /// Property test: Table never panics on index selection + #[test] + fn test_table_index_selection_safety( + list_size in list_size(), + index in 0usize..1000 + ) { + let mut table = StatefulTable::::default(); + let movies: Vec = (0..list_size).map(|i| { + let mut movie = Movie::default(); + movie.id = i as i64; + movie + }).collect(); + + table.set_items(movies); + + // Try to select an arbitrary index + if index < list_size { + table.select_index(Some(index)); + let selected = table.current_selection(); + prop_assert_eq!(selected.id, index as i64); + } else { + // Out of bounds selection should be safe + table.select_index(Some(index)); + // Should not panic, selection stays valid + } + } + + /// Property test: Table state remains consistent after scroll operations + #[test] + fn test_table_scroll_consistency( + list_size in list_size(), + scroll_amount in 0usize..20 + ) { + let mut table = StatefulTable::::default(); + let movies: Vec = (0..list_size).map(|i| { + let mut movie = Movie::default(); + movie.id = i as i64; + movie + }).collect(); + + table.set_items(movies); + let initial_id = table.current_selection().id; + + // Scroll down multiple times + for _ in 0..scroll_amount { + table.scroll_down(); + } + let after_down_id = table.current_selection().id; + + // Position should increase (up to max) + prop_assert!(after_down_id >= initial_id); + prop_assert!(after_down_id < list_size as i64); + + // Scroll back up + for _ in 0..scroll_amount { + table.scroll_up(); + } + + // Should return to initial position (or 0 if we hit the top) + prop_assert!(table.current_selection().id <= initial_id); + } + + /// Property test: Empty tables handle operations gracefully + #[test] + fn test_empty_table_safety(_scroll_ops in 0usize..50) { + let table = StatefulTable::::default(); + + // Empty table operations should be safe + prop_assert!(table.is_empty()); + prop_assert!(table.items.is_empty()); + } + + /// Property test: Navigation operations maintain consistency + #[test] + fn test_navigation_consistency(pushes in 1usize..20) { + let mut app = App::test_default(); + let initial_route = app.get_current_route(); + + // Push multiple routes + let routes = vec![ + ActiveRadarrBlock::Movies, + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::Downloads, + ActiveRadarrBlock::Blocklist, + ]; + + for i in 0..pushes { + let route = routes[i % routes.len()]; + app.push_navigation_stack(route.into()); + } + + // Current route should be the last pushed + let last_pushed = routes[(pushes - 1) % routes.len()]; + prop_assert_eq!(app.get_current_route(), last_pushed.into()); + + // Pop all routes + for _ in 0..pushes { + app.pop_navigation_stack(); + } + + // Should return to initial route + prop_assert_eq!(app.get_current_route(), initial_route); + } + + /// Property test: String input handling is safe + #[test] + fn test_string_input_safety(input in text_input_string()) { + // String operations should never panic + let _lowercase = input.to_lowercase(); + let _uppercase = input.to_uppercase(); + let _trimmed = input.trim(); + let _len = input.len(); + let _chars: Vec = input.chars().collect(); + + // All operations completed without panic + prop_assert!(true); + } + + /// Property test: Table maintains data integrity after operations + #[test] + fn test_table_data_integrity( + list_size in 1usize..100 + ) { + let mut table = StatefulTable::::default(); + let movies: Vec = (0..list_size).map(|i| { + let mut movie = Movie::default(); + movie.id = i as i64; + movie.title = format!("Movie {}", i).into(); + movie + }).collect(); + + table.set_items(movies.clone()); + let original_count = table.items.len(); + + // Count should remain the same after various operations + prop_assert_eq!(table.items.len(), original_count); + + // All original items should still be present + for movie in &movies { + prop_assert!(table.items.iter().any(|m| m.id == movie.id)); + } + } + + /// Property test: Page up/down maintains bounds + #[test] + fn test_page_navigation_bounds( + list_size in list_size(), + page_ops in 0usize..10 + ) { + let mut table = StatefulTable::::default(); + let movies: Vec = (0..list_size).map(|i| { + let mut movie = Movie::default(); + movie.id = i as i64; + movie + }).collect(); + + table.set_items(movies); + + // Perform page operations + for i in 0..page_ops { + if i % 2 == 0 { + table.page_down(); + } else { + table.page_up(); + } + + // Should never exceed bounds + let current = table.current_selection(); + prop_assert!(current.id >= 0); + prop_assert!(current.id < list_size as i64); + } + } + + /// Property test: Table filtering reduces or maintains size + #[test] + fn test_table_filter_size_invariant( + list_size in list_size(), + filter_term in text_input_string() + ) { + let mut table = StatefulTable::::default(); + let movies: Vec = (0..list_size).map(|i| { + let mut movie = Movie::default(); + movie.id = i as i64; + movie.title = format!("Test Movie {}", i % 10).into(); + movie + }).collect(); + + table.set_items(movies.clone()); + let original_size = table.items.len(); + + // Apply filter + if !filter_term.is_empty() { + let filtered: Vec = movies.into_iter() + .filter(|m| m.title.text.to_lowercase().contains(&filter_term.to_lowercase())) + .collect(); + table.set_items(filtered); + } + + // Filtered size should be <= original + prop_assert!(table.items.len() <= original_size); + + // Selection should still be valid if table not empty + if !table.items.is_empty() { + let current = table.current_selection(); + prop_assert!(current.id >= 0); + } + } + } +} diff --git a/src/handlers/handler_test_utils.rs b/src/handlers/handler_test_utils.rs index 64bfada..f3348c4 100644 --- a/src/handlers/handler_test_utils.rs +++ b/src/handlers/handler_test_utils.rs @@ -452,4 +452,40 @@ mod test_utils { assert!(app.should_refresh); }; } + + #[macro_export] + macro_rules! assert_modal_present { + ($modal:expr) => { + assert!($modal.is_some(), "Expected modal to be present"); + }; + } + + #[macro_export] + macro_rules! assert_modal_absent { + ($modal:expr) => { + assert!($modal.is_none(), "Expected modal to be absent"); + }; + } + + #[macro_export] + macro_rules! assert_navigation_pushed { + ($app:expr, $expected_route:expr) => { + pretty_assertions::assert_eq!( + $app.get_current_route(), + $expected_route, + "Expected route to be pushed onto navigation stack" + ); + }; + } + + #[macro_export] + macro_rules! assert_navigation_popped { + ($app:expr, $expected_route:expr) => { + pretty_assertions::assert_eq!( + $app.get_current_route(), + $expected_route, + "Expected route after popping navigation stack" + ); + }; + } } diff --git a/src/handlers/handlers_tests.rs b/src/handlers/handlers_tests.rs index ac81556..650511c 100644 --- a/src/handlers/handlers_tests.rs +++ b/src/handlers/handlers_tests.rs @@ -1,27 +1,30 @@ #[cfg(test)] mod tests { + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::models::radarr_models::Movie; use crate::models::sonarr_models::Series; + use crate::{assert_modal_present, assert_navigation_popped}; use pretty_assertions::assert_eq; use rstest::rstest; use tokio_util::sync::CancellationToken; + use crate::app::App; use crate::app::context_clues::SERVARR_CONTEXT_CLUES; - use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS}; + use crate::app::key_binding::{DEFAULT_KEYBINDINGS, KeyBinding}; use crate::app::radarr::radarr_context_clues::{ LIBRARY_CONTEXT_CLUES, MOVIE_DETAILS_CONTEXT_CLUES, }; - use crate::app::App; use crate::event::Key; use crate::handlers::{handle_clear_errors, handle_prompt_toggle}; use crate::handlers::{handle_events, populate_keymapping_table}; - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; - use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; - use crate::models::servarr_data::ActiveKeybindingBlock; - use crate::models::servarr_models::KeybindingItem; - use crate::models::stateful_table::StatefulTable; use crate::models::HorizontallyScrollableText; use crate::models::Route; + use crate::models::servarr_data::ActiveKeybindingBlock; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; + use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; + use crate::models::servarr_models::KeybindingItem; + use crate::models::stateful_table::StatefulTable; #[test] fn test_handle_clear_errors() { @@ -30,7 +33,7 @@ mod tests { handle_clear_errors(&mut app); - assert!(app.error.text.is_empty()); + assert_is_empty!(app.error.text); } #[rstest] @@ -53,7 +56,7 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.esc.key, &mut app); - assert_eq!(app.get_current_route(), base_block); + assert_navigation_popped!(app, base_block); } #[rstest] @@ -70,7 +73,7 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.previous_servarr.key, &mut app); assert_eq!(app.server_tabs.get_active_route(), left_block.into()); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); assert!(app.is_first_render); assert_eq!(app.error, HorizontallyScrollableText::default()); assert!(app.cancellation_token.is_cancelled()); @@ -83,7 +86,7 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.next_servarr.key, &mut app); assert_eq!(app.server_tabs.get_active_route(), right_block.into()); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); assert!(app.is_first_render); assert_eq!(app.error, HorizontallyScrollableText::default()); assert!(app.cancellation_token.is_cancelled()); @@ -100,7 +103,7 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.help.key, &mut app); - assert!(app.keymapping_table.is_some()); + assert_modal_present!(app.keymapping_table); assert_eq!( expected_keybinding_items, app.keymapping_table.unwrap().items @@ -115,12 +118,12 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.help.key, &mut app); - assert!(app.keymapping_table.is_none()); + assert_modal_absent!(app.keymapping_table); } #[test] - fn test_handle_empties_keybindings_table_on_help_button_press_when_keybindings_table_is_already_populated( - ) { + fn test_handle_empties_keybindings_table_on_help_button_press_when_keybindings_table_is_already_populated() + { let mut app = App::test_default(); let keybinding_items = Vec::from(SERVARR_CONTEXT_CLUES) .iter() @@ -133,7 +136,7 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.help.key, &mut app); - assert!(app.keymapping_table.is_none()); + assert_modal_absent!(app.keymapping_table); } #[test] @@ -158,7 +161,7 @@ mod tests { handle_events(DEFAULT_KEYBINDINGS.down.key, &mut app); - assert!(app.keymapping_table.is_some()); + assert_modal_present!(app.keymapping_table); assert_eq!( &expected_selection, app.keymapping_table.unwrap().current_selection() @@ -219,7 +222,7 @@ mod tests { populate_keymapping_table(&mut app); - assert!(app.keymapping_table.is_some()); + assert_modal_present!(app.keymapping_table); assert_eq!( expected_keybinding_items, app.keymapping_table.unwrap().items @@ -243,7 +246,7 @@ mod tests { populate_keymapping_table(&mut app); - assert!(app.keymapping_table.is_some()); + assert_modal_present!(app.keymapping_table); assert_eq!( expected_keybinding_items, app.keymapping_table.unwrap().items @@ -251,8 +254,8 @@ mod tests { } #[test] - fn test_populate_keymapping_table_populates_delegated_servarr_context_provider_options_before_global_options( - ) { + fn test_populate_keymapping_table_populates_delegated_servarr_context_provider_options_before_global_options() + { let mut expected_keybinding_items = MOVIE_DETAILS_CONTEXT_CLUES .iter() .map(|(key, desc)| context_clue_to_keybinding_item(key, desc)) @@ -268,7 +271,7 @@ mod tests { populate_keymapping_table(&mut app); - assert!(app.keymapping_table.is_some()); + assert_modal_present!(app.keymapping_table); assert_eq!( expected_keybinding_items, app.keymapping_table.unwrap().items diff --git a/src/handlers/keybinding_handler.rs b/src/handlers/keybinding_handler.rs index b33dfbd..b9560a0 100644 --- a/src/handlers/keybinding_handler.rs +++ b/src/handlers/keybinding_handler.rs @@ -1,10 +1,8 @@ use crate::app::App; use crate::event::Key; -use crate::handle_table_events; -use crate::handlers::table_handler::TableHandlingConfig; use crate::handlers::KeyEventHandler; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::models::servarr_data::ActiveKeybindingBlock; -use crate::models::servarr_models::KeybindingItem; #[cfg(test)] #[path = "keybinding_handler_tests.rs"] @@ -15,20 +13,15 @@ pub(super) struct KeybindingHandler<'a, 'b> { app: &'a mut App<'b>, } -impl KeybindingHandler<'_, '_> { - handle_table_events!( - self, - keybindings, - self.app.keymapping_table.as_mut().unwrap(), - KeybindingItem - ); -} - impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveKeybindingBlock> for KeybindingHandler<'a, 'b> { fn handle(&mut self) { let keybinding_table_handling_config = TableHandlingConfig::new(self.app.get_current_route()); - if !self.handle_keybindings_table_events(keybinding_table_handling_config) { + if !handle_table( + self, + |app| app.keymapping_table.as_mut().unwrap(), + keybinding_table_handling_config, + ) { self.handle_key_event(); } } @@ -77,4 +70,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveKeybindingBlock> for KeybindingHandle } fn handle_char_key_event(&mut self) {} + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/keybinding_handler_tests.rs b/src/handlers/keybinding_handler_tests.rs index 5a44ea8..49568a7 100644 --- a/src/handlers/keybinding_handler_tests.rs +++ b/src/handlers/keybinding_handler_tests.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::event::Key; use crate::handlers::KeyEventHandler; use crate::handlers::KeybindingHandler; @@ -11,6 +11,7 @@ mod tests { mod test_handle_esc { use super::*; + use crate::assert_modal_absent; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use pretty_assertions::assert_eq; @@ -25,7 +26,7 @@ mod tests { KeybindingHandler::new(ESC_KEY, &mut app, ActiveKeybindingBlock::Help, None).handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert!(app.keymapping_table.is_none()); + assert_modal_absent!(app.keymapping_table); } } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 619cd72..c64ef20 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,11 +1,11 @@ use radarr_handlers::RadarrHandler; use sonarr_handlers::SonarrHandler; +use crate::app::App; use crate::app::context_clues::{ - ContextClueProvider, ServarrContextClueProvider, SERVARR_CONTEXT_CLUES, + ContextClueProvider, SERVARR_CONTEXT_CLUES, ServarrContextClueProvider, }; use crate::app::key_binding::KeyBinding; -use crate::app::App; use crate::event::Key; use crate::handlers::keybinding_handler::KeybindingHandler; use crate::matches_key; @@ -93,6 +93,8 @@ pub trait KeyEventHandler<'a, 'b, T: Into + Copy> { fn handle_submit(&mut self); fn handle_esc(&mut self); fn handle_char_key_event(&mut self); + fn app_mut(&mut self) -> &mut App<'b>; + fn current_route(&self) -> Route; } pub fn handle_events(key: Key, app: &mut App<'_>) { @@ -128,7 +130,7 @@ pub fn handle_events(key: Key, app: &mut App<'_>) { } } -fn populate_keymapping_table(app: &mut App<'_>) { +pub fn populate_keymapping_table(app: &mut App<'_>) { let context_clue_to_keybinding_item = |key: &KeyBinding, desc: &&str| { let (key, alt_key) = if key.alt.is_some() { (key.key.to_string(), key.alt.as_ref().unwrap().to_string()) diff --git a/src/handlers/radarr_handlers/blocklist/blocklist_handler_tests.rs b/src/handlers/radarr_handlers/blocklist/blocklist_handler_tests.rs index bc76578..af27925 100644 --- a/src/handlers/radarr_handlers/blocklist/blocklist_handler_tests.rs +++ b/src/handlers/radarr_handlers/blocklist/blocklist_handler_tests.rs @@ -7,11 +7,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::radarr_handlers::blocklist::{blocklist_sorting_options, BlocklistHandler}; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::blocklist::{BlocklistHandler, blocklist_sorting_options}; use crate::models::radarr_models::{BlocklistItem, BlocklistItemMovie}; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS}; use crate::models::servarr_models::{Language, Quality, QualityWrapper}; @@ -30,10 +31,7 @@ mod tests { BlocklistHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::DeleteBlocklistItemPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::DeleteBlocklistItemPrompt.into()); } #[test] @@ -54,6 +52,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_blocklist_tab_left(#[values(true, false)] is_ready: bool) { @@ -73,7 +72,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Downloads.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Downloads.into()); } #[rstest] @@ -94,10 +93,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::RootFolders.into() ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::RootFolders.into()); } #[rstest] @@ -122,11 +118,11 @@ mod tests { } mod test_handle_submit { + use crate::assert_navigation_popped; + use crate::network::radarr_network::RadarrEvent; use pretty_assertions::assert_eq; use rstest::rstest; - use crate::network::radarr_network::RadarrEvent; - use super::*; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -139,10 +135,7 @@ mod tests { BlocklistHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::BlocklistItemDetails.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::BlocklistItemDetails.into()); } #[test] @@ -186,7 +179,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(expected_action) ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } #[rstest] @@ -205,18 +198,18 @@ mod tests { BlocklistHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveRadarrBlock::Blocklist.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use crate::handlers::radarr_handlers::downloads::DownloadsHandler; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -240,7 +233,7 @@ mod tests { BlocklistHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); - assert_eq!(app.get_current_route(), base_block.into()); + assert_navigation_popped!(app, base_block.into()); assert!(!app.data.radarr_data.prompt_confirm); } @@ -258,7 +251,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Blocklist.into()); } #[rstest] @@ -271,7 +264,7 @@ mod tests { DownloadsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Blocklist.into()); assert!(app.error.text.is_empty()); } } @@ -283,6 +276,7 @@ mod tests { use crate::network::radarr_network::RadarrEvent; use super::*; + use crate::{assert_navigation_popped, assert_navigation_pushed}; #[test] fn test_refresh_blocklist_key() { @@ -298,7 +292,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Blocklist.into()); assert!(app.should_refresh); } @@ -334,10 +328,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::BlocklistClearAllItemsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::BlocklistClearAllItemsPrompt.into()); } #[test] @@ -392,7 +383,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(expected_action) ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } } diff --git a/src/handlers/radarr_handlers/blocklist/mod.rs b/src/handlers/radarr_handlers/blocklist/mod.rs index 1160781..9cf43a0 100644 --- a/src/handlers/radarr_handlers/blocklist/mod.rs +++ b/src/handlers/radarr_handlers/blocklist/mod.rs @@ -1,13 +1,13 @@ use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; use crate::models::radarr_models::BlocklistItem; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS}; use crate::models::stateful_table::SortOption; use crate::network::radarr_network::RadarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "blocklist_handler_tests.rs"] @@ -21,13 +21,6 @@ pub(super) struct BlocklistHandler<'a, 'b> { } impl BlocklistHandler<'_, '_> { - handle_table_events!( - self, - blocklist, - self.app.data.radarr_data.blocklist, - BlocklistItem - ); - fn extract_blocklist_item_id(&self) -> i64 { self.app.data.radarr_data.blocklist.current_selection().id } @@ -38,10 +31,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a, let blocklist_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Blocklist.into()) .sorting_block(ActiveRadarrBlock::BlocklistSortPrompt.into()) - .sort_by_fn(|a: &BlocklistItem, b: &BlocklistItem| a.id.cmp(&b.id)) .sort_options(blocklist_sorting_options()); - if !self.handle_blocklist_table_events(blocklist_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.blocklist, + blocklist_table_handling_config, + ) { self.handle_key_event(); } } @@ -177,6 +173,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } fn blocklist_sorting_options() -> Vec> { diff --git a/src/handlers/radarr_handlers/collections/collection_details_handler.rs b/src/handlers/radarr_handlers/collections/collection_details_handler.rs index 70af277..2cb628b 100644 --- a/src/handlers/radarr_handlers/collections/collection_details_handler.rs +++ b/src/handlers/radarr_handlers/collections/collection_details_handler.rs @@ -1,15 +1,14 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::table_handler::TableHandlingConfig; use crate::handlers::KeyEventHandler; -use crate::models::radarr_models::CollectionMovie; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::matches_key; +use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, ADD_MOVIE_SELECTION_BLOCKS, COLLECTION_DETAILS_BLOCKS, + ADD_MOVIE_SELECTION_BLOCKS, ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; use crate::models::stateful_table::StatefulTable; -use crate::models::BlockSelectionState; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "collection_details_handler_tests.rs"] @@ -22,21 +21,18 @@ pub(super) struct CollectionDetailsHandler<'a, 'b> { _context: Option, } -impl CollectionDetailsHandler<'_, '_> { - handle_table_events!( - self, - collection_movies, - self.app.data.radarr_data.collection_movies, - CollectionMovie - ); -} +impl CollectionDetailsHandler<'_, '_> {} impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHandler<'a, 'b> { fn handle(&mut self) { let collection_movies_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::CollectionDetails.into()); - if !self.handle_collection_movies_table_events(collection_movies_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.collection_movies, + collection_movies_table_handling_config, + ) { self.handle_key_event(); } } @@ -147,4 +143,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS); } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs b/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs index 62fec18..2f5bdb8 100644 --- a/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs +++ b/src/handlers/radarr_handlers/collections/collection_details_handler_tests.rs @@ -4,23 +4,24 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; use crate::event::Key; - use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler; use crate::models::radarr_models::CollectionMovie; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, }; mod test_handle_submit { - use bimap::BiMap; - use pretty_assertions::assert_eq; - + use crate::assert_navigation_pushed; + use crate::models::BlockSelectionState; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; + use bimap::BiMap; + use pretty_assertions::assert_eq; use super::*; @@ -51,45 +52,51 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ( ActiveRadarrBlock::AddMoviePrompt, Some(ActiveRadarrBlock::CollectionDetails) ) .into() ); - assert!(!app - .data - .radarr_data - .add_movie_modal - .as_ref() - .unwrap() - .monitor_list - .items - .is_empty()); + assert!( + !app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .items + .is_empty() + ); assert_eq!( app.data.radarr_data.selected_block.get_active_block(), ActiveRadarrBlock::AddMovieSelectRootFolder ); - assert!(!app - .data - .radarr_data - .add_movie_modal - .as_ref() - .unwrap() - .minimum_availability_list - .items - .is_empty()); - assert!(!app - .data - .radarr_data - .add_movie_modal - .as_ref() - .unwrap() - .quality_profile_list - .items - .is_empty()); + assert!( + !app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .items + .is_empty() + ); + assert!( + !app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .items + .is_empty() + ); assert_str_eq!( app .data @@ -126,7 +133,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::CollectionDetails.into() ); - assert!(app.data.radarr_data.add_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.add_movie_modal); } #[test] @@ -151,16 +158,13 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::ViewMovieOverview.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::ViewMovieOverview.into()); } } mod test_handle_esc { use super::*; - use pretty_assertions::assert_eq; + use crate::assert_navigation_popped; use rstest::rstest; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -185,11 +189,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); - assert!(app.data.radarr_data.collection_movies.items.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); + assert_is_empty!(app.data.radarr_data.collection_movies.items); } #[test] @@ -206,10 +207,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::CollectionDetails.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::CollectionDetails.into()); } } @@ -221,7 +219,7 @@ mod tests { use crate::models::radarr_models::{Collection, MinimumAvailability}; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::servarr_data::radarr::radarr_data::{ - RadarrData, EDIT_COLLECTION_SELECTION_BLOCKS, + EDIT_COLLECTION_SELECTION_BLOCKS, RadarrData, }; use crate::test_edit_collection_key; @@ -264,7 +262,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::CollectionDetails.into() ); - assert!(app.data.radarr_data.edit_collection_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_collection_modal); } } diff --git a/src/handlers/radarr_handlers/collections/collections_handler_tests.rs b/src/handlers/radarr_handlers/collections/collections_handler_tests.rs index 6467417..2b15773 100644 --- a/src/handlers/radarr_handlers/collections/collections_handler_tests.rs +++ b/src/handlers/radarr_handlers/collections/collections_handler_tests.rs @@ -7,16 +7,18 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::radarr_handlers::collections::{ - collections_sorting_options, CollectionsHandler, - }; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::collections::{ + CollectionsHandler, collections_sorting_options, + }; use crate::models::radarr_models::{Collection, CollectionMovie}; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, + ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, COLLECTIONS_BLOCKS, EDIT_COLLECTION_BLOCKS, }; use crate::test_handler_delegation; @@ -25,6 +27,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_collections_tab_left(#[values(true, false)] is_ready: bool) { @@ -44,7 +47,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Movies.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Movies.into()); } #[rstest] @@ -65,7 +68,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Downloads.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Downloads.into()); } #[rstest] @@ -97,9 +100,9 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; use super::*; @@ -116,10 +119,7 @@ mod tests { CollectionsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::CollectionDetails.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::CollectionDetails.into()); } #[test] @@ -166,10 +166,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::UpdateCollections) ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); } #[test] @@ -192,17 +189,13 @@ mod tests { .handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use super::*; @@ -224,10 +217,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); assert!(!app.data.radarr_data.prompt_confirm); } @@ -242,11 +232,8 @@ mod tests { CollectionsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); + assert_is_empty!(app.error.text); } } @@ -258,10 +245,10 @@ mod tests { use crate::models::radarr_models::MinimumAvailability; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::servarr_data::radarr::radarr_data::{ - RadarrData, EDIT_COLLECTION_SELECTION_BLOCKS, + EDIT_COLLECTION_SELECTION_BLOCKS, RadarrData, }; use crate::network::radarr_network::RadarrEvent; - use crate::test_edit_collection_key; + use crate::{assert_navigation_popped, test_edit_collection_key}; use super::*; @@ -298,7 +285,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::Collections.into() ); - assert!(app.data.radarr_data.edit_collection_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_collection_modal); } #[test] @@ -318,10 +305,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::UpdateAllCollectionsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::UpdateAllCollectionsPrompt.into()); } #[test] @@ -367,10 +351,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::Collections.into()); assert!(app.should_refresh); } @@ -424,10 +405,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::UpdateCollections) ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); } } diff --git a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs index 77426b9..dff7e63 100644 --- a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs +++ b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Scrollable; use crate::models::radarr_models::EditCollectionParams; use crate::models::servarr_data::radarr::modals::EditCollectionModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS}; -use crate::models::Scrollable; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; @@ -371,4 +371,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs b/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs index 8e9a0d4..ac355af 100644 --- a/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs +++ b/src/handlers/radarr_handlers/collections/edit_collection_handler_tests.rs @@ -5,12 +5,14 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::collections::edit_collection_handler::EditCollectionHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::collection; - use crate::handlers::KeyEventHandler; use crate::models::radarr_models::{Collection, EditCollectionParams, MinimumAvailability}; use crate::models::servarr_data::radarr::modals::EditCollectionModal; use crate::models::servarr_data::radarr::radarr_data::{ @@ -22,9 +24,9 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; + use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::modals::EditCollectionModal; use crate::models::servarr_data::radarr::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use super::*; @@ -443,13 +445,13 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::radarr::modals::EditCollectionModal; use crate::models::servarr_data::radarr::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; use crate::models::{BlockSelectionState, Route}; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; + use rstest::rstest; use super::*; @@ -475,19 +477,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_collection_modal - .as_ref() - .unwrap() - .path - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditCollectionPrompt.into() + assert!( + !app + .data + .radarr_data + .edit_collection_modal + .as_ref() + .unwrap() + .path + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditCollectionPrompt.into()); } #[test] @@ -512,11 +513,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); } #[test] @@ -569,16 +567,13 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::EditCollection(expected_edit_collection_params)) ); assert!(app.should_refresh); - assert!(app.data.radarr_data.edit_collection_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_collection_modal); } #[test] @@ -609,7 +604,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditCollectionPrompt.into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.should_refresh); } @@ -634,7 +629,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .radarr_data @@ -642,7 +637,7 @@ mod tests { .as_ref() .unwrap() .monitored, - Some(true) + true ); EditCollectionHandler::new( @@ -654,7 +649,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .radarr_data @@ -662,7 +657,7 @@ mod tests { .as_ref() .unwrap() .monitored, - Some(false) + false ); } @@ -692,7 +687,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .radarr_data @@ -700,7 +695,7 @@ mod tests { .as_ref() .unwrap() .search_on_add, - Some(true) + true ); EditCollectionHandler::new( @@ -712,7 +707,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .radarr_data @@ -720,7 +715,7 @@ mod tests { .as_ref() .unwrap() .search_on_add, - Some(false) + false ); } @@ -753,11 +748,11 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, (selected_block, Some(ActiveRadarrBlock::Collections)).into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput { assert!(app.ignore_special_keys_for_textbox_input); @@ -786,10 +781,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditCollectionPrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditCollectionPrompt.into()); if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput { assert!(!app.ignore_special_keys_for_textbox_input); @@ -798,10 +790,9 @@ mod tests { } mod test_handle_esc { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use rstest::rstest; use super::*; @@ -825,10 +816,7 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditCollectionPrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditCollectionPrompt.into()); } #[test] @@ -846,13 +834,10 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); let radarr_data = &app.data.radarr_data; - assert!(radarr_data.edit_collection_modal.is_none()); + assert_modal_absent!(radarr_data.edit_collection_modal); assert!(!radarr_data.prompt_confirm); } @@ -873,21 +858,19 @@ mod tests { EditCollectionHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); } } mod test_handle_key_char { use super::*; use crate::{ + assert_navigation_popped, models::{ + BlockSelectionState, servarr_data::radarr::{ modals::EditCollectionModal, radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS, }, - BlockSelectionState, }, network::radarr_network::RadarrEvent, }; @@ -996,16 +979,13 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::Collections.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::EditCollection(expected_edit_collection_params)) ); assert!(app.should_refresh); - assert!(app.data.radarr_data.edit_collection_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_collection_modal); } } @@ -1080,7 +1060,7 @@ mod tests { .build_edit_collection_params(); assert_eq!(edit_collection_params, expected_edit_collection_params); - assert!(app.data.radarr_data.edit_collection_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_collection_modal); } #[test] diff --git a/src/handlers/radarr_handlers/collections/mod.rs b/src/handlers/radarr_handlers/collections/mod.rs index 2164080..69e22d1 100644 --- a/src/handlers/radarr_handlers/collections/mod.rs +++ b/src/handlers/radarr_handlers/collections/mod.rs @@ -3,16 +3,16 @@ use crate::event::Key; use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler; use crate::handlers::radarr_handlers::collections::edit_collection_handler::EditCollectionHandler; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; +use crate::models::BlockSelectionState; use crate::models::radarr_models::Collection; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTIONS_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; use crate::models::stateful_table::SortOption; -use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; -use crate::{handle_table_events, matches_key}; mod collection_details_handler; mod edit_collection_handler; @@ -28,21 +28,13 @@ pub(super) struct CollectionsHandler<'a, 'b> { context: Option, } -impl CollectionsHandler<'_, '_> { - handle_table_events!( - self, - collections, - self.app.data.radarr_data.collections, - Collection - ); -} +impl CollectionsHandler<'_, '_> {} impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'a, 'b> { fn handle(&mut self) { let collections_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Collections.into()) .sorting_block(ActiveRadarrBlock::CollectionsSortPrompt.into()) - .sort_by_fn(|a: &Collection, b: &Collection| a.id.cmp(&b.id)) .sort_options(collections_sorting_options()) .searching_block(ActiveRadarrBlock::SearchCollection.into()) .search_error_block(ActiveRadarrBlock::SearchCollectionError.into()) @@ -51,7 +43,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<' .filter_error_block(ActiveRadarrBlock::FilterCollectionsError.into()) .filter_field_fn(|collection| &collection.title.text); - if !self.handle_collections_table_events(collections_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.collections, + collections_table_handling_config, + ) { match self.active_radarr_block { _ if CollectionDetailsHandler::accepts(self.active_radarr_block) => { CollectionDetailsHandler::new(self.key, self.app, self.active_radarr_block, self.context) @@ -178,6 +174,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } fn collections_sorting_options() -> Vec> { diff --git a/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs b/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs index bbdd673..afc9805 100644 --- a/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs +++ b/src/handlers/radarr_handlers/downloads/downloads_handler_tests.rs @@ -4,12 +4,13 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::downloads::DownloadsHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::download_record; - use crate::handlers::KeyEventHandler; use crate::models::radarr_models::DownloadRecord; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; @@ -31,10 +32,7 @@ mod tests { DownloadsHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::DeleteDownloadPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::DeleteDownloadPrompt.into()); } #[test] @@ -78,10 +76,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Collections.into() ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::Collections.into()); } #[rstest] @@ -102,7 +97,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Blocklist.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Blocklist.into()); } #[rstest] @@ -133,6 +128,7 @@ mod tests { use crate::network::radarr_network::RadarrEvent; use super::*; + use crate::assert_navigation_popped; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -169,7 +165,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(expected_action) ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } #[rstest] @@ -191,16 +187,16 @@ mod tests { DownloadsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), base_route.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, base_route.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -218,7 +214,7 @@ mod tests { DownloadsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); - assert_eq!(app.get_current_route(), base_block.into()); + assert_navigation_popped!(app, base_block.into()); assert!(!app.data.radarr_data.prompt_confirm); } @@ -232,17 +228,17 @@ mod tests { DownloadsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::Downloads.into()); + assert_is_empty!(app.error.text); } } mod test_handle_key_char { + use crate::assert_navigation_popped; + use crate::network::radarr_network::RadarrEvent; use pretty_assertions::assert_eq; use rstest::rstest; - use crate::network::radarr_network::RadarrEvent; - use super::*; #[test] @@ -262,10 +258,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::UpdateDownloadsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::UpdateDownloadsPrompt.into()); } #[test] @@ -308,7 +301,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Downloads.into()); assert!(app.should_refresh); } @@ -373,7 +366,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(expected_action) ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } } diff --git a/src/handlers/radarr_handlers/downloads/mod.rs b/src/handlers/radarr_handlers/downloads/mod.rs index 173019f..3a449d1 100644 --- a/src/handlers/radarr_handlers/downloads/mod.rs +++ b/src/handlers/radarr_handlers/downloads/mod.rs @@ -1,12 +1,11 @@ use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::radarr_models::DownloadRecord; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; use crate::network::radarr_network::RadarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "downloads_handler_tests.rs"] @@ -20,13 +19,6 @@ pub(super) struct DownloadsHandler<'a, 'b> { } impl DownloadsHandler<'_, '_> { - handle_table_events!( - self, - downloads, - self.app.data.radarr_data.downloads, - DownloadRecord - ); - fn extract_download_id(&self) -> i64 { self.app.data.radarr_data.downloads.current_selection().id } @@ -37,7 +29,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a, let downloads_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Downloads.into()); - if !self.handle_downloads_table_events(downloads_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.downloads, + downloads_table_handling_config, + ) { self.handle_key_event(); } } @@ -163,4 +159,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs index d9ba23c..33a2383 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs @@ -1,6 +1,6 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::servarr_models::EditIndexerParams; @@ -522,4 +522,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs index b3107f2..179e7fe 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs @@ -1,11 +1,14 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::servarr_models::EditIndexerParams; @@ -18,9 +21,9 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; + use crate::models::BlockSelectionState; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use super::*; @@ -419,11 +422,11 @@ mod tests { use std::sync::atomic::Ordering; use crate::app::App; + use crate::models::BlockSelectionState; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, }; - use crate::models::BlockSelectionState; use pretty_assertions::assert_eq; use rstest::rstest; @@ -850,9 +853,10 @@ mod tests { use rstest::rstest; use crate::app::App; + use crate::assert_navigation_popped; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::{ - servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, }; use crate::network::radarr_network::RadarrEvent; @@ -882,10 +886,10 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.should_refresh); - assert_eq!(app.data.radarr_data.edit_indexer_modal, None); + assert_none!(app.data.radarr_data.edit_indexer_modal); } #[test] @@ -936,8 +940,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert!(app.data.radarr_data.edit_indexer_modal.is_none()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_modal_absent!(app.data.radarr_data.edit_indexer_modal); assert!(app.should_refresh); assert_eq!( app.data.radarr_data.prompt_confirm_action, @@ -966,9 +970,9 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(app.data.radarr_data.edit_indexer_modal.is_some()); + assert_modal_present!(app.data.radarr_data.edit_indexer_modal); assert!(!app.should_refresh); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); } #[rstest] @@ -1002,7 +1006,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), block.into()); + assert_navigation_pushed!(app, block.into()); assert!(app.ignore_special_keys_for_textbox_input); } @@ -1024,10 +1028,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPriorityInput.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::EditIndexerPriorityInput.into()); assert!(!app.ignore_special_keys_for_textbox_input); } @@ -1053,14 +1054,16 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_rss - .unwrap()); + assert!( + app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_rss + .unwrap() + ); EditIndexerHandler::new( SUBMIT_KEY, @@ -1074,14 +1077,16 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_rss - .unwrap()); + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_rss + .unwrap() + ); } #[test] @@ -1106,14 +1111,16 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_automatic_search - .unwrap()); + assert!( + app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_automatic_search + .unwrap() + ); EditIndexerHandler::new( SUBMIT_KEY, @@ -1127,14 +1134,16 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_automatic_search - .unwrap()); + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_automatic_search + .unwrap() + ); } #[test] @@ -1159,14 +1168,16 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_interactive_search - .unwrap()); + assert!( + app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_interactive_search + .unwrap() + ); EditIndexerHandler::new( SUBMIT_KEY, @@ -1180,14 +1191,16 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditIndexerPrompt.into() ); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_interactive_search - .unwrap()); + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_interactive_search + .unwrap() + ); } #[test] @@ -1211,19 +1224,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .name - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .name + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1247,19 +1259,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .url - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .url + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1283,19 +1294,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .api_key - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .api_key + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1319,19 +1329,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .seed_ratio - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .seed_ratio + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1355,25 +1364,25 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .tags - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .tags + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditIndexerPrompt.into()); } } mod test_handle_esc { use super::*; use crate::app::App; + use crate::assert_navigation_popped; use crate::event::Key; use crate::models::servarr_data::modals::EditIndexerModal; use pretty_assertions::assert_eq; @@ -1397,9 +1406,9 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.edit_indexer_modal, None); + assert_none!(app.data.radarr_data.edit_indexer_modal); } #[rstest] @@ -1422,7 +1431,7 @@ mod tests { EditIndexerHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert!(!app.ignore_special_keys_for_textbox_input); assert_eq!( app.data.radarr_data.edit_indexer_modal, @@ -1432,15 +1441,15 @@ mod tests { } mod test_handle_key_char { + use super::*; use crate::app::App; + use crate::assert_navigation_popped; + use crate::models::BlockSelectionState; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; use pretty_assertions::{assert_eq, assert_str_eq}; - use super::*; - #[test] fn test_edit_indexer_name_input_backspace() { let mut app = App::test_default(); @@ -1773,8 +1782,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert!(app.data.radarr_data.edit_indexer_modal.is_none()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_modal_absent!(app.data.radarr_data.edit_indexer_modal); assert!(app.should_refresh); assert_eq!( app.data.radarr_data.prompt_confirm_action, @@ -1852,7 +1861,7 @@ mod tests { .build_edit_indexer_params(); assert_eq!(edit_indexer_params, expected_edit_indexer_params); - assert!(app.data.radarr_data.edit_indexer_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_indexer_modal); } #[test] diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs index 4e1eca5..f933187 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -1,6 +1,6 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::models::radarr_models::IndexerSettings; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, @@ -288,4 +288,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs index 25fe87a..b9a219e 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler_tests.rs @@ -4,12 +4,14 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer_settings; - use crate::handlers::KeyEventHandler; use crate::models::radarr_models::IndexerSettings; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, @@ -19,9 +21,9 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; + use crate::models::BlockSelectionState; use crate::models::radarr_models::IndexerSettings; use crate::models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use super::*; @@ -267,9 +269,9 @@ mod tests { mod test_handle_left_right_action { use std::sync::atomic::Ordering; + use crate::models::BlockSelectionState; use crate::models::radarr_models::IndexerSettings; use crate::models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use pretty_assertions::assert_eq; use rstest::rstest; @@ -424,9 +426,10 @@ mod tests { use rstest::rstest; use crate::{ + assert_navigation_popped, models::{ - radarr_models::IndexerSettings, - servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, radarr_models::IndexerSettings, + servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, }, network::radarr_network::RadarrEvent, }; @@ -457,10 +460,10 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.should_refresh); - assert_eq!(app.data.radarr_data.indexer_settings, None); + assert_none!(app.data.radarr_data.indexer_settings); } #[test] @@ -486,12 +489,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::EditAllIndexerSettings(indexer_settings())) ); - assert!(app.data.radarr_data.indexer_settings.is_none()); + assert_modal_absent!(app.data.radarr_data.indexer_settings); assert!(app.should_refresh); } @@ -549,7 +552,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), selected_block.into()); + assert_navigation_pushed!(app, selected_block.into()); } #[rstest] @@ -599,8 +602,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into() ); assert!(app.ignore_special_keys_for_textbox_input); @@ -736,19 +739,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .indexer_settings - .as_ref() - .unwrap() - .whitelisted_hardcoded_subs - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AllIndexerSettingsPrompt.into() + assert!( + !app + .data + .radarr_data + .indexer_settings + .as_ref() + .unwrap() + .whitelisted_hardcoded_subs + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::AllIndexerSettingsPrompt.into()); } #[rstest] @@ -769,20 +771,17 @@ mod tests { IndexerSettingsHandler::new(SUBMIT_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AllIndexerSettingsPrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::AllIndexerSettingsPrompt.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use crate::models::radarr_models::IndexerSettings; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -802,9 +801,9 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.indexer_settings, None); + assert_none!(app.data.radarr_data.indexer_settings); } #[test] @@ -825,11 +824,11 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.data.radarr_data.indexer_settings, - Some(IndexerSettings::default()) + assert_some_eq_x!( + &app.data.radarr_data.indexer_settings, + &IndexerSettings::default() ); } @@ -852,21 +851,22 @@ mod tests { IndexerSettingsHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert_eq!( - app.data.radarr_data.indexer_settings, - Some(IndexerSettings::default()) + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_some_eq_x!( + &app.data.radarr_data.indexer_settings, + &IndexerSettings::default() ); } } mod test_handle_key_char { - use pretty_assertions::{assert_eq, assert_str_eq}; + use pretty_assertions::assert_str_eq; use crate::{ + assert_navigation_popped, models::{ - radarr_models::IndexerSettings, - servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, radarr_models::IndexerSettings, + servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, }, network::radarr_network::RadarrEvent, }; @@ -950,12 +950,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::EditAllIndexerSettings(indexer_settings())) + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::EditAllIndexerSettings(indexer_settings()) ); - assert!(app.data.radarr_data.indexer_settings.is_none()); + assert_modal_absent!(app.data.radarr_data.indexer_settings); assert!(app.should_refresh); } } @@ -1004,7 +1004,7 @@ mod tests { .build_edit_indexer_settings_body(); assert_eq!(body, indexer_settings()); - assert!(app.data.radarr_data.indexer_settings.is_none()); + assert_modal_absent!(app.data.radarr_data.indexer_settings); } #[test] diff --git a/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs b/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs index e4a26c4..e25c24c 100644 --- a/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/indexers_handler_tests.rs @@ -4,14 +4,15 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::indexers::IndexersHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, EDIT_INDEXER_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, + ActiveRadarrBlock, EDIT_INDEXER_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXERS_BLOCKS, }; use crate::models::servarr_models::Indexer; use crate::test_handler_delegation; @@ -34,10 +35,7 @@ mod tests { IndexersHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::DeleteIndexerPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::DeleteIndexerPrompt.into()); } #[test] @@ -81,10 +79,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::RootFolders.into() ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::RootFolders.into()); } #[rstest] @@ -105,7 +100,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::System.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::System.into()); } #[rstest] @@ -125,10 +120,12 @@ mod tests { } mod test_handle_submit { + use super::*; + use crate::assert_navigation_popped; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ - RadarrData, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, + EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, RadarrData, }; use crate::models::servarr_models::{Indexer, IndexerField}; use crate::network::radarr_network::RadarrEvent; @@ -136,8 +133,6 @@ mod tests { use pretty_assertions::assert_eq; use serde_json::{Number, Value}; - use super::*; - const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; #[rstest] @@ -196,17 +191,14 @@ mod tests { IndexersHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditIndexerPrompt.into() + assert_navigation_pushed!(app, ActiveRadarrBlock::EditIndexerPrompt.into()); + assert_some_eq_x!( + &app.data.radarr_data.edit_indexer_modal, + &EditIndexerModal::from(&app.data.radarr_data) ); - assert_eq!( - app.data.radarr_data.edit_indexer_modal, - Some((&app.data.radarr_data).into()) - ); - assert_eq!( - app.data.radarr_data.edit_indexer_modal, - Some(expected_edit_indexer_modal) + assert_some_eq_x!( + &app.data.radarr_data.edit_indexer_modal, + &expected_edit_indexer_modal ); if torrent_protocol { assert_eq!( @@ -235,7 +227,7 @@ mod tests { IndexersHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert_eq!(app.data.radarr_data.edit_indexer_modal, None); + assert_none!(app.data.radarr_data.edit_indexer_modal); } #[test] @@ -255,11 +247,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::DeleteIndexer(1)) + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::DeleteIndexer(1) ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); } #[test] @@ -282,15 +274,14 @@ mod tests { .handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; - use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -310,7 +301,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert!(!app.data.radarr_data.prompt_confirm); } @@ -324,8 +315,8 @@ mod tests { IndexersHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::TestIndexer, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert_eq!(app.data.radarr_data.indexer_test_errors, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_none!(app.data.radarr_data.indexer_test_errors); } #[rstest] @@ -338,8 +329,8 @@ mod tests { IndexersHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); + assert_is_empty!(app.error.text); } } @@ -349,6 +340,7 @@ mod tests { use super::*; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer; use crate::{ + assert_navigation_popped, models::servarr_data::radarr::radarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, network::radarr_network::RadarrEvent, }; @@ -371,7 +363,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Indexers.into()); assert!(app.should_refresh); } @@ -415,10 +407,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AllIndexerSettingsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::AllIndexerSettingsPrompt.into()); assert_eq!( app.data.radarr_data.selected_block.blocks, INDEXER_SETTINGS_SELECTION_BLOCKS @@ -464,10 +453,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::TestIndexer.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::TestIndexer.into()); } #[test] @@ -509,10 +495,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::TestAllIndexers.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::TestAllIndexers.into()); } #[test] @@ -553,11 +536,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::DeleteIndexer(1)) + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::DeleteIndexer(1) ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); } } diff --git a/src/handlers/radarr_handlers/indexers/mod.rs b/src/handlers/radarr_handlers/indexers/mod.rs index 5770c2a..85f5adc 100644 --- a/src/handlers/radarr_handlers/indexers/mod.rs +++ b/src/handlers/radarr_handlers/indexers/mod.rs @@ -4,16 +4,15 @@ use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler; use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler; use crate::handlers::radarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; +use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, - INDEXERS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, + INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, }; -use crate::models::servarr_models::Indexer; -use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; -use crate::{handle_table_events, matches_key}; mod edit_indexer_handler; mod edit_indexer_settings_handler; @@ -31,8 +30,6 @@ pub(super) struct IndexersHandler<'a, 'b> { } impl IndexersHandler<'_, '_> { - handle_table_events!(self, indexers, self.app.data.radarr_data.indexers, Indexer); - fn extract_indexer_id(&self) -> i64 { self.app.data.radarr_data.indexers.current_selection().id } @@ -43,7 +40,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a, let indexer_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Indexers.into()); - if !self.handle_indexers_table_events(indexer_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.indexers, + indexer_table_handling_config, + ) { match self.active_radarr_block { _ if EditIndexerHandler::accepts(self.active_radarr_block) => { EditIndexerHandler::new(self.key, self.app, self.active_radarr_block, self.context) @@ -206,4 +207,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/indexers/test_all_indexers_handler.rs b/src/handlers/radarr_handlers/indexers/test_all_indexers_handler.rs index 896bd72..c8e26d4 100644 --- a/src/handlers/radarr_handlers/indexers/test_all_indexers_handler.rs +++ b/src/handlers/radarr_handlers/indexers/test_all_indexers_handler.rs @@ -1,9 +1,7 @@ use crate::app::App; use crate::event::Key; -use crate::handle_table_events; -use crate::handlers::table_handler::TableHandlingConfig; use crate::handlers::KeyEventHandler; -use crate::models::servarr_data::modals::IndexerTestResultModalItem; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; #[cfg(test)] @@ -17,27 +15,23 @@ pub(super) struct TestAllIndexersHandler<'a, 'b> { _context: Option, } -impl TestAllIndexersHandler<'_, '_> { - handle_table_events!( - self, - indexer_test_all_results, - self - .app - .data - .radarr_data - .indexer_test_all_results - .as_mut() - .unwrap(), - IndexerTestResultModalItem - ); -} +impl TestAllIndexersHandler<'_, '_> {} impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for TestAllIndexersHandler<'a, 'b> { fn handle(&mut self) { let test_all_indexers_test_results_table_handler_config = TableHandlingConfig::new(ActiveRadarrBlock::TestAllIndexers.into()); - if !self.handle_indexer_test_all_results_table_events( + if !handle_table( + self, + |app| { + app + .data + .radarr_data + .indexer_test_all_results + .as_mut() + .unwrap() + }, test_all_indexers_test_results_table_handler_config, ) { self.handle_key_event(); @@ -102,4 +96,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for TestAllIndexersHandl } fn handle_char_key_event(&mut self) {} + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/indexers/test_all_indexers_handler_tests.rs b/src/handlers/radarr_handlers/indexers/test_all_indexers_handler_tests.rs index 7bfc93c..367d816 100644 --- a/src/handlers/radarr_handlers/indexers/test_all_indexers_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/test_all_indexers_handler_tests.rs @@ -1,9 +1,9 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; - use crate::handlers::radarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler; use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::stateful_table::StatefulTable; @@ -13,7 +13,7 @@ mod tests { mod test_handle_esc { use super::*; use crate::models::stateful_table::StatefulTable; - use pretty_assertions::assert_eq; + use crate::{assert_modal_absent, assert_navigation_popped}; use rstest::rstest; #[rstest] @@ -32,9 +32,9 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Indexers.into()); assert!(!app.data.radarr_data.prompt_confirm); - assert!(app.data.radarr_data.indexer_test_all_results.is_none()); + assert_modal_absent!(app.data.radarr_data.indexer_test_all_results); } } diff --git a/src/handlers/radarr_handlers/library/add_movie_handler.rs b/src/handlers/radarr_handlers/library/add_movie_handler.rs index 3480bdb..e668304 100644 --- a/src/handlers/radarr_handlers/library/add_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/add_movie_handler.rs @@ -1,18 +1,15 @@ -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::models::radarr_models::{ AddMovieBody, AddMovieOptions, AddMovieSearchResult, CollectionMovie, }; use crate::models::servarr_data::radarr::modals::AddMovieModal; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, + ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, ActiveRadarrBlock, }; -use crate::models::stateful_table::StatefulTable; use crate::models::{BlockSelectionState, Scrollable}; use crate::network::radarr_network::RadarrEvent; -use crate::{ - handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, App, Key, -}; +use crate::{App, Key, handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; #[cfg(test)] #[path = "add_movie_handler_tests.rs"] @@ -26,19 +23,6 @@ pub(super) struct AddMovieHandler<'a, 'b> { } impl AddMovieHandler<'_, '_> { - handle_table_events!( - self, - add_movie_search_results, - self - .app - .data - .radarr_data - .add_searched_movies - .as_mut() - .unwrap_or(&mut StatefulTable::default()), - AddMovieSearchResult - ); - fn build_add_movie_body(&mut self) -> AddMovieBody { let add_movie_modal = self .app @@ -124,7 +108,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, let add_movie_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::AddMovieSearchResults.into()); - if !self.handle_add_movie_search_results_table_events(add_movie_table_handling_config) { + if !handle_table( + self, + |app| { + app + .data + .radarr_data + .add_searched_movies + .as_mut() + .expect("add_searched_movies should be initialized") + }, + add_movie_table_handling_config, + ) { self.handle_key_event(); } } @@ -558,4 +553,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs b/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs index 4449905..b61d7ec 100644 --- a/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/add_movie_handler_tests.rs @@ -1,23 +1,26 @@ #[cfg(test)] mod tests { + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::add_movie_search_result; use crate::models::stateful_table::StatefulTable; use pretty_assertions::assert_str_eq; use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::library::add_movie_handler::AddMovieHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::add_movie_body; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::collection_movie; - use crate::handlers::KeyEventHandler; + use crate::models::HorizontallyScrollableText; use crate::models::radarr_models::{AddMovieSearchResult, MinimumAvailability, MovieMonitor}; use crate::models::servarr_data::radarr::modals::AddMovieModal; - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; + use crate::models::servarr_data::radarr::radarr_data::{ADD_MOVIE_BLOCKS, ActiveRadarrBlock}; use crate::models::servarr_models::RootFolder; - use crate::models::HorizontallyScrollableText; use bimap::BiMap; mod test_handle_scroll_up_and_down { @@ -25,9 +28,9 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; + use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::modals::AddMovieModal; use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use crate::simple_stateful_iterable_vec; use super::*; @@ -761,19 +764,19 @@ mod tests { } mod test_handle_submit { - use bimap::BiMap; - use pretty_assertions::{assert_eq, assert_str_eq}; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::{ add_movie_body, add_movie_search_result, collection_movie, }; + use crate::models::BlockSelectionState; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::modals::AddMovieModal; use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; use crate::models::stateful_table::StatefulTable; - use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; + use bimap::BiMap; + use pretty_assertions::{assert_eq, assert_str_eq}; + use rstest::rstest; use super::*; @@ -847,34 +850,40 @@ mod tests { app.data.radarr_data.selected_block.get_active_block(), ActiveRadarrBlock::AddMovieSelectRootFolder ); - assert!(app.data.radarr_data.add_movie_modal.is_some()); - assert!(!app - .data - .radarr_data - .add_movie_modal - .as_ref() - .unwrap() - .monitor_list - .items - .is_empty()); - assert!(!app - .data - .radarr_data - .add_movie_modal - .as_ref() - .unwrap() - .minimum_availability_list - .items - .is_empty()); - assert!(!app - .data - .radarr_data - .add_movie_modal - .as_ref() - .unwrap() - .quality_profile_list - .items - .is_empty()); + assert_modal_present!(app.data.radarr_data.add_movie_modal); + assert!( + !app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .monitor_list + .items + .is_empty() + ); + assert!( + !app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .minimum_availability_list + .items + .is_empty() + ); + assert!( + !app + .data + .radarr_data + .add_movie_modal + .as_ref() + .unwrap() + .quality_profile_list + .items + .is_empty() + ); assert_str_eq!( app .data @@ -908,7 +917,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::AddMovieSearchResults.into() ); - assert!(app.data.radarr_data.add_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.add_movie_modal); } #[test] @@ -975,8 +984,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); } #[rstest] @@ -1049,12 +1058,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::AddMovie(add_movie_body())) + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::AddMovie(add_movie_body()) ); - assert!(app.data.radarr_data.add_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.add_movie_modal); } #[rstest] @@ -1086,11 +1095,11 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, (selected_block, Some(ActiveRadarrBlock::CollectionDetails)).into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); if selected_block == ActiveRadarrBlock::AddMovieTagsInput { assert!(app.ignore_special_keys_for_textbox_input); @@ -1120,10 +1129,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMoviePrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::AddMoviePrompt.into()); if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput { assert!(!app.ignore_special_keys_for_textbox_input); @@ -1132,13 +1138,12 @@ mod tests { } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use crate::models::servarr_data::radarr::modals::AddMovieModal; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::stateful_table::StatefulTable; - use crate::simple_stateful_iterable_vec; + use crate::{assert_navigation_popped, simple_stateful_iterable_vec}; use super::*; @@ -1161,8 +1166,8 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert_eq!(app.data.radarr_data.add_movie_search, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_none!(app.data.radarr_data.add_movie_search); } #[test] @@ -1182,10 +1187,7 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMoviePrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::AddMoviePrompt.into()); } #[rstest] @@ -1208,11 +1210,8 @@ mod tests { AddMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMovieSearchInput.into() - ); - assert!(app.data.radarr_data.add_searched_movies.is_none()); + assert_navigation_popped!(app, ActiveRadarrBlock::AddMovieSearchInput.into()); + assert_modal_absent!(app.data.radarr_data.add_searched_movies); assert!(app.ignore_special_keys_for_textbox_input); } @@ -1231,10 +1230,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMovieSearchResults.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::AddMovieSearchResults.into()); } #[test] @@ -1248,11 +1244,8 @@ mod tests { AddMovieHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMovieSearchResults.into() - ); - assert!(app.data.radarr_data.add_movie_modal.is_none()); + assert_navigation_popped!(app, ActiveRadarrBlock::AddMovieSearchResults.into()); + assert_modal_absent!(app.data.radarr_data.add_movie_modal); } #[test] @@ -1272,10 +1265,7 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMoviePrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::AddMoviePrompt.into()); } #[rstest] @@ -1312,8 +1302,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_popped!( + app, ( ActiveRadarrBlock::AddMoviePrompt, Some(ActiveRadarrBlock::CollectionDetails), @@ -1325,18 +1315,18 @@ mod tests { mod test_handle_key_char { use bimap::BiMap; - use pretty_assertions::assert_eq; use rstest::rstest; use super::*; use crate::{ + assert_navigation_popped, handlers::radarr_handlers::radarr_handler_test_utils::utils::{ add_movie_body, add_movie_search_result, collection_movie, }, models::{ + BlockSelectionState, servarr_data::radarr::{modals::AddMovieModal, radarr_data::ADD_MOVIE_SELECTION_BLOCKS}, stateful_table::StatefulTable, - BlockSelectionState, }, network::radarr_network::RadarrEvent, }; @@ -1503,12 +1493,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::AddMovie(add_movie_body())) + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::AddMovie(add_movie_body()) ); - assert!(app.data.radarr_data.add_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.add_movie_modal); } } diff --git a/src/handlers/radarr_handlers/library/delete_movie_handler.rs b/src/handlers/radarr_handlers/library/delete_movie_handler.rs index b10ac3c..561489f 100644 --- a/src/handlers/radarr_handlers/library/delete_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/delete_movie_handler.rs @@ -1,6 +1,6 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; use crate::models::radarr_models::DeleteMovieParams; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; @@ -136,4 +136,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<' self.app.pop_navigation_stack(); } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs b/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs index 17b9338..ca73c5a 100644 --- a/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/delete_movie_handler_tests.rs @@ -4,12 +4,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::library::delete_movie_handler::DeleteMovieHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie; - use crate::handlers::KeyEventHandler; use crate::models::radarr_models::DeleteMovieParams; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; @@ -17,8 +17,8 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use super::*; @@ -83,11 +83,12 @@ mod tests { mod test_handle_submit { use pretty_assertions::assert_eq; - use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS; use crate::network::radarr_network::RadarrEvent; use super::*; + use crate::assert_navigation_popped; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -113,8 +114,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.data.radarr_data.prompt_confirm); assert!(!app.data.radarr_data.delete_movie_files); assert!(!app.data.radarr_data.add_list_exclusion); @@ -149,7 +150,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::DeleteMovie(expected_delete_movie_params)) @@ -182,7 +183,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::DeleteMoviePrompt.into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.should_refresh); assert!(app.data.radarr_data.prompt_confirm); assert!(app.data.radarr_data.delete_movie_files); @@ -222,7 +223,7 @@ mod tests { mod test_handle_esc { use super::*; - use pretty_assertions::assert_eq; + use crate::assert_navigation_popped; use rstest::rstest; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -245,7 +246,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert!(!app.data.radarr_data.prompt_confirm); assert!(!app.data.radarr_data.delete_movie_files); assert!(!app.data.radarr_data.add_list_exclusion); @@ -254,8 +255,9 @@ mod tests { mod test_handle_key_char { use crate::{ + assert_navigation_popped, models::{ - servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, servarr_data::radarr::radarr_data::DELETE_MOVIE_SELECTION_BLOCKS, }, network::radarr_network::RadarrEvent, }; @@ -291,7 +293,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::DeleteMovie(expected_delete_movie_params)) diff --git a/src/handlers/radarr_handlers/library/edit_movie_handler.rs b/src/handlers/radarr_handlers/library/edit_movie_handler.rs index 10c3f14..f463d0f 100644 --- a/src/handlers/radarr_handlers/library/edit_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/edit_movie_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Scrollable; use crate::models::radarr_models::EditMovieParams; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; -use crate::models::Scrollable; use crate::network::radarr_network::RadarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; @@ -392,4 +392,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs b/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs index 9853ee3..03bfc52 100644 --- a/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/edit_movie_handler_tests.rs @@ -5,12 +5,14 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::library::edit_movie_handler::EditMovieHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie; - use crate::handlers::KeyEventHandler; use crate::models::radarr_models::{EditMovieParams, MinimumAvailability, Movie}; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; @@ -20,9 +22,9 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; + use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::EDIT_MOVIE_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use super::*; @@ -534,13 +536,13 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::EDIT_MOVIE_SELECTION_BLOCKS; use crate::models::{BlockSelectionState, Route}; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; + use rstest::rstest; use super::*; @@ -566,19 +568,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_movie_modal - .as_ref() - .unwrap() - .path - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditMoviePrompt.into() + assert!( + !app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .unwrap() + .path + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditMoviePrompt.into()); } #[test] @@ -601,19 +602,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .radarr_data - .edit_movie_modal - .as_mut() - .unwrap() - .tags - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditMoviePrompt.into() + assert!( + !app + .data + .radarr_data + .edit_movie_modal + .as_mut() + .unwrap() + .tags + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditMoviePrompt.into()); } #[test] @@ -637,8 +637,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); } #[test] @@ -690,12 +690,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::EditMovie(expected_edit_movie_params)) ); - assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_movie_modal); assert!(app.should_refresh); } @@ -720,7 +720,7 @@ mod tests { app.get_current_route(), ActiveRadarrBlock::EditMoviePrompt.into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.should_refresh); } @@ -744,7 +744,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .radarr_data @@ -752,7 +752,7 @@ mod tests { .as_ref() .unwrap() .monitored, - Some(true) + true ); EditMovieHandler::new( @@ -764,7 +764,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .radarr_data @@ -772,7 +772,7 @@ mod tests { .as_ref() .unwrap() .monitored, - Some(false) + false ); } @@ -805,11 +805,11 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, (selected_block, Some(ActiveRadarrBlock::Movies)).into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); if selected_block == ActiveRadarrBlock::EditMoviePathInput || selected_block == ActiveRadarrBlock::EditMovieTagsInput @@ -851,7 +851,7 @@ mod tests { ) .into() ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_none!(app.data.radarr_data.prompt_confirm_action); assert!(!app.ignore_special_keys_for_textbox_input); } @@ -878,10 +878,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditMoviePrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditMoviePrompt.into()); if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput || active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput @@ -892,11 +889,10 @@ mod tests { } mod test_handle_esc { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use rstest::rstest; use super::*; @@ -919,10 +915,7 @@ mod tests { EditMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::EditMoviePrompt.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::EditMoviePrompt.into()); } #[test] @@ -934,9 +927,9 @@ mod tests { EditMovieHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); - assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_movie_modal); assert!(!app.data.radarr_data.prompt_confirm); } @@ -956,16 +949,17 @@ mod tests { EditMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } } mod test_handle_key_char { use super::*; use crate::{ + assert_navigation_popped, models::{ - servarr_data::radarr::{modals::EditMovieModal, radarr_data::EDIT_MOVIE_SELECTION_BLOCKS}, BlockSelectionState, + servarr_data::radarr::{modals::EditMovieModal, radarr_data::EDIT_MOVIE_SELECTION_BLOCKS}, }, network::radarr_network::RadarrEvent, }; @@ -1128,12 +1122,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert_eq!( app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::EditMovie(expected_edit_movie_params)) ); - assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_movie_modal); assert!(app.should_refresh); } } @@ -1209,7 +1203,7 @@ mod tests { .build_edit_movie_params(); assert_eq!(edit_movie_params, expected_edit_movie_params); - assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_movie_modal); } #[test] diff --git a/src/handlers/radarr_handlers/library/library_handler_tests.rs b/src/handlers/radarr_handlers/library/library_handler_tests.rs index f6bb55d..5ac7b9a 100644 --- a/src/handlers/radarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/library_handler_tests.rs @@ -5,15 +5,18 @@ mod tests { use std::cmp::Ordering; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::radarr_handlers::library::{movies_sorting_options, LibraryHandler}; - use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::library::{LibraryHandler, movies_sorting_options}; + use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::movie; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, ADD_MOVIE_BLOCKS, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS, + ADD_MOVIE_BLOCKS, ActiveRadarrBlock, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, }; use crate::models::servarr_models::Language; @@ -72,6 +75,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_movie_tab_left(#[values(true, false)] is_ready: bool) { @@ -91,7 +95,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::System.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::System.into()); } #[rstest] @@ -112,10 +116,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Collections.into() ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::Collections.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::Collections.into()); } #[rstest] @@ -147,9 +148,9 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; use super::*; @@ -166,10 +167,7 @@ mod tests { LibraryHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::MovieDetails.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::MovieDetails.into()); } #[test] @@ -209,11 +207,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::UpdateAllMovies) + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::UpdateAllMovies ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } #[test] @@ -236,19 +234,19 @@ mod tests { .handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use ratatui::widgets::TableState; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::stateful_table::StatefulTable; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -267,7 +265,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert!(!app.data.radarr_data.prompt_confirm); } @@ -289,8 +287,8 @@ mod tests { LibraryHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + assert_is_empty!(app.error.text); } } @@ -303,11 +301,11 @@ mod tests { use crate::models::radarr_models::MinimumAvailability; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::servarr_data::radarr::radarr_data::{ - RadarrData, EDIT_MOVIE_SELECTION_BLOCKS, + EDIT_MOVIE_SELECTION_BLOCKS, RadarrData, }; use crate::network::radarr_network::RadarrEvent; - use crate::test_edit_movie_key; + use crate::{assert_navigation_popped, test_edit_movie_key}; use super::*; @@ -328,12 +326,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddMovieSearchInput.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::AddMovieSearchInput.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.add_movie_search.is_some()); + assert_modal_present!(app.data.radarr_data.add_movie_search); } #[test] @@ -357,7 +352,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.add_movie_search.is_none()); + assert_modal_absent!(app.data.radarr_data.add_movie_search); } #[test] @@ -389,7 +384,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_movie_modal); } #[test] @@ -410,9 +405,9 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(app.data.radarr_data.prompt_confirm); assert!(app.is_routing); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::ToggleMovieMonitoring(0)) + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::ToggleMovieMonitoring(0) ); } @@ -433,7 +428,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(!app.data.radarr_data.prompt_confirm); - assert!(app.data.radarr_data.prompt_confirm_action.is_none()); + assert_modal_absent!(app.data.radarr_data.prompt_confirm_action); assert!(!app.is_routing); } @@ -454,10 +449,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::UpdateAllMoviesPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::UpdateAllMoviesPrompt.into()); } #[test] @@ -500,7 +492,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Movies.into()); assert!(app.should_refresh); } @@ -547,11 +539,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::UpdateAllMovies) + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::UpdateAllMovies ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } } diff --git a/src/handlers/radarr_handlers/library/mod.rs b/src/handlers/radarr_handlers/library/mod.rs index 3c24f90..7c441ee 100644 --- a/src/handlers/radarr_handlers/library/mod.rs +++ b/src/handlers/radarr_handlers/library/mod.rs @@ -5,17 +5,17 @@ use crate::handlers::radarr_handlers::library::add_movie_handler::AddMovieHandle use crate::handlers::radarr_handlers::library::delete_movie_handler::DeleteMovieHandler; use crate::handlers::radarr_handlers::library::edit_movie_handler::EditMovieHandler; use crate::handlers::radarr_handlers::library::movie_details_handler::MovieDetailsHandler; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; -use crate::handlers::table_handler::TableHandlingConfig; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::matches_key; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, DELETE_MOVIE_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, LIBRARY_BLOCKS, }; use crate::models::stateful_table::SortOption; -use crate::models::{BlockSelectionState, HorizontallyScrollableText}; +use crate::models::{BlockSelectionState, HorizontallyScrollableText, Route}; use crate::network::radarr_network::RadarrEvent; -use crate::{handle_table_events, matches_key}; mod add_movie_handler; mod delete_movie_handler; @@ -34,7 +34,6 @@ pub(super) struct LibraryHandler<'a, 'b> { } impl LibraryHandler<'_, '_> { - handle_table_events!(self, movies, self.app.data.radarr_data.movies, Movie); fn extract_movie_id(&self) -> i64 { self.app.data.radarr_data.movies.current_selection().id } @@ -44,7 +43,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, ' fn handle(&mut self) { let movie_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Movies.into()) .sorting_block(ActiveRadarrBlock::MoviesSortPrompt.into()) - .sort_by_fn(|a: &Movie, b: &Movie| a.id.cmp(&b.id)) .sort_options(movies_sorting_options()) .searching_block(ActiveRadarrBlock::SearchMovie.into()) .search_error_block(ActiveRadarrBlock::SearchMovieError.into()) @@ -53,7 +51,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, ' .filter_error_block(ActiveRadarrBlock::FilterMoviesError.into()) .filter_field_fn(|movie| &movie.title.text); - if !self.handle_movies_table_events(movie_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.movies, + movie_table_handling_config, + ) { match self.active_radarr_block { _ if AddMovieHandler::accepts(self.active_radarr_block) => { AddMovieHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle(); @@ -216,6 +218,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, ' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> Route { + self.app.get_current_route() + } } fn movies_sorting_options() -> Vec> { diff --git a/src/handlers/radarr_handlers/library/movie_details_handler.rs b/src/handlers/radarr_handlers/library/movie_details_handler.rs index ac08fa1..9877b79 100644 --- a/src/handlers/radarr_handlers/library/movie_details_handler.rs +++ b/src/handlers/radarr_handlers/library/movie_details_handler.rs @@ -2,11 +2,10 @@ use serde_json::Number; use crate::app::App; use crate::event::Key; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; -use crate::models::radarr_models::{ - Credit, MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody, -}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::matches_key; +use crate::models::radarr_models::{RadarrRelease, RadarrReleaseDownloadBody}; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, EDIT_MOVIE_SELECTION_BLOCKS, MOVIE_DETAILS_BLOCKS, }; @@ -14,7 +13,6 @@ use crate::models::servarr_models::Language; use crate::models::stateful_table::SortOption; use crate::models::{BlockSelectionState, Scrollable}; use crate::network::radarr_network::RadarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "movie_details_handler_tests.rs"] @@ -28,59 +26,6 @@ pub(super) struct MovieDetailsHandler<'a, 'b> { } impl MovieDetailsHandler<'_, '_> { - handle_table_events!( - self, - movie_releases, - self - .app - .data - .radarr_data - .movie_details_modal - .as_mut() - .unwrap() - .movie_releases, - RadarrRelease - ); - handle_table_events!( - self, - movie_history, - self - .app - .data - .radarr_data - .movie_details_modal - .as_mut() - .unwrap() - .movie_history, - MovieHistoryItem - ); - handle_table_events!( - self, - movie_cast, - self - .app - .data - .radarr_data - .movie_details_modal - .as_mut() - .unwrap() - .movie_cast, - Credit - ); - handle_table_events!( - self, - movie_crew, - self - .app - .data - .radarr_data - .movie_details_modal - .as_mut() - .unwrap() - .movie_crew, - Credit - ); - fn build_radarr_release_download_body(&self) -> RadarrReleaseDownloadBody { let movie_id = self.app.data.radarr_data.movies.current_selection().id; let (guid, indexer_id) = { @@ -122,11 +67,55 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler< let movie_cast_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Cast.into()); let movie_crew_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Crew.into()); - if !self.handle_movie_history_table_events(movie_history_table_handling_config) - && !self.handle_movie_releases_table_events(movie_releases_table_handling_config) - && !self.handle_movie_cast_table_events(movie_cast_table_handling_config) - && !self.handle_movie_crew_table_events(movie_crew_table_handling_config) - { + if !handle_table( + self, + |app| { + &mut app + .data + .radarr_data + .movie_details_modal + .as_mut() + .unwrap() + .movie_history + }, + movie_history_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .radarr_data + .movie_details_modal + .as_mut() + .unwrap() + .movie_releases + }, + movie_releases_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .radarr_data + .movie_details_modal + .as_mut() + .unwrap() + .movie_cast + }, + movie_cast_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .radarr_data + .movie_details_modal + .as_mut() + .unwrap() + .movie_crew + }, + movie_crew_table_handling_config, + ) { self.handle_key_event(); } } @@ -158,27 +147,23 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler< } fn is_ready(&self) -> bool { - if let Some(movie_details_modal) = &self.app.data.radarr_data.movie_details_modal { - match self.active_radarr_block { - ActiveRadarrBlock::MovieDetails => { - !self.app.is_loading && !movie_details_modal.movie_details.is_empty() - } - ActiveRadarrBlock::MovieHistory => { - !self.app.is_loading && !movie_details_modal.movie_history.is_empty() - } - ActiveRadarrBlock::Cast => { - !self.app.is_loading && !movie_details_modal.movie_cast.is_empty() - } - ActiveRadarrBlock::Crew => { - !self.app.is_loading && !movie_details_modal.movie_crew.is_empty() - } - ActiveRadarrBlock::ManualSearch => { - !self.app.is_loading && !movie_details_modal.movie_releases.is_empty() - } - _ => !self.app.is_loading, + let Some(movie_details_modal) = &self.app.data.radarr_data.movie_details_modal else { + return false; + }; + + match self.active_radarr_block { + ActiveRadarrBlock::MovieDetails => { + !self.app.is_loading && !movie_details_modal.movie_details.is_empty() } - } else { - false + ActiveRadarrBlock::MovieHistory => { + !self.app.is_loading && !movie_details_modal.movie_history.is_empty() + } + ActiveRadarrBlock::Cast => !self.app.is_loading && !movie_details_modal.movie_cast.is_empty(), + ActiveRadarrBlock::Crew => !self.app.is_loading && !movie_details_modal.movie_crew.is_empty(), + ActiveRadarrBlock::ManualSearch => { + !self.app.is_loading && !movie_details_modal.movie_releases.is_empty() + } + _ => !self.app.is_loading, } } @@ -389,6 +374,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler< _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } fn releases_sorting_options() -> Vec> { diff --git a/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs b/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs index 2153748..a5d8077 100644 --- a/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs +++ b/src/handlers/radarr_handlers/library/movie_details_handler_tests.rs @@ -7,14 +7,16 @@ mod tests { use serde_json::Number; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::library::movie_details_handler::{ - releases_sorting_options, MovieDetailsHandler, + MovieDetailsHandler, releases_sorting_options, }; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::{movie, release}; - use crate::handlers::KeyEventHandler; use crate::models::radarr_models::{Credit, MovieHistoryItem}; use crate::models::radarr_models::{RadarrRelease, RadarrReleaseDownloadBody}; use crate::models::servarr_data::radarr::modals::MovieDetailsModal; @@ -294,7 +296,7 @@ mod tests { app.get_current_route(), app.data.radarr_data.movie_info_tabs.get_active_route() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); MovieDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle(); @@ -302,16 +304,16 @@ mod tests { app.get_current_route(), app.data.radarr_data.movie_info_tabs.get_active_route() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } } mod test_handle_submit { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::radarr::modals::MovieDetailsModal; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; + use rstest::rstest; use super::*; @@ -333,10 +335,7 @@ mod tests { MovieDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::ManualSearch, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::ManualSearchConfirmPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::ManualSearchConfirmPrompt.into()); } #[test] @@ -393,13 +392,10 @@ mod tests { MovieDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::MovieDetails.into() - ); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_popped!(app, ActiveRadarrBlock::MovieDetails.into()); + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &expected_action ); } @@ -423,11 +419,8 @@ mod tests { MovieDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::MovieDetails.into() - ); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveRadarrBlock::MovieDetails.into()); + assert_none!(app.data.radarr_data.prompt_confirm_action); } } @@ -435,8 +428,8 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::assert_movie_info_tabs_reset; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; + use crate::{assert_movie_info_tabs_reset, assert_navigation_popped}; use super::*; @@ -463,7 +456,7 @@ mod tests { MovieDetailsHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert_movie_info_tabs_reset!(app.data.radarr_data); } @@ -487,7 +480,7 @@ mod tests { MovieDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } } @@ -502,10 +495,10 @@ mod tests { use crate::models::servarr_data::radarr::modals::MovieDetailsModal; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::servarr_data::radarr::radarr_data::{ - RadarrData, EDIT_MOVIE_SELECTION_BLOCKS, + EDIT_MOVIE_SELECTION_BLOCKS, RadarrData, }; use crate::network::radarr_network::RadarrEvent; - use crate::test_edit_movie_key; + use crate::{assert_navigation_popped, test_edit_movie_key}; use super::*; @@ -544,8 +537,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into() ); } @@ -629,7 +622,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), active_radarr_block.into()); - assert!(app.data.radarr_data.edit_movie_modal.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_movie_modal); } #[rstest] @@ -667,10 +660,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::UpdateAndScanPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::UpdateAndScanPrompt.into()); } #[rstest] @@ -739,7 +729,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), active_radarr_block.into()); + assert_navigation_pushed!(app, active_radarr_block.into()); assert!(app.is_routing); } @@ -817,13 +807,10 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::MovieDetails.into() - ); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_popped!(app, ActiveRadarrBlock::MovieDetails.into()); + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &expected_action ); } } diff --git a/src/handlers/radarr_handlers/mod.rs b/src/handlers/radarr_handlers/mod.rs index e27237e..d8f8075 100644 --- a/src/handlers/radarr_handlers/mod.rs +++ b/src/handlers/radarr_handlers/mod.rs @@ -1,3 +1,4 @@ +use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::blocklist::BlocklistHandler; use crate::handlers::radarr_handlers::collections::CollectionsHandler; use crate::handlers::radarr_handlers::downloads::DownloadsHandler; @@ -5,9 +6,8 @@ use crate::handlers::radarr_handlers::indexers::IndexersHandler; use crate::handlers::radarr_handlers::library::LibraryHandler; use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler; use crate::handlers::radarr_handlers::system::SystemHandler; -use crate::handlers::KeyEventHandler; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; -use crate::{matches_key, App, Key}; +use crate::{App, Key, matches_key}; mod blocklist; mod collections; @@ -107,6 +107,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b fn handle_esc(&mut self) {} fn handle_char_key_event(&mut self) {} + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) { diff --git a/src/handlers/radarr_handlers/radarr_handler_test_utils.rs b/src/handlers/radarr_handlers/radarr_handler_test_utils.rs index afd8ff6..b97b31e 100644 --- a/src/handlers/radarr_handlers/radarr_handler_test_utils.rs +++ b/src/handlers/radarr_handlers/radarr_handler_test_utils.rs @@ -1,6 +1,7 @@ #[cfg(test)] #[macro_use] pub(in crate::handlers::radarr_handlers) mod utils { + use crate::models::HorizontallyScrollableText; use crate::models::radarr_models::{ AddMovieBody, AddMovieOptions, AddMovieSearchResult, Collection, CollectionMovie, DownloadRecord, IndexerSettings, MediaInfo, MinimumAvailability, Movie, MovieCollection, @@ -9,9 +10,8 @@ pub(in crate::handlers::radarr_handlers) mod utils { use crate::models::servarr_models::{ Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder, }; - use crate::models::HorizontallyScrollableText; use chrono::DateTime; - use serde_json::{json, Number}; + use serde_json::{Number, json}; #[macro_export] macro_rules! test_edit_movie_key { @@ -37,8 +37,8 @@ pub(in crate::handlers::radarr_handlers) mod utils { $handler::new(DEFAULT_KEYBINDINGS.edit.key, &mut app, $block, None).handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, (ActiveRadarrBlock::EditMoviePrompt, Some($context)).into() ); assert_eq!( @@ -151,8 +151,8 @@ pub(in crate::handlers::radarr_handlers) mod utils { $handler::new(DEFAULT_KEYBINDINGS.edit.key, &mut app, $block, None).handle(); - assert_eq!( - app.get_current_route(), + $crate::assert_navigation_pushed!( + app, (ActiveRadarrBlock::EditCollectionPrompt, $context).into() ); assert_eq!( diff --git a/src/handlers/radarr_handlers/radarr_handler_tests.rs b/src/handlers/radarr_handlers/radarr_handler_tests.rs index 9003ded..0a3bc46 100644 --- a/src/handlers/radarr_handlers/radarr_handler_tests.rs +++ b/src/handlers/radarr_handlers/radarr_handler_tests.rs @@ -4,10 +4,11 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; - use crate::handlers::radarr_handlers::{handle_change_tab_left_right_keys, RadarrHandler}; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::{RadarrHandler, handle_change_tab_left_right_keys}; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::test_handler_delegation; @@ -33,7 +34,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), left_block.into() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); app.data.radarr_data.main_tabs.set_index(index); @@ -43,7 +44,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), right_block.into() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } #[rstest] @@ -69,7 +70,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), left_block.into() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); app.data.radarr_data.main_tabs.set_index(index); @@ -79,7 +80,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), right_block.into() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } #[rstest] diff --git a/src/handlers/radarr_handlers/root_folders/mod.rs b/src/handlers/radarr_handlers/root_folders/mod.rs index 88c028b..aa2a64f 100644 --- a/src/handlers/radarr_handlers/root_folders/mod.rs +++ b/src/handlers/radarr_handlers/root_folders/mod.rs @@ -1,15 +1,13 @@ use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; -use crate::models::servarr_models::{AddRootFolderBody, RootFolder}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; use crate::models::HorizontallyScrollableText; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; +use crate::models::servarr_models::AddRootFolderBody; use crate::network::radarr_network::RadarrEvent; -use crate::{ - handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, -}; +use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; #[cfg(test)] #[path = "root_folders_handler_tests.rs"] @@ -23,13 +21,6 @@ pub(super) struct RootFoldersHandler<'a, 'b> { } impl RootFoldersHandler<'_, '_> { - handle_table_events!( - self, - root_folders, - self.app.data.radarr_data.root_folders, - RootFolder - ); - fn build_add_root_folder_body(&mut self) -> AddRootFolderBody { let edit_root_folder = self .app @@ -60,7 +51,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<' let root_folder_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::RootFolders.into()); - if !self.handle_root_folders_table_events(root_folder_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.radarr_data.root_folders, + root_folder_table_handling_config, + ) { self.handle_key_event(); } } @@ -231,4 +226,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs b/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs index 632550a..a032253 100644 --- a/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs +++ b/src/handlers/radarr_handlers/root_folders/root_folders_handler_tests.rs @@ -4,15 +4,18 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::root_folder; use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler; - use crate::handlers::KeyEventHandler; + use crate::models::HorizontallyScrollableText; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::servarr_models::{AddRootFolderBody, RootFolder}; - use crate::models::HorizontallyScrollableText; mod test_handle_home_end { use pretty_assertions::assert_eq; @@ -91,10 +94,7 @@ mod tests { RootFoldersHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::RootFolders, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::DeleteRootFolderPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::DeleteRootFolderPrompt.into()); } #[test] @@ -124,6 +124,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_root_folders_tab_left(#[values(true, false)] is_ready: bool) { @@ -143,7 +144,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Blocklist.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Blocklist.into()); } #[rstest] @@ -164,7 +165,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Indexers.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Indexers.into()); } #[rstest] @@ -242,9 +243,9 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; use super::*; @@ -281,10 +282,7 @@ mod tests { app.data.radarr_data.prompt_confirm_action, Some(RadarrEvent::AddRootFolder(expected_add_root_folder_body)) ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); } #[test] @@ -306,7 +304,7 @@ mod tests { assert!(!app.data.radarr_data.prompt_confirm); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.prompt_confirm_action.is_none()); + assert_modal_absent!(app.data.radarr_data.prompt_confirm_action); assert_eq!( app.get_current_route(), ActiveRadarrBlock::AddRootFolderPrompt.into() @@ -334,14 +332,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::DeleteRootFolder(1)) - ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::DeleteRootFolder(1) ); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); } #[test] @@ -364,17 +359,14 @@ mod tests { .handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); } } mod test_handle_esc { use super::*; - use pretty_assertions::assert_eq; + use crate::assert_navigation_popped; use rstest::rstest; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -394,10 +386,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); assert!(!app.data.radarr_data.prompt_confirm); } @@ -417,12 +406,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); - assert!(app.data.radarr_data.edit_root_folder.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_root_folder); assert!(!app.data.radarr_data.prompt_confirm); assert!(!app.ignore_special_keys_for_textbox_input); } @@ -437,18 +423,15 @@ mod tests { RootFoldersHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::RootFolders, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); + assert_is_empty!(app.error.text); } } mod test_handle_key_char { - use pretty_assertions::{assert_eq, assert_str_eq}; - + use crate::assert_navigation_popped; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::{assert_eq, assert_str_eq}; use super::*; @@ -469,12 +452,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::AddRootFolderPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::AddRootFolderPrompt.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.edit_root_folder.is_some()); + assert_modal_present!(app.data.radarr_data.edit_root_folder); } #[test] @@ -501,7 +481,7 @@ mod tests { ActiveRadarrBlock::RootFolders.into() ); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.edit_root_folder.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_root_folder); } #[test] @@ -522,10 +502,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::RootFolders.into()); assert!(app.should_refresh); } @@ -623,14 +600,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::DeleteRootFolder(1)) - ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::RootFolders.into() + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::DeleteRootFolder(1) ); + assert_navigation_popped!(app, ActiveRadarrBlock::RootFolders.into()); } } @@ -681,7 +655,7 @@ mod tests { .build_add_root_folder_body(); assert_eq!(actual_add_root_folder_body, expected_add_root_folder_body); - assert!(app.data.radarr_data.edit_root_folder.is_none()); + assert_modal_absent!(app.data.radarr_data.edit_root_folder); } #[test] diff --git a/src/handlers/radarr_handlers/system/mod.rs b/src/handlers/radarr_handlers/system/mod.rs index 0a194b5..50201b0 100644 --- a/src/handlers/radarr_handlers/system/mod.rs +++ b/src/handlers/radarr_handlers/system/mod.rs @@ -2,10 +2,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler; -use crate::handlers::{handle_clear_errors, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_clear_errors}; use crate::matches_key; -use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::Scrollable; +use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; mod system_details_handler; @@ -124,4 +124,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemHandler<'a, 'b } } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/system/system_details_handler.rs b/src/handlers/radarr_handlers/system/system_details_handler.rs index 354fd08..7b13d4e 100644 --- a/src/handlers/radarr_handlers/system/system_details_handler.rs +++ b/src/handlers/radarr_handlers/system/system_details_handler.rs @@ -1,11 +1,11 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; +use crate::models::Scrollable; use crate::models::radarr_models::RadarrTaskName; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; use crate::models::stateful_list::StatefulList; -use crate::models::Scrollable; use crate::network::radarr_network::RadarrEvent; #[cfg(test)] @@ -196,4 +196,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler self.app.pop_navigation_stack(); } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/radarr_handlers/system/system_details_handler_tests.rs b/src/handlers/radarr_handlers/system/system_details_handler_tests.rs index bb9f098..a2eed58 100644 --- a/src/handlers/radarr_handlers/system/system_details_handler_tests.rs +++ b/src/handlers/radarr_handlers/system/system_details_handler_tests.rs @@ -4,11 +4,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::models::radarr_models::{RadarrTask, RadarrTaskName}; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, @@ -636,9 +637,9 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::network::radarr_network::RadarrEvent; + use pretty_assertions::assert_eq; use super::*; @@ -652,10 +653,7 @@ mod tests { SystemDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::SystemTasks, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemTaskStartConfirmPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SystemTaskStartConfirmPrompt.into()); } #[test] @@ -695,14 +693,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::StartTask(RadarrTaskName::default())) - ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemTasks.into() + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::StartTask(RadarrTaskName::default()) ); + assert_navigation_popped!(app, ActiveRadarrBlock::SystemTasks.into()); } #[test] @@ -721,20 +716,17 @@ mod tests { .handle(); assert!(!app.data.radarr_data.prompt_confirm); - assert_eq!(app.data.radarr_data.prompt_confirm_action, None); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemTasks.into() - ); + assert_none!(app.data.radarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveRadarrBlock::SystemTasks.into()); } } mod test_handle_esc { use crate::models::HorizontallyScrollableText; - use pretty_assertions::assert_eq; use rstest::rstest; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -757,8 +749,8 @@ mod tests { SystemDetailsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::SystemLogs, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); - assert!(app.data.radarr_data.log_details.items.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::System.into()); + assert_is_empty!(app.data.radarr_data.log_details.items); } #[rstest] @@ -775,7 +767,7 @@ mod tests { SystemDetailsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::SystemTasks, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::System.into()); } #[rstest] @@ -798,7 +790,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::System.into()); } #[rstest] @@ -810,7 +802,7 @@ mod tests { SystemDetailsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::SystemUpdates, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::System.into()); } #[test] @@ -828,10 +820,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemTasks.into() - ); + assert_navigation_popped!(app, ActiveRadarrBlock::SystemTasks.into()); assert!(!app.data.radarr_data.prompt_confirm); } } @@ -843,6 +832,7 @@ mod tests { use crate::network::radarr_network::RadarrEvent; use super::*; + use crate::{assert_navigation_popped, assert_navigation_pushed}; #[rstest] fn test_refresh_key( @@ -866,7 +856,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), active_radarr_block.into()); + assert_navigation_pushed!(app, active_radarr_block.into()); assert!(app.should_refresh); } @@ -917,14 +907,11 @@ mod tests { .handle(); assert!(app.data.radarr_data.prompt_confirm); - assert_eq!( - app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::StartTask(RadarrTaskName::default())) - ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemTasks.into() + assert_some_eq_x!( + &app.data.radarr_data.prompt_confirm_action, + &RadarrEvent::StartTask(RadarrTaskName::default()) ); + assert_navigation_popped!(app, ActiveRadarrBlock::SystemTasks.into()); } } diff --git a/src/handlers/radarr_handlers/system/system_handler_tests.rs b/src/handlers/radarr_handlers/system/system_handler_tests.rs index e59148d..cd4ab61 100644 --- a/src/handlers/radarr_handlers/system/system_handler_tests.rs +++ b/src/handlers/radarr_handlers/system/system_handler_tests.rs @@ -3,11 +3,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::radarr_handlers::system::SystemHandler; use crate::handlers::KeyEventHandler; + use crate::handlers::radarr_handlers::system::SystemHandler; use crate::models::radarr_models::RadarrTask; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, @@ -19,6 +20,7 @@ mod tests { use pretty_assertions::assert_eq; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_system_tab_left(#[values(true, false)] is_ready: bool) { @@ -38,7 +40,7 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Indexers.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Indexers.into()); } #[rstest] @@ -59,14 +61,14 @@ mod tests { app.data.radarr_data.main_tabs.get_active_route(), ActiveRadarrBlock::Movies.into() ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::Movies.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -80,8 +82,8 @@ mod tests { SystemHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::System, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveRadarrBlock::System.into()); + assert_is_empty!(app.error.text); } } @@ -118,10 +120,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemUpdates.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SystemUpdates.into()); } #[test] @@ -181,10 +180,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemQueuedEvents.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SystemQueuedEvents.into()); } #[test] @@ -245,7 +241,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); + assert_navigation_pushed!(app, ActiveRadarrBlock::System.into()); assert!(app.should_refresh); } @@ -308,10 +304,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemLogs.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SystemLogs.into()); assert_eq!( app.data.radarr_data.log_details.items, app.data.radarr_data.logs.items @@ -351,7 +344,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::System.into()); - assert!(app.data.radarr_data.log_details.is_empty()); + assert_is_empty!(app.data.radarr_data.log_details); } #[test] @@ -380,10 +373,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SystemTasks.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SystemTasks.into()); } #[test] diff --git a/src/handlers/sonarr_handlers/blocklist/blocklist_handler_tests.rs b/src/handlers/sonarr_handlers/blocklist/blocklist_handler_tests.rs index b7fbc1d..06c6ada 100644 --- a/src/handlers/sonarr_handlers/blocklist/blocklist_handler_tests.rs +++ b/src/handlers/sonarr_handlers/blocklist/blocklist_handler_tests.rs @@ -7,11 +7,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::sonarr_handlers::blocklist::{blocklist_sorting_options, BlocklistHandler}; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::blocklist::{BlocklistHandler, blocklist_sorting_options}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, BLOCKLIST_BLOCKS}; use crate::models::servarr_models::{Language, Quality, QualityWrapper}; use crate::models::sonarr_models::BlocklistItem; @@ -31,10 +32,7 @@ mod tests { BlocklistHandler::new(DELETE_KEY, &mut app, ActiveSonarrBlock::Blocklist, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::DeleteBlocklistItemPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::DeleteBlocklistItemPrompt.into()); } #[test] @@ -55,6 +53,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_blocklist_tab_left(#[values(true, false)] is_ready: bool) { @@ -75,7 +74,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Downloads.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Downloads.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Downloads.into()); } #[rstest] @@ -97,7 +96,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::History.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::History.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::History.into()); } #[rstest] @@ -123,11 +122,11 @@ mod tests { } mod test_handle_submit { + use crate::assert_navigation_popped; + use crate::network::sonarr_network::SonarrEvent; use pretty_assertions::assert_eq; use rstest::rstest; - use crate::network::sonarr_network::SonarrEvent; - use super::*; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -140,10 +139,7 @@ mod tests { BlocklistHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::Blocklist, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::BlocklistItemDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::BlocklistItemDetails.into()); } #[test] @@ -183,11 +179,11 @@ mod tests { BlocklistHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } #[rstest] @@ -206,16 +202,16 @@ mod tests { BlocklistHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Blocklist.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveSonarrBlock::Blocklist.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -239,7 +235,7 @@ mod tests { BlocklistHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); - assert_eq!(app.get_current_route(), base_block.into()); + assert_navigation_popped!(app, base_block.into()); assert!(!app.data.sonarr_data.prompt_confirm); } @@ -257,7 +253,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Blocklist.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Blocklist.into()); } #[rstest] @@ -270,8 +266,8 @@ mod tests { BlocklistHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::Blocklist, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Blocklist.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::Blocklist.into()); + assert_is_empty!(app.error.text); } } @@ -282,6 +278,7 @@ mod tests { use crate::network::sonarr_network::SonarrEvent; use super::*; + use crate::{assert_navigation_popped, assert_navigation_pushed}; #[test] fn test_refresh_blocklist_key() { @@ -297,7 +294,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Blocklist.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Blocklist.into()); assert!(app.should_refresh); } @@ -334,10 +331,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::BlocklistClearAllItemsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::BlocklistClearAllItemsPrompt.into()); } #[test] @@ -388,11 +382,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } } diff --git a/src/handlers/sonarr_handlers/blocklist/mod.rs b/src/handlers/sonarr_handlers/blocklist/mod.rs index 5c7862b..2989042 100644 --- a/src/handlers/sonarr_handlers/blocklist/mod.rs +++ b/src/handlers/sonarr_handlers/blocklist/mod.rs @@ -1,13 +1,13 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, BLOCKLIST_BLOCKS}; use crate::models::sonarr_models::BlocklistItem; use crate::models::stateful_table::SortOption; use crate::network::sonarr_network::SonarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "blocklist_handler_tests.rs"] @@ -21,13 +21,6 @@ pub(super) struct BlocklistHandler<'a, 'b> { } impl BlocklistHandler<'_, '_> { - handle_table_events!( - self, - blocklist, - self.app.data.sonarr_data.blocklist, - BlocklistItem - ); - fn extract_blocklist_item_id(&self) -> i64 { self.app.data.sonarr_data.blocklist.current_selection().id } @@ -38,10 +31,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a, let blocklist_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::Blocklist.into()) .sorting_block(ActiveSonarrBlock::BlocklistSortPrompt.into()) - .sort_by_fn(|a: &BlocklistItem, b: &BlocklistItem| a.id.cmp(&b.id)) .sort_options(blocklist_sorting_options()); - if !self.handle_blocklist_table_events(blocklist_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.blocklist, + blocklist_table_handling_config, + ) { self.handle_key_event(); } } @@ -177,6 +173,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } fn blocklist_sorting_options() -> Vec> { diff --git a/src/handlers/sonarr_handlers/downloads/downloads_handler_tests.rs b/src/handlers/sonarr_handlers/downloads/downloads_handler_tests.rs index 441a347..6792376 100644 --- a/src/handlers/sonarr_handlers/downloads/downloads_handler_tests.rs +++ b/src/handlers/sonarr_handlers/downloads/downloads_handler_tests.rs @@ -4,12 +4,13 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::downloads::DownloadsHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::download_record; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS}; use crate::models::sonarr_models::DownloadRecord; @@ -32,10 +33,7 @@ mod tests { DownloadsHandler::new(DELETE_KEY, &mut app, ActiveSonarrBlock::Downloads, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::DeleteDownloadPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::DeleteDownloadPrompt.into()); } #[test] @@ -60,6 +58,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_downloads_tab_left(#[values(true, false)] is_ready: bool) { @@ -80,7 +79,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Series.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Series.into()); } #[rstest] @@ -102,7 +101,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Blocklist.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Blocklist.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Blocklist.into()); } #[rstest] @@ -128,12 +127,12 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; use rstest::rstest; use crate::network::sonarr_network::SonarrEvent; use super::*; + use crate::assert_navigation_popped; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -166,11 +165,11 @@ mod tests { DownloadsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } #[rstest] @@ -192,16 +191,16 @@ mod tests { DownloadsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), base_route.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); + assert_navigation_popped!(app, base_route.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -219,7 +218,7 @@ mod tests { DownloadsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); - assert_eq!(app.get_current_route(), base_block.into()); + assert_navigation_popped!(app, base_block.into()); assert!(!app.data.sonarr_data.prompt_confirm); } @@ -233,17 +232,17 @@ mod tests { DownloadsHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::Downloads, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Downloads.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::Downloads.into()); + assert_is_empty!(app.error.text); } } mod test_handle_key_char { + use crate::assert_navigation_popped; + use crate::network::sonarr_network::SonarrEvent; use pretty_assertions::assert_eq; use rstest::rstest; - use crate::network::sonarr_network::SonarrEvent; - use super::*; #[test] @@ -264,10 +263,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::UpdateDownloadsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::UpdateDownloadsPrompt.into()); } #[test] @@ -310,7 +306,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Downloads.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Downloads.into()); assert!(app.should_refresh); } @@ -371,11 +367,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); - assert_eq!(app.get_current_route(), base_route.into()); + assert_navigation_popped!(app, base_route.into()); } } diff --git a/src/handlers/sonarr_handlers/downloads/mod.rs b/src/handlers/sonarr_handlers/downloads/mod.rs index d6adab0..7a9819a 100644 --- a/src/handlers/sonarr_handlers/downloads/mod.rs +++ b/src/handlers/sonarr_handlers/downloads/mod.rs @@ -1,12 +1,11 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS}; -use crate::models::sonarr_models::DownloadRecord; use crate::network::sonarr_network::SonarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "downloads_handler_tests.rs"] @@ -20,13 +19,6 @@ pub(super) struct DownloadsHandler<'a, 'b> { } impl DownloadsHandler<'_, '_> { - handle_table_events!( - self, - downloads, - self.app.data.sonarr_data.downloads, - DownloadRecord - ); - fn extract_download_id(&self) -> i64 { self.app.data.sonarr_data.downloads.current_selection().id } @@ -37,7 +29,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a, let download_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::Downloads.into()); - if !self.handle_downloads_table_events(download_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.downloads, + download_table_handling_config, + ) { self.handle_key_event(); } } @@ -163,4 +159,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/history/history_handler_tests.rs b/src/handlers/sonarr_handlers/history/history_handler_tests.rs index 5d51e20..4a34d17 100644 --- a/src/handlers/sonarr_handlers/history/history_handler_tests.rs +++ b/src/handlers/sonarr_handlers/history/history_handler_tests.rs @@ -7,11 +7,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::sonarr_handlers::history::{history_sorting_options, HistoryHandler}; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::history::{HistoryHandler, history_sorting_options}; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS}; use crate::models::servarr_models::{Language, Quality, QualityWrapper}; use crate::models::sonarr_models::{SonarrHistoryEventType, SonarrHistoryItem}; @@ -21,6 +22,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_history_tab_left(#[values(true, false)] is_ready: bool) { @@ -41,7 +43,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Blocklist.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Blocklist.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Blocklist.into()); } #[rstest] @@ -85,10 +87,7 @@ mod tests { HistoryHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::History, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::HistoryItemDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::HistoryItemDetails.into()); } #[test] @@ -111,6 +110,7 @@ mod tests { use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -133,7 +133,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::History.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::History.into()); } #[rstest] @@ -153,7 +153,7 @@ mod tests { HistoryHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::History, None).handle(); assert_eq!(app.get_current_route(), ActiveSonarrBlock::History.into()); - assert!(app.error.text.is_empty()); + assert_is_empty!(app.error.text); } } @@ -161,6 +161,7 @@ mod tests { use pretty_assertions::assert_eq; use super::*; + use crate::assert_navigation_pushed; #[test] fn test_refresh_history_key() { @@ -176,7 +177,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::History.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::History.into()); assert!(app.should_refresh); } diff --git a/src/handlers/sonarr_handlers/history/mod.rs b/src/handlers/sonarr_handlers/history/mod.rs index 262f7bb..049de25 100644 --- a/src/handlers/sonarr_handlers/history/mod.rs +++ b/src/handlers/sonarr_handlers/history/mod.rs @@ -1,13 +1,13 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors}; +use crate::matches_key; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS}; use crate::models::servarr_models::Language; use crate::models::sonarr_models::SonarrHistoryItem; use crate::models::stateful_table::SortOption; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "history_handler_tests.rs"] @@ -20,20 +20,12 @@ pub(super) struct HistoryHandler<'a, 'b> { _context: Option, } -impl HistoryHandler<'_, '_> { - handle_table_events!( - self, - history, - self.app.data.sonarr_data.history, - SonarrHistoryItem - ); -} +impl HistoryHandler<'_, '_> {} impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for HistoryHandler<'a, 'b> { fn handle(&mut self) { let history_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::History.into()) .sorting_block(ActiveSonarrBlock::HistorySortPrompt.into()) - .sort_by_fn(|a: &SonarrHistoryItem, b: &SonarrHistoryItem| a.id.cmp(&b.id)) .sort_options(history_sorting_options()) .searching_block(ActiveSonarrBlock::SearchHistory.into()) .search_error_block(ActiveSonarrBlock::SearchHistoryError.into()) @@ -42,7 +34,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for HistoryHandler<'a, ' .filter_error_block(ActiveSonarrBlock::FilterHistoryError.into()) .filter_field_fn(|history| &history.source_title.text); - if !self.handle_history_table_events(history_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.history, + history_table_handling_config, + ) { self.handle_key_event(); } } @@ -120,10 +116,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for HistoryHandler<'a, ' } } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } -pub(in crate::handlers::sonarr_handlers) fn history_sorting_options( -) -> Vec> { +pub(in crate::handlers::sonarr_handlers) fn history_sorting_options() +-> Vec> { vec![ SortOption { name: "Source Title", diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs index 68cd44c..c253008 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs @@ -1,6 +1,6 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::servarr_models::EditIndexerParams; @@ -521,4 +521,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler_tests.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler_tests.rs index 87468d0..824ecae 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler_tests.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler_tests.rs @@ -1,11 +1,14 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::indexer; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::servarr_models::EditIndexerParams; @@ -18,9 +21,9 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; + use crate::models::BlockSelectionState; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use super::*; @@ -419,11 +422,11 @@ mod tests { use std::sync::atomic::Ordering; use crate::app::App; + use crate::models::BlockSelectionState; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::{ EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, }; - use crate::models::BlockSelectionState; use pretty_assertions::assert_eq; use rstest::rstest; @@ -850,9 +853,10 @@ mod tests { use rstest::rstest; use crate::app::App; + use crate::assert_navigation_popped; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::{ - servarr_data::sonarr::sonarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, servarr_data::sonarr::sonarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, }; use crate::network::sonarr_network::SonarrEvent; @@ -882,10 +886,10 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.should_refresh); - assert_eq!(app.data.sonarr_data.edit_indexer_modal, None); + assert_none!(app.data.sonarr_data.edit_indexer_modal); } #[test] @@ -936,8 +940,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert!(app.data.sonarr_data.edit_indexer_modal.is_none()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_modal_absent!(app.data.sonarr_data.edit_indexer_modal); assert!(app.should_refresh); assert_eq!( app.data.sonarr_data.prompt_confirm_action, @@ -966,9 +970,9 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(app.data.sonarr_data.edit_indexer_modal.is_some()); + assert_modal_present!(app.data.sonarr_data.edit_indexer_modal); assert!(!app.should_refresh); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_none!(app.data.sonarr_data.prompt_confirm_action); } #[rstest] @@ -1002,7 +1006,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), block.into()); + assert_navigation_pushed!(app, block.into()); assert!(app.ignore_special_keys_for_textbox_input); } @@ -1024,10 +1028,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPriorityInput.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::EditIndexerPriorityInput.into()); assert!(!app.ignore_special_keys_for_textbox_input); } @@ -1053,14 +1054,16 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_rss - .unwrap()); + assert!( + app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_rss + .unwrap() + ); EditIndexerHandler::new( SUBMIT_KEY, @@ -1074,14 +1077,16 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_rss - .unwrap()); + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_rss + .unwrap() + ); } #[test] @@ -1106,14 +1111,16 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_automatic_search - .unwrap()); + assert!( + app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_automatic_search + .unwrap() + ); EditIndexerHandler::new( SUBMIT_KEY, @@ -1127,14 +1134,16 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_automatic_search - .unwrap()); + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_automatic_search + .unwrap() + ); } #[test] @@ -1159,14 +1168,16 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_interactive_search - .unwrap()); + assert!( + app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_interactive_search + .unwrap() + ); EditIndexerHandler::new( SUBMIT_KEY, @@ -1180,14 +1191,16 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditIndexerPrompt.into() ); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .enable_interactive_search - .unwrap()); + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .enable_interactive_search + .unwrap() + ); } #[test] @@ -1211,19 +1224,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .name - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .name + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1247,19 +1259,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .url - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .url + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1283,19 +1294,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .api_key - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .api_key + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1319,19 +1329,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .seed_ratio - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .seed_ratio + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditIndexerPrompt.into()); } #[test] @@ -1355,28 +1364,27 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .tags - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .tags + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditIndexerPrompt.into()); } } mod test_handle_esc { use super::*; use crate::app::App; + use crate::assert_navigation_popped; use crate::event::Key; use crate::models::servarr_data::modals::EditIndexerModal; - use pretty_assertions::assert_eq; use rstest::rstest; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -1397,9 +1405,9 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.edit_indexer_modal, None); + assert_none!(app.data.sonarr_data.edit_indexer_modal); } #[rstest] @@ -1422,25 +1430,25 @@ mod tests { EditIndexerHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.data.sonarr_data.edit_indexer_modal, - Some(EditIndexerModal::default()) + assert_some_eq_x!( + &app.data.sonarr_data.edit_indexer_modal, + &EditIndexerModal::default() ); } } mod test_handle_key_char { + use super::*; use crate::app::App; + use crate::assert_navigation_popped; + use crate::models::BlockSelectionState; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use crate::network::sonarr_network::SonarrEvent; use pretty_assertions::{assert_eq, assert_str_eq}; - use super::*; - #[test] fn test_edit_indexer_name_input_backspace() { let mut app = App::test_default(); @@ -1773,8 +1781,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert!(app.data.sonarr_data.edit_indexer_modal.is_none()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_modal_absent!(app.data.sonarr_data.edit_indexer_modal); assert!(app.should_refresh); assert_eq!( app.data.sonarr_data.prompt_confirm_action, @@ -1852,7 +1860,7 @@ mod tests { .build_edit_indexer_params(); assert_eq!(params, expected_edit_indexer_params); - assert!(app.data.sonarr_data.edit_indexer_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_indexer_modal); } #[test] diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs index 039f35f..8da2449 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -1,6 +1,6 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS, }; @@ -197,4 +197,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandl self.app.pop_navigation_stack(); } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler_tests.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler_tests.rs index f49a86a..c8464f7 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler_tests.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler_tests.rs @@ -4,12 +4,14 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::indexer_settings; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS, }; @@ -19,9 +21,9 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; + use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS; use crate::models::sonarr_models::IndexerSettings; - use crate::models::BlockSelectionState; use super::*; @@ -237,9 +239,10 @@ mod tests { use rstest::rstest; use crate::{ + assert_navigation_popped, models::{ - servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, - sonarr_models::IndexerSettings, BlockSelectionState, + BlockSelectionState, servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, + sonarr_models::IndexerSettings, }, network::sonarr_network::SonarrEvent, }; @@ -270,10 +273,10 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.should_refresh); - assert_eq!(app.data.sonarr_data.indexer_settings, None); + assert_none!(app.data.sonarr_data.indexer_settings); } #[test] @@ -299,12 +302,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::EditAllIndexerSettings(indexer_settings())) + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::EditAllIndexerSettings(indexer_settings()) ); - assert!(app.data.sonarr_data.indexer_settings.is_none()); + assert_modal_absent!(app.data.sonarr_data.indexer_settings); assert!(app.should_refresh); } @@ -357,7 +360,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), selected_block.into()); + assert_navigation_pushed!(app, selected_block.into()); } #[rstest] @@ -405,20 +408,17 @@ mod tests { IndexerSettingsHandler::new(SUBMIT_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AllIndexerSettingsPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::AllIndexerSettingsPrompt.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use crate::models::sonarr_models::IndexerSettings; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -438,9 +438,9 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.indexer_settings, None); + assert_none!(app.data.sonarr_data.indexer_settings); } #[rstest] @@ -460,22 +460,22 @@ mod tests { IndexerSettingsHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!( - app.data.sonarr_data.indexer_settings, - Some(IndexerSettings::default()) + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_some_eq_x!( + &app.data.sonarr_data.indexer_settings, + &IndexerSettings::default() ); } } mod test_handle_key_char { use crate::{ + assert_navigation_popped, models::{ - servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, }, network::sonarr_network::SonarrEvent, }; - use pretty_assertions::assert_eq; use super::*; @@ -501,12 +501,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::EditAllIndexerSettings(indexer_settings())) + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::EditAllIndexerSettings(indexer_settings()) ); - assert!(app.data.sonarr_data.indexer_settings.is_none()); + assert_modal_absent!(app.data.sonarr_data.indexer_settings); assert!(app.should_refresh); } } @@ -555,7 +555,7 @@ mod tests { .build_edit_indexer_settings_params(); assert_eq!(actual_indexer_settings, indexer_settings()); - assert!(app.data.sonarr_data.indexer_settings.is_none()); + assert_modal_absent!(app.data.sonarr_data.indexer_settings); } #[test] diff --git a/src/handlers/sonarr_handlers/indexers/indexers_handler_tests.rs b/src/handlers/sonarr_handlers/indexers/indexers_handler_tests.rs index 5d218b3..81357dd 100644 --- a/src/handlers/sonarr_handlers/indexers/indexers_handler_tests.rs +++ b/src/handlers/sonarr_handlers/indexers/indexers_handler_tests.rs @@ -4,14 +4,15 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::indexers::IndexersHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::indexer; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, + ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXERS_BLOCKS, }; use crate::models::servarr_models::Indexer; use crate::test_handler_delegation; @@ -35,10 +36,7 @@ mod tests { IndexersHandler::new(DELETE_KEY, &mut app, ActiveSonarrBlock::Indexers, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::DeleteIndexerPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::DeleteIndexerPrompt.into()); } #[test] @@ -83,10 +81,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::RootFolders.into() ); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::RootFolders.into()); } #[rstest] @@ -108,7 +103,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::System.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::System.into()); } #[rstest] @@ -129,17 +124,17 @@ mod tests { } mod test_handle_submit { + use crate::assert_navigation_popped; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::sonarr::sonarr_data::{ - SonarrData, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, + EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, SonarrData, }; use crate::models::servarr_models::{Indexer, IndexerField}; + use crate::network::sonarr_network::SonarrEvent; use bimap::BiMap; use pretty_assertions::assert_eq; use serde_json::{Number, Value}; - use crate::network::sonarr_network::SonarrEvent; - use super::*; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -201,17 +196,14 @@ mod tests { IndexersHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::Indexers, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditIndexerPrompt.into() + assert_navigation_pushed!(app, ActiveSonarrBlock::EditIndexerPrompt.into()); + assert_some_eq_x!( + &app.data.sonarr_data.edit_indexer_modal, + &EditIndexerModal::from(&app.data.sonarr_data) ); - assert_eq!( - app.data.sonarr_data.edit_indexer_modal, - Some((&app.data.sonarr_data).into()) - ); - assert_eq!( - app.data.sonarr_data.edit_indexer_modal, - Some(expected_edit_indexer_modal) + assert_some_eq_x!( + &app.data.sonarr_data.edit_indexer_modal, + &expected_edit_indexer_modal ); if torrent_protocol { assert_eq!( @@ -241,7 +233,7 @@ mod tests { IndexersHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::Indexers, None).handle(); assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!(app.data.sonarr_data.edit_indexer_modal, None); + assert_none!(app.data.sonarr_data.edit_indexer_modal); } #[test] @@ -261,11 +253,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DeleteIndexer(1)) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DeleteIndexer(1) ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); } #[test] @@ -288,15 +280,15 @@ mod tests { .handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -316,7 +308,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); assert!(!app.data.sonarr_data.prompt_confirm); } @@ -330,8 +322,8 @@ mod tests { IndexersHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::TestIndexer, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert_eq!(app.data.sonarr_data.indexer_test_errors, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_none!(app.data.sonarr_data.indexer_test_errors); } #[rstest] @@ -344,8 +336,8 @@ mod tests { IndexersHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::Indexers, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); + assert_is_empty!(app.error.text); } } @@ -353,6 +345,7 @@ mod tests { use pretty_assertions::assert_eq; use crate::{ + assert_navigation_popped, models::servarr_data::sonarr::sonarr_data::INDEXER_SETTINGS_SELECTION_BLOCKS, network::sonarr_network::SonarrEvent, }; @@ -377,7 +370,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Indexers.into()); assert!(app.should_refresh); } @@ -427,10 +420,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AllIndexerSettingsPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::AllIndexerSettingsPrompt.into()); assert_eq!( app.data.sonarr_data.selected_block.blocks, INDEXER_SETTINGS_SELECTION_BLOCKS @@ -477,10 +467,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::TestIndexer.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::TestIndexer.into()); } #[test] @@ -523,10 +510,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::TestAllIndexers.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::TestAllIndexers.into()); } #[test] @@ -567,11 +551,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DeleteIndexer(1)) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DeleteIndexer(1) ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); } } diff --git a/src/handlers/sonarr_handlers/indexers/mod.rs b/src/handlers/sonarr_handlers/indexers/mod.rs index 2dae7d9..cc33890 100644 --- a/src/handlers/sonarr_handlers/indexers/mod.rs +++ b/src/handlers/sonarr_handlers/indexers/mod.rs @@ -4,16 +4,15 @@ use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::sonarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler; use crate::handlers::sonarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler; use crate::handlers::sonarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; +use crate::matches_key; +use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, - INDEXERS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, + INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, }; -use crate::models::servarr_models::Indexer; -use crate::models::BlockSelectionState; use crate::network::sonarr_network::SonarrEvent; -use crate::{handle_table_events, matches_key}; mod edit_indexer_handler; mod edit_indexer_settings_handler; @@ -31,8 +30,6 @@ pub(super) struct IndexersHandler<'a, 'b> { } impl IndexersHandler<'_, '_> { - handle_table_events!(self, indexers, self.app.data.sonarr_data.indexers, Indexer); - fn extract_indexer_id(&self) -> i64 { self.app.data.sonarr_data.indexers.current_selection().id } @@ -43,7 +40,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a, let indexers_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::Indexers.into()); - if !self.handle_indexers_table_events(indexers_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.indexers, + indexers_table_handling_config, + ) { match self.active_sonarr_block { _ if EditIndexerHandler::accepts(self.active_sonarr_block) => { EditIndexerHandler::new(self.key, self.app, self.active_sonarr_block, self.context) @@ -205,4 +206,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler.rs b/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler.rs index de4bad1..d0e3d57 100644 --- a/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler.rs @@ -1,9 +1,7 @@ use crate::app::App; use crate::event::Key; -use crate::handle_table_events; -use crate::handlers::table_handler::TableHandlingConfig; use crate::handlers::KeyEventHandler; -use crate::models::servarr_data::modals::IndexerTestResultModalItem; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; #[cfg(test)] @@ -17,29 +15,25 @@ pub(super) struct TestAllIndexersHandler<'a, 'b> { _context: Option, } -impl TestAllIndexersHandler<'_, '_> { - handle_table_events!( - self, - indexer_test_all_results, - self - .app - .data - .sonarr_data - .indexer_test_all_results - .as_mut() - .unwrap(), - IndexerTestResultModalItem - ); -} +impl TestAllIndexersHandler<'_, '_> {} impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for TestAllIndexersHandler<'a, 'b> { fn handle(&mut self) { let indexer_test_all_results_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::TestAllIndexers.into()); - if !self - .handle_indexer_test_all_results_table_events(indexer_test_all_results_table_handling_config) - { + if !handle_table( + self, + |app| { + app + .data + .sonarr_data + .indexer_test_all_results + .as_mut() + .unwrap() + }, + indexer_test_all_results_table_handling_config, + ) { self.handle_key_event(); } } @@ -102,4 +96,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for TestAllIndexersHandl } fn handle_char_key_event(&mut self) {} + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler_tests.rs b/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler_tests.rs index 0764f16..f1972f3 100644 --- a/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler_tests.rs +++ b/src/handlers/sonarr_handlers/indexers/test_all_indexers_handler_tests.rs @@ -1,9 +1,9 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; - use crate::handlers::sonarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::indexers::test_all_indexers_handler::TestAllIndexersHandler; use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::stateful_table::StatefulTable; @@ -13,7 +13,7 @@ mod tests { mod test_handle_esc { use super::*; use crate::models::stateful_table::StatefulTable; - use pretty_assertions::assert_eq; + use crate::{assert_modal_absent, assert_navigation_popped}; use rstest::rstest; #[rstest] @@ -32,9 +32,9 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Indexers.into()); assert!(!app.data.sonarr_data.prompt_confirm); - assert!(app.data.sonarr_data.indexer_test_all_results.is_none()); + assert_modal_absent!(app.data.sonarr_data.indexer_test_all_results); } } diff --git a/src/handlers/sonarr_handlers/library/add_series_handler.rs b/src/handlers/sonarr_handlers/library/add_series_handler.rs index 304d3a6..e6f8162 100644 --- a/src/handlers/sonarr_handlers/library/add_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/add_series_handler.rs @@ -1,16 +1,13 @@ -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::models::servarr_data::sonarr::modals::AddSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, ADD_SERIES_BLOCKS, ADD_SERIES_SELECTION_BLOCKS, + ADD_SERIES_BLOCKS, ADD_SERIES_SELECTION_BLOCKS, ActiveSonarrBlock, }; use crate::models::sonarr_models::{AddSeriesBody, AddSeriesOptions, AddSeriesSearchResult}; -use crate::models::stateful_table::StatefulTable; use crate::models::{BlockSelectionState, Scrollable}; use crate::network::sonarr_network::SonarrEvent; -use crate::{ - handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, App, Key, -}; +use crate::{App, Key, handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; #[cfg(test)] #[path = "add_series_handler_tests.rs"] @@ -24,19 +21,6 @@ pub(super) struct AddSeriesHandler<'a, 'b> { } impl AddSeriesHandler<'_, '_> { - handle_table_events!( - self, - add_searched_series, - self - .app - .data - .sonarr_data - .add_searched_series - .as_mut() - .unwrap_or(&mut StatefulTable::default()), - AddSeriesSearchResult - ); - fn build_add_series_body(&mut self) -> AddSeriesBody { let add_series_modal = self .app @@ -118,7 +102,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a, let add_series_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::AddSeriesSearchResults.into()); - if !self.handle_add_searched_series_table_events(add_series_table_handling_config) { + if !handle_table( + self, + |app| { + app + .data + .sonarr_data + .add_searched_series + .as_mut() + .expect("add_searched_series should be initialized") + }, + add_series_table_handling_config, + ) { self.handle_key_event(); } } @@ -625,4 +620,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a, _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/library/add_series_handler_tests.rs b/src/handlers/sonarr_handlers/library/add_series_handler_tests.rs index db9740b..e7a783a 100644 --- a/src/handlers/sonarr_handlers/library/add_series_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/add_series_handler_tests.rs @@ -5,29 +5,32 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::library::add_series_handler::AddSeriesHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::add_series_search_result; - use crate::handlers::KeyEventHandler; + use crate::models::HorizontallyScrollableText; use crate::models::servarr_data::sonarr::modals::AddSeriesModal; - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ADD_SERIES_BLOCKS}; + use crate::models::servarr_data::sonarr::sonarr_data::{ADD_SERIES_BLOCKS, ActiveSonarrBlock}; use crate::models::servarr_models::RootFolder; use crate::models::sonarr_models::{ AddSeriesBody, AddSeriesOptions, AddSeriesSearchResult, SeriesMonitor, SeriesType, }; use crate::models::stateful_table::StatefulTable; - use crate::models::HorizontallyScrollableText; mod test_handle_scroll_up_and_down { use pretty_assertions::assert_eq; use rstest::rstest; use strum::IntoEnumIterator; + use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::modals::AddSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::ADD_SERIES_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use crate::simple_stateful_iterable_vec; use super::*; @@ -894,16 +897,16 @@ mod tests { } mod test_handle_submit { - use bimap::BiMap; - use pretty_assertions::{assert_eq, assert_str_eq}; - use rstest::rstest; - + use crate::assert_navigation_popped; + use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::modals::AddSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::ADD_SERIES_SELECTION_BLOCKS; use crate::models::sonarr_models::Series; use crate::models::stateful_table::StatefulTable; - use crate::models::BlockSelectionState; use crate::network::sonarr_network::SonarrEvent; + use bimap::BiMap; + use pretty_assertions::{assert_eq, assert_str_eq}; + use rstest::rstest; use super::*; @@ -925,10 +928,7 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesSearchResults.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::AddSeriesSearchResults.into()); } #[test] @@ -972,42 +972,45 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::AddSeriesPrompt.into()); assert_eq!( app.data.sonarr_data.selected_block.get_active_block(), ActiveSonarrBlock::AddSeriesSelectRootFolder ); - assert!(app.data.sonarr_data.add_series_modal.is_some()); - assert!(!app - .data - .sonarr_data - .add_series_modal - .as_ref() - .unwrap() - .monitor_list - .items - .is_empty()); - assert!(!app - .data - .sonarr_data - .add_series_modal - .as_ref() - .unwrap() - .series_type_list - .items - .is_empty()); - assert!(!app - .data - .sonarr_data - .add_series_modal - .as_ref() - .unwrap() - .quality_profile_list - .items - .is_empty()); + assert_modal_present!(app.data.sonarr_data.add_series_modal); + assert!( + !app + .data + .sonarr_data + .add_series_modal + .as_ref() + .unwrap() + .monitor_list + .items + .is_empty() + ); + assert!( + !app + .data + .sonarr_data + .add_series_modal + .as_ref() + .unwrap() + .series_type_list + .items + .is_empty() + ); + assert!( + !app + .data + .sonarr_data + .add_series_modal + .as_ref() + .unwrap() + .quality_profile_list + .items + .is_empty() + ); assert_str_eq!( app .data @@ -1042,7 +1045,7 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::AddSeriesSearchResults.into() ); - assert!(app.data.sonarr_data.add_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.add_series_modal); } #[test] @@ -1085,10 +1088,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesAlreadyInLibrary.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::AddSeriesAlreadyInLibrary.into()); } #[test] @@ -1111,8 +1111,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); } #[test] @@ -1194,12 +1194,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert_eq!( app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::AddSeries(expected_add_series_body)) ); - assert!(app.data.sonarr_data.add_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.add_series_modal); } #[rstest] @@ -1227,8 +1227,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), selected_block.into()); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_pushed!(app, selected_block.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); if selected_block == ActiveSonarrBlock::AddSeriesTagsInput { assert!(app.ignore_special_keys_for_textbox_input); @@ -1254,10 +1254,7 @@ mod tests { AddSeriesHandler::new(SUBMIT_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesPrompt.into()); if active_sonarr_block == ActiveSonarrBlock::AddSeriesTagsInput { assert!(!app.ignore_special_keys_for_textbox_input); @@ -1320,13 +1317,12 @@ mod tests { } mod test_handle_esc { - use pretty_assertions::assert_eq; use rstest::rstest; use crate::models::servarr_data::sonarr::modals::AddSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::stateful_table::StatefulTable; - use crate::simple_stateful_iterable_vec; + use crate::{assert_navigation_popped, simple_stateful_iterable_vec}; use super::*; @@ -1350,8 +1346,8 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); - assert_eq!(app.data.sonarr_data.add_series_search, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); + assert_none!(app.data.sonarr_data.add_series_search); } #[test] @@ -1372,10 +1368,7 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesPrompt.into()); } #[rstest] @@ -1399,11 +1392,8 @@ mod tests { AddSeriesHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesSearchInput.into() - ); - assert!(app.data.sonarr_data.add_searched_series.is_none()); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesSearchInput.into()); + assert_modal_absent!(app.data.sonarr_data.add_searched_series); assert!(app.ignore_special_keys_for_textbox_input); } @@ -1423,10 +1413,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesSearchResults.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesSearchResults.into()); } #[test] @@ -1441,11 +1428,8 @@ mod tests { AddSeriesHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::AddSeriesPrompt, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesSearchResults.into() - ); - assert!(app.data.sonarr_data.add_series_modal.is_none()); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesSearchResults.into()); + assert_modal_absent!(app.data.sonarr_data.add_series_modal); } #[test] @@ -1466,10 +1450,7 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesPrompt.into()); } #[rstest] @@ -1490,19 +1471,17 @@ mod tests { AddSeriesHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::AddSeriesPrompt.into()); } } mod test_handle_key_char { use super::*; use crate::{ + assert_navigation_popped, models::{ - servarr_data::sonarr::{modals::AddSeriesModal, sonarr_data::ADD_SERIES_SELECTION_BLOCKS}, BlockSelectionState, + servarr_data::sonarr::{modals::AddSeriesModal, sonarr_data::ADD_SERIES_SELECTION_BLOCKS}, }, network::sonarr_network::SonarrEvent, }; @@ -1695,12 +1674,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert_eq!( app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::AddSeries(expected_add_series_body)) ); - assert!(app.data.sonarr_data.add_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.add_series_modal); } } @@ -1818,7 +1797,7 @@ mod tests { .build_add_series_body(); assert_eq!(add_series_body, expected_add_series_body); - assert!(app.data.sonarr_data.add_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.add_series_modal); } #[test] diff --git a/src/handlers/sonarr_handlers/library/delete_series_handler.rs b/src/handlers/sonarr_handlers/library/delete_series_handler.rs index c98d262..97fde80 100644 --- a/src/handlers/sonarr_handlers/library/delete_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/delete_series_handler.rs @@ -3,7 +3,7 @@ use crate::network::sonarr_network::SonarrEvent; use crate::{ app::App, event::Key, - handlers::{handle_prompt_toggle, KeyEventHandler}, + handlers::{KeyEventHandler, handle_prompt_toggle}, matches_key, models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS}, }; @@ -138,4 +138,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DeleteSeriesHandler< self.app.pop_navigation_stack(); } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/library/delete_series_handler_tests.rs b/src/handlers/sonarr_handlers/library/delete_series_handler_tests.rs index 4c85ec7..50a6520 100644 --- a/src/handlers/sonarr_handlers/library/delete_series_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/delete_series_handler_tests.rs @@ -4,12 +4,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::library::delete_series_handler::DeleteSeriesHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::series; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS}; use crate::models::sonarr_models::DeleteSeriesParams; @@ -17,8 +17,8 @@ mod tests { use pretty_assertions::assert_eq; use rstest::rstest; - use crate::models::servarr_data::sonarr::sonarr_data::DELETE_SERIES_SELECTION_BLOCKS; use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::DELETE_SERIES_SELECTION_BLOCKS; use super::*; @@ -86,11 +86,12 @@ mod tests { mod test_handle_submit { use pretty_assertions::assert_eq; - use crate::models::servarr_data::sonarr::sonarr_data::DELETE_SERIES_SELECTION_BLOCKS; use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::DELETE_SERIES_SELECTION_BLOCKS; use crate::network::sonarr_network::SonarrEvent; use super::*; + use crate::assert_navigation_popped; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -117,8 +118,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.data.sonarr_data.prompt_confirm); assert!(!app.data.sonarr_data.delete_series_files); assert!(!app.data.sonarr_data.add_list_exclusion); @@ -154,7 +155,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert_eq!( app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::DeleteSeries(expected_delete_series_params)) @@ -187,7 +188,7 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::DeleteSeriesPrompt.into() ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_none!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.should_refresh); assert!(app.data.sonarr_data.prompt_confirm); assert!(app.data.sonarr_data.delete_series_files); @@ -228,7 +229,7 @@ mod tests { mod test_handle_esc { use super::*; - use pretty_assertions::assert_eq; + use crate::assert_navigation_popped; use rstest::rstest; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -251,7 +252,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert!(!app.data.sonarr_data.prompt_confirm); assert!(!app.data.sonarr_data.delete_series_files); assert!(!app.data.sonarr_data.add_list_exclusion); @@ -260,8 +261,9 @@ mod tests { mod test_handle_key_char { use crate::{ + assert_navigation_popped, models::{ - servarr_data::sonarr::sonarr_data::DELETE_SERIES_SELECTION_BLOCKS, BlockSelectionState, + BlockSelectionState, servarr_data::sonarr::sonarr_data::DELETE_SERIES_SELECTION_BLOCKS, }, network::sonarr_network::SonarrEvent, }; @@ -298,7 +300,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert_eq!( app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::DeleteSeries(expected_delete_series_params)) diff --git a/src/handlers/sonarr_handlers/library/edit_series_handler.rs b/src/handlers/sonarr_handlers/library/edit_series_handler.rs index fa72b4d..a57224e 100644 --- a/src/handlers/sonarr_handlers/library/edit_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/edit_series_handler.rs @@ -1,10 +1,10 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::models::Scrollable; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS}; use crate::models::sonarr_models::EditSeriesParams; -use crate::models::Scrollable; use crate::network::sonarr_network::SonarrEvent; use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; @@ -466,4 +466,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/library/edit_series_handler_tests.rs b/src/handlers/sonarr_handlers/library/edit_series_handler_tests.rs index 7bb05a1..6eb48b7 100644 --- a/src/handlers/sonarr_handlers/library/edit_series_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/edit_series_handler_tests.rs @@ -5,12 +5,14 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::library::edit_series_handler::EditSeriesHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::series; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS}; use crate::models::sonarr_models::{EditSeriesParams, Series, SeriesType}; @@ -20,9 +22,9 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; + use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::EDIT_SERIES_SELECTION_BLOCKS; - use crate::models::BlockSelectionState; use super::*; @@ -663,13 +665,13 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::EDIT_SERIES_SELECTION_BLOCKS; use crate::models::{BlockSelectionState, Route}; use crate::network::sonarr_network::SonarrEvent; + use pretty_assertions::assert_eq; + use rstest::rstest; use super::*; @@ -696,19 +698,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_series_modal - .as_ref() - .unwrap() - .path - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditSeriesPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_series_modal + .as_ref() + .unwrap() + .path + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditSeriesPrompt.into()); } #[test] @@ -732,19 +733,18 @@ mod tests { .handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(!app - .data - .sonarr_data - .edit_series_modal - .as_mut() - .unwrap() - .tags - .text - .is_empty()); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditSeriesPrompt.into() + assert!( + !app + .data + .sonarr_data + .edit_series_modal + .as_mut() + .unwrap() + .tags + .text + .is_empty() ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditSeriesPrompt.into()); } #[test] @@ -768,8 +768,8 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); } #[test] @@ -830,12 +830,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert_eq!( app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::EditSeries(expected_edit_series_params)) ); - assert!(app.data.sonarr_data.edit_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_series_modal); assert!(app.should_refresh); } @@ -860,7 +860,7 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::EditSeriesPrompt.into() ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_none!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.should_refresh); } @@ -885,7 +885,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .sonarr_data @@ -893,7 +893,7 @@ mod tests { .as_ref() .unwrap() .monitored, - Some(true) + true ); EditSeriesHandler::new( @@ -905,7 +905,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .sonarr_data @@ -913,7 +913,7 @@ mod tests { .as_ref() .unwrap() .monitored, - Some(false) + false ); } @@ -939,7 +939,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .sonarr_data @@ -947,7 +947,7 @@ mod tests { .as_ref() .unwrap() .use_season_folders, - Some(true) + true ); EditSeriesHandler::new( @@ -959,7 +959,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), current_route); - assert_eq!( + assert_some_eq_x!( app .data .sonarr_data @@ -967,7 +967,7 @@ mod tests { .as_ref() .unwrap() .use_season_folders, - Some(false) + false ); } @@ -1002,11 +1002,11 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, (selected_block, Some(ActiveSonarrBlock::Series)).into() ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_none!(app.data.sonarr_data.prompt_confirm_action); if selected_block == ActiveSonarrBlock::EditSeriesPathInput || selected_block == ActiveSonarrBlock::EditSeriesTagsInput @@ -1049,7 +1049,7 @@ mod tests { ) .into() ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_none!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.ignore_special_keys_for_textbox_input); } @@ -1078,10 +1078,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditSeriesPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditSeriesPrompt.into()); if active_sonarr_block == ActiveSonarrBlock::EditSeriesPathInput || active_sonarr_block == ActiveSonarrBlock::EditSeriesTagsInput @@ -1092,11 +1089,10 @@ mod tests { } mod test_handle_esc { - use pretty_assertions::assert_eq; - use rstest::rstest; - + use crate::assert_navigation_popped; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; + use rstest::rstest; use super::*; @@ -1120,10 +1116,7 @@ mod tests { EditSeriesHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EditSeriesPrompt.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::EditSeriesPrompt.into()); } #[test] @@ -1136,9 +1129,9 @@ mod tests { EditSeriesHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::EditSeriesPrompt, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); - assert!(app.data.sonarr_data.edit_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_series_modal); assert!(!app.data.sonarr_data.prompt_confirm); } @@ -1160,18 +1153,19 @@ mod tests { EditSeriesHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); } } mod test_handle_key_char { use super::*; use crate::{ + assert_navigation_popped, models::{ + BlockSelectionState, servarr_data::sonarr::{ modals::EditSeriesModal, sonarr_data::EDIT_SERIES_SELECTION_BLOCKS, }, - BlockSelectionState, }, network::sonarr_network::SonarrEvent, }; @@ -1348,12 +1342,12 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert_eq!( app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::EditSeries(expected_edit_series_params)) ); - assert!(app.data.sonarr_data.edit_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_series_modal); assert!(app.should_refresh); } } @@ -1438,7 +1432,7 @@ mod tests { .build_edit_series_params(); assert_eq!(edit_series_params, expected_edit_series_params); - assert!(app.data.sonarr_data.edit_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_series_modal); } #[test] diff --git a/src/handlers/sonarr_handlers/library/episode_details_handler.rs b/src/handlers/sonarr_handlers/library/episode_details_handler.rs index 037c97a..c007778 100644 --- a/src/handlers/sonarr_handlers/library/episode_details_handler.rs +++ b/src/handlers/sonarr_handlers/library/episode_details_handler.rs @@ -1,12 +1,12 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::library::season_details_handler::releases_sorting_options; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::matches_key; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS}; -use crate::models::sonarr_models::{SonarrHistoryItem, SonarrRelease, SonarrReleaseDownloadBody}; +use crate::models::sonarr_models::{SonarrRelease, SonarrReleaseDownloadBody}; use crate::network::sonarr_network::SonarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "episode_details_handler_tests.rs"] @@ -20,39 +20,6 @@ pub(super) struct EpisodeDetailsHandler<'a, 'b> { } impl EpisodeDetailsHandler<'_, '_> { - handle_table_events!( - self, - episode_history, - self - .app - .data - .sonarr_data - .season_details_modal - .as_mut() - .expect("Season details modal is undefined") - .episode_details_modal - .as_mut() - .expect("Episode details modal is undefined") - .episode_history, - SonarrHistoryItem - ); - handle_table_events!( - self, - episode_releases, - self - .app - .data - .sonarr_data - .season_details_modal - .as_mut() - .expect("Season details modal is undefined") - .episode_details_modal - .as_mut() - .expect("Episode details modal is undefined") - .episode_releases, - SonarrRelease - ); - fn extract_episode_id(&self) -> i64 { self .app @@ -76,9 +43,37 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle .sorting_block(ActiveSonarrBlock::ManualEpisodeSearchSortPrompt.into()) .sort_options(releases_sorting_options()); - if !self.handle_episode_history_table_events(episode_history_table_handling_config) - && !self.handle_episode_releases_table_events(episode_releases_table_handling_config) - { + if !handle_table( + self, + |app| { + &mut app + .data + .sonarr_data + .season_details_modal + .as_mut() + .expect("Season details modal is undefined") + .episode_details_modal + .as_mut() + .expect("Episode details modal is undefined") + .episode_history + }, + episode_history_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .sonarr_data + .season_details_modal + .as_mut() + .expect("Season details modal is undefined") + .episode_details_modal + .as_mut() + .expect("Episode details modal is undefined") + .episode_releases + }, + episode_releases_table_handling_config, + ) { self.handle_key_event(); } } @@ -110,23 +105,23 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle } fn is_ready(&self) -> bool { - !self.app.is_loading - && if let Some(season_details_modal) = self.app.data.sonarr_data.season_details_modal.as_ref() - { - if let Some(episode_details_modal) = &season_details_modal.episode_details_modal { - match self.active_sonarr_block { - ActiveSonarrBlock::EpisodeHistory => !episode_details_modal.episode_history.is_empty(), - ActiveSonarrBlock::ManualEpisodeSearch => { - !episode_details_modal.episode_releases.is_empty() - } - _ => true, - } - } else { - false - } - } else { - false - } + if self.app.is_loading { + return false; + } + + let Some(season_details_modal) = self.app.data.sonarr_data.season_details_modal.as_ref() else { + return false; + }; + + let Some(episode_details_modal) = &season_details_modal.episode_details_modal else { + return false; + }; + + match self.active_sonarr_block { + ActiveSonarrBlock::EpisodeHistory => !episode_details_modal.episode_history.is_empty(), + ActiveSonarrBlock::ManualEpisodeSearch => !episode_details_modal.episode_releases.is_empty(), + _ => true, + } } fn handle_scroll_up(&mut self) {} @@ -370,4 +365,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/library/episode_details_handler_tests.rs b/src/handlers/sonarr_handlers/library/episode_details_handler_tests.rs index c8bba29..1de4098 100644 --- a/src/handlers/sonarr_handlers/library/episode_details_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/episode_details_handler_tests.rs @@ -1,10 +1,11 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::library::episode_details_handler::EpisodeDetailsHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::episode; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::modals::{EpisodeDetailsModal, SeasonDetailsModal}; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::servarr_data::sonarr::sonarr_data::{ @@ -103,7 +104,7 @@ mod tests { .episode_details_tabs .get_active_route() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); EpisodeDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None) .handle(); @@ -122,12 +123,13 @@ mod tests { .episode_details_tabs .get_active_route() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } } mod test_handle_submit { use super::*; + use crate::assert_navigation_popped; use crate::event::Key; use crate::models::stateful_table::StatefulTable; use crate::network::sonarr_network::SonarrEvent; @@ -148,10 +150,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EpisodeHistoryDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::EpisodeHistoryDetails.into()); } #[test] @@ -238,10 +237,10 @@ mod tests { EpisodeDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_pushed!(app, active_sonarr_block.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); } @@ -262,18 +261,15 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::ManualEpisodeSearch.into() - ); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { + assert_navigation_popped!(app, ActiveSonarrBlock::ManualEpisodeSearch.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { guid: String::new(), indexer_id: 0, episode_id: Some(0), ..SonarrReleaseDownloadBody::default() - })) + }) ); } @@ -293,11 +289,8 @@ mod tests { EpisodeDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EpisodeDetails.into() - ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::EpisodeDetails.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); } #[test] @@ -314,8 +307,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt.into() ); } @@ -344,8 +337,8 @@ mod tests { mod test_handle_esc { use super::*; + use crate::assert_navigation_popped; use crate::event::Key; - use pretty_assertions::assert_eq; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -364,10 +357,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EpisodeHistory.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::EpisodeHistory.into()); } #[rstest] @@ -389,10 +379,7 @@ mod tests { EpisodeDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EpisodeDetails.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::EpisodeDetails.into()); } #[rstest] @@ -412,23 +399,22 @@ mod tests { EpisodeDetailsHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeasonDetails.into() + assert_navigation_popped!(app, ActiveSonarrBlock::SeasonDetails.into()); + assert_none!( + app + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal ); - assert!(app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .is_none()); } } mod test_handle_key_char { use super::*; + use crate::assert_navigation_popped; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::network::sonarr_network::SonarrEvent; use pretty_assertions::assert_eq; @@ -455,8 +441,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveSonarrBlock::AutomaticallySearchEpisodePrompt.into() ); } @@ -509,7 +495,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); + assert_navigation_pushed!(app, active_sonarr_block.into()); assert!(app.is_routing); } @@ -574,10 +560,10 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::TriggerAutomaticEpisodeSearch(1)) + assert_navigation_popped!(app, active_sonarr_block.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::TriggerAutomaticEpisodeSearch(1) ); } @@ -598,18 +584,15 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::ManualEpisodeSearch.into() - ); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { + assert_navigation_popped!(app, ActiveSonarrBlock::ManualEpisodeSearch.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { guid: String::new(), indexer_id: 0, episode_id: Some(0), ..SonarrReleaseDownloadBody::default() - })) + }) ); } } diff --git a/src/handlers/sonarr_handlers/library/library_handler_tests.rs b/src/handlers/sonarr_handlers/library/library_handler_tests.rs index d09fd6a..712168b 100644 --- a/src/handlers/sonarr_handlers/library/library_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/library_handler_tests.rs @@ -5,14 +5,17 @@ mod tests { use std::cmp::Ordering; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::sonarr_handlers::library::{series_sorting_options, LibraryHandler}; - use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::series; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::library::{LibraryHandler, series_sorting_options}; + use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::series; use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, ADD_SERIES_BLOCKS, DELETE_SERIES_BLOCKS, EDIT_SERIES_BLOCKS, + ADD_SERIES_BLOCKS, ActiveSonarrBlock, DELETE_SERIES_BLOCKS, EDIT_SERIES_BLOCKS, EPISODE_DETAILS_BLOCKS, LIBRARY_BLOCKS, SEASON_DETAILS_BLOCKS, SERIES_DETAILS_BLOCKS, }; use crate::models::sonarr_models::{Series, SeriesStatistics, SeriesStatus, SeriesType}; @@ -71,6 +74,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_series_tab_left(#[values(true, false)] is_ready: bool) { @@ -90,7 +94,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::System.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::System.into()); } #[rstest] @@ -111,7 +115,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Downloads.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Downloads.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Downloads.into()); } #[rstest] @@ -144,9 +148,9 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::network::sonarr_network::SonarrEvent; + use pretty_assertions::assert_eq; use super::*; @@ -163,10 +167,7 @@ mod tests { LibraryHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::Series, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SeriesDetails.into()); } #[test] @@ -206,11 +207,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::UpdateAllSeries) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::UpdateAllSeries ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); } #[test] @@ -233,17 +234,17 @@ mod tests { .handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -262,7 +263,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); assert!(!app.data.sonarr_data.prompt_confirm); } @@ -277,8 +278,8 @@ mod tests { LibraryHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::Series, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); + assert_is_empty!(app.error.text); } } @@ -287,12 +288,12 @@ mod tests { use serde_json::Number; use strum::IntoEnumIterator; - use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::servarr_data::sonarr::sonarr_data::SonarrData; + use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::sonarr_models::SeriesType; use crate::network::sonarr_network::SonarrEvent; - use crate::test_edit_series_key; + use crate::{assert_navigation_popped, test_edit_series_key}; use super::*; @@ -313,12 +314,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddSeriesSearchInput.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::AddSeriesSearchInput.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.sonarr_data.add_series_search.is_some()); + assert_modal_present!(app.data.sonarr_data.add_series_search); } #[test] @@ -342,7 +340,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(app.data.sonarr_data.add_series_search.is_none()); + assert_modal_absent!(app.data.sonarr_data.add_series_search); } #[test] @@ -374,7 +372,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); - assert!(app.data.sonarr_data.edit_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_series_modal); } #[test] @@ -395,9 +393,9 @@ mod tests { assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); assert!(app.data.sonarr_data.prompt_confirm); assert!(app.is_routing); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::ToggleSeriesMonitoring(0)) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::ToggleSeriesMonitoring(0) ); } @@ -418,7 +416,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); assert!(!app.data.sonarr_data.prompt_confirm); - assert!(app.data.sonarr_data.prompt_confirm_action.is_none()); + assert_modal_absent!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.is_routing); } @@ -439,10 +437,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::UpdateAllSeriesPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::UpdateAllSeriesPrompt.into()); } #[test] @@ -485,7 +480,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Series.into()); assert!(app.should_refresh); } @@ -532,11 +527,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::UpdateAllSeries) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::UpdateAllSeries ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::Series.into()); } } diff --git a/src/handlers/sonarr_handlers/library/mod.rs b/src/handlers/sonarr_handlers/library/mod.rs index 5ab3a6f..dc60579 100644 --- a/src/handlers/sonarr_handlers/library/mod.rs +++ b/src/handlers/sonarr_handlers/library/mod.rs @@ -6,17 +6,16 @@ use edit_series_handler::EditSeriesHandler; use crate::{ app::App, event::Key, - handle_table_events, - handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}, + handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}, matches_key, models::{ + BlockSelectionState, HorizontallyScrollableText, servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, DELETE_SERIES_SELECTION_BLOCKS, EDIT_SERIES_SELECTION_BLOCKS, LIBRARY_BLOCKS, }, sonarr_models::Series, stateful_table::SortOption, - BlockSelectionState, HorizontallyScrollableText, }, network::sonarr_network::SonarrEvent, }; @@ -25,7 +24,7 @@ use super::handle_change_tab_left_right_keys; use crate::handlers::sonarr_handlers::library::episode_details_handler::EpisodeDetailsHandler; use crate::handlers::sonarr_handlers::library::season_details_handler::SeasonDetailsHandler; use crate::handlers::sonarr_handlers::library::series_details_handler::SeriesDetailsHandler; -use crate::handlers::table_handler::TableHandlingConfig; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; mod add_series_handler; mod delete_series_handler; @@ -45,7 +44,6 @@ pub(super) struct LibraryHandler<'a, 'b> { } impl LibraryHandler<'_, '_> { - handle_table_events!(self, series, self.app.data.sonarr_data.series, Series); fn extract_series_id(&self) -> i64 { self.app.data.sonarr_data.series.current_selection().id } @@ -55,7 +53,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, ' fn handle(&mut self) { let series_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::Series.into()) .sorting_block(ActiveSonarrBlock::SeriesSortPrompt.into()) - .sort_by_fn(|a: &Series, b: &Series| a.id.cmp(&b.id)) .sort_options(series_sorting_options()) .searching_block(ActiveSonarrBlock::SearchSeries.into()) .search_error_block(ActiveSonarrBlock::SearchSeriesError.into()) @@ -64,7 +61,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, ' .filter_error_block(ActiveSonarrBlock::FilterSeriesError.into()) .filter_field_fn(|series| &series.title.text); - if !self.handle_series_table_events(series_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.series, + series_table_handling_config, + ) { match self.active_sonarr_block { _ if AddSeriesHandler::accepts(self.active_sonarr_block) => { AddSeriesHandler::new(self.key, self.app, self.active_sonarr_block, self.context) @@ -239,6 +240,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, ' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } fn series_sorting_options() -> Vec> { diff --git a/src/handlers/sonarr_handlers/library/season_details_handler.rs b/src/handlers/sonarr_handlers/library/season_details_handler.rs index eae579c..193c3ff 100644 --- a/src/handlers/sonarr_handlers/library/season_details_handler.rs +++ b/src/handlers/sonarr_handlers/library/season_details_handler.rs @@ -1,8 +1,9 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::history::history_sorting_options; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::matches_key; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SEASON_DETAILS_BLOCKS}; use crate::models::servarr_models::Language; use crate::models::sonarr_models::{ @@ -10,7 +11,6 @@ use crate::models::sonarr_models::{ }; use crate::models::stateful_table::SortOption; use crate::network::sonarr_network::SonarrEvent; -use crate::{handle_table_events, matches_key}; use serde_json::Number; #[cfg(test)] @@ -25,46 +25,6 @@ pub(super) struct SeasonDetailsHandler<'a, 'b> { } impl SeasonDetailsHandler<'_, '_> { - handle_table_events!( - self, - episodes, - self - .app - .data - .sonarr_data - .season_details_modal - .as_mut() - .expect("Season details modal is undefined") - .episodes, - Episode - ); - handle_table_events!( - self, - season_history, - self - .app - .data - .sonarr_data - .season_details_modal - .as_mut() - .expect("Season details modal is undefined") - .season_history, - SonarrHistoryItem - ); - handle_table_events!( - self, - season_releases, - self - .app - .data - .sonarr_data - .season_details_modal - .as_mut() - .expect("Season details modal is undefined") - .season_releases, - SonarrRelease - ); - fn extract_episode_file_id(&self) -> i64 { self .app @@ -115,7 +75,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler TableHandlingConfig::new(ActiveSonarrBlock::SeasonHistory.into()) .sorting_block(ActiveSonarrBlock::SeasonHistorySortPrompt.into()) .sort_options(history_sorting_options()) - .sort_by_fn(|a: &SonarrHistoryItem, b: &SonarrHistoryItem| a.id.cmp(&b.id)) .searching_block(ActiveSonarrBlock::SearchSeasonHistory.into()) .search_error_block(ActiveSonarrBlock::SearchSeasonHistoryError.into()) .search_field_fn(|history_item: &SonarrHistoryItem| &history_item.source_title.text) @@ -127,10 +86,43 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler .sorting_block(ActiveSonarrBlock::ManualSeasonSearchSortPrompt.into()) .sort_options(releases_sorting_options()); - if !self.handle_episodes_table_events(episodes_table_handling_config) - && !self.handle_season_history_table_events(season_history_table_handling_config) - && !self.handle_season_releases_table_events(season_releases_table_handling_config) - { + if !handle_table( + self, + |app| { + &mut app + .data + .sonarr_data + .season_details_modal + .as_mut() + .expect("Season details modal is undefined") + .episodes + }, + episodes_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .sonarr_data + .season_details_modal + .as_mut() + .expect("Season details modal is undefined") + .season_history + }, + season_history_table_handling_config, + ) && !handle_table( + self, + |app| { + &mut app + .data + .sonarr_data + .season_details_modal + .as_mut() + .expect("Season details modal is undefined") + .season_releases + }, + season_releases_table_handling_config, + ) { self.handle_key_event(); } } @@ -162,17 +154,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler } fn is_ready(&self) -> bool { - !self.app.is_loading - && if let Some(season_details_modal) = &self.app.data.sonarr_data.season_details_modal { - match self.active_sonarr_block { - ActiveSonarrBlock::SeasonDetails => !season_details_modal.episodes.is_empty(), - ActiveSonarrBlock::SeasonHistory => !season_details_modal.season_history.is_empty(), - ActiveSonarrBlock::ManualSeasonSearch => !season_details_modal.season_releases.is_empty(), - _ => true, - } - } else { - false - } + if self.app.is_loading { + return false; + } + + let Some(season_details_modal) = &self.app.data.sonarr_data.season_details_modal else { + return false; + }; + + match self.active_sonarr_block { + ActiveSonarrBlock::SeasonDetails => !season_details_modal.episodes.is_empty(), + ActiveSonarrBlock::SeasonHistory => !season_details_modal.season_history.is_empty(), + ActiveSonarrBlock::ManualSeasonSearch => !season_details_modal.season_releases.is_empty(), + _ => true, + } } fn handle_scroll_up(&mut self) {} @@ -458,10 +453,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } -pub(in crate::handlers::sonarr_handlers::library) fn releases_sorting_options( -) -> Vec> { +pub(in crate::handlers::sonarr_handlers::library) fn releases_sorting_options() +-> Vec> { vec![ SortOption { name: "Source", diff --git a/src/handlers/sonarr_handlers/library/season_details_handler_tests.rs b/src/handlers/sonarr_handlers/library/season_details_handler_tests.rs index 3318669..35b4c70 100644 --- a/src/handlers/sonarr_handlers/library/season_details_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/season_details_handler_tests.rs @@ -1,12 +1,15 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::library::season_details_handler::{ - releases_sorting_options, SeasonDetailsHandler, + SeasonDetailsHandler, releases_sorting_options, }; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::episode; - use crate::handlers::KeyEventHandler; + use crate::models::HorizontallyScrollableText; use crate::models::servarr_data::sonarr::modals::SeasonDetailsModal; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::servarr_data::sonarr::sonarr_data::{ @@ -14,7 +17,6 @@ mod tests { }; use crate::models::servarr_models::{Language, Quality, QualityWrapper}; use crate::models::sonarr_models::{SonarrRelease, SonarrReleaseDownloadBody}; - use crate::models::HorizontallyScrollableText; use pretty_assertions::{assert_eq, assert_str_eq}; use rstest::rstest; use serde_json::Number; @@ -37,10 +39,7 @@ mod tests { SeasonDetailsHandler::new(DELETE_KEY, &mut app, ActiveSonarrBlock::SeasonDetails, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::DeleteEpisodeFilePrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::DeleteEpisodeFilePrompt.into()); } #[test] @@ -139,7 +138,7 @@ mod tests { .season_details_tabs .get_active_route() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); SeasonDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle(); @@ -154,12 +153,13 @@ mod tests { .season_details_tabs .get_active_route() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } } mod test_handle_submit { use super::*; + use crate::assert_navigation_popped; use crate::event::Key; use crate::models::stateful_table::StatefulTable; use crate::network::sonarr_network::SonarrEvent; @@ -176,10 +176,7 @@ mod tests { SeasonDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::SeasonDetails, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::EpisodeDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::EpisodeDetails.into()); } #[test] @@ -227,10 +224,7 @@ mod tests { SeasonDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::SeasonHistory, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeasonHistoryDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SeasonHistoryDetails.into()); } #[test] @@ -295,10 +289,10 @@ mod tests { SeasonDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_popped!(app, active_sonarr_block.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); } @@ -319,19 +313,16 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::ManualSeasonSearch.into() - ); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { + assert_navigation_popped!(app, ActiveSonarrBlock::ManualSeasonSearch.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { guid: String::new(), indexer_id: 0, series_id: Some(0), season_number: Some(0), ..SonarrReleaseDownloadBody::default() - })) + }) ); } @@ -352,11 +343,8 @@ mod tests { SeasonDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeasonDetails.into() - ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::SeasonDetails.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); } #[test] @@ -373,8 +361,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt.into() ); } @@ -403,6 +391,7 @@ mod tests { mod test_handle_esc { use super::*; + use crate::assert_navigation_popped; use crate::event::Key; use crate::models::sonarr_models::SonarrHistoryItem; use crate::models::stateful_table::StatefulTable; @@ -426,10 +415,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeasonHistory.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::SeasonHistory.into()); } #[rstest] @@ -452,10 +438,7 @@ mod tests { SeasonDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeasonDetails.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::SeasonDetails.into()); } #[test] @@ -485,33 +468,36 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::SeasonHistory.into() ); - assert!(app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .filter - .is_none()); - assert!(app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .filtered_items - .is_none()); - assert!(app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .filtered_state - .is_none()); + assert_none!( + app + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .filter + ); + assert_none!( + app + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .filtered_items + ); + assert_none!( + app + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .filtered_state + ); } #[rstest] @@ -530,16 +516,14 @@ mod tests { SeasonDetailsHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesDetails.into() - ); - assert!(app.data.sonarr_data.season_details_modal.is_none()); + assert_navigation_popped!(app, ActiveSonarrBlock::SeriesDetails.into()); + assert_modal_absent!(app.data.sonarr_data.season_details_modal); } } mod test_handle_key_char { use super::*; + use crate::assert_navigation_popped; use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::network::sonarr_network::SonarrEvent; use pretty_assertions::assert_eq; @@ -573,9 +557,9 @@ mod tests { ); assert!(app.data.sonarr_data.prompt_confirm); assert!(app.is_routing); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::ToggleEpisodeMonitoring(1)) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::ToggleEpisodeMonitoring(1) ); } @@ -599,7 +583,7 @@ mod tests { ActiveSonarrBlock::SeasonDetails.into() ); assert!(!app.data.sonarr_data.prompt_confirm); - assert!(app.data.sonarr_data.prompt_confirm_action.is_none()); + assert_modal_absent!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.is_routing); } @@ -624,8 +608,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveSonarrBlock::AutomaticallySearchSeasonPrompt.into() ); } @@ -676,7 +660,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); + assert_navigation_pushed!(app, active_sonarr_block.into()); assert!(app.is_routing); } @@ -737,10 +721,10 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_popped!(app, active_sonarr_block.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); } @@ -761,19 +745,16 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::ManualSeasonSearch.into() - ); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { + assert_navigation_popped!(app, ActiveSonarrBlock::ManualSeasonSearch.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DownloadRelease(SonarrReleaseDownloadBody { guid: String::new(), indexer_id: 0, series_id: Some(0), season_number: Some(0), ..SonarrReleaseDownloadBody::default() - })) + }) ); } } diff --git a/src/handlers/sonarr_handlers/library/series_details_handler.rs b/src/handlers/sonarr_handlers/library/series_details_handler.rs index a87a419..ee60e3e 100644 --- a/src/handlers/sonarr_handlers/library/series_details_handler.rs +++ b/src/handlers/sonarr_handlers/library/series_details_handler.rs @@ -1,15 +1,15 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::history::history_sorting_options; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; +use crate::matches_key; +use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EDIT_SERIES_SELECTION_BLOCKS, SERIES_DETAILS_BLOCKS, }; use crate::models::sonarr_models::{Season, SonarrHistoryItem}; -use crate::models::BlockSelectionState; use crate::network::sonarr_network::SonarrEvent; -use crate::{handle_table_events, matches_key}; #[cfg(test)] #[path = "series_details_handler_tests.rs"] @@ -23,20 +23,6 @@ pub(super) struct SeriesDetailsHandler<'a, 'b> { } impl SeriesDetailsHandler<'_, '_> { - handle_table_events!(self, season, self.app.data.sonarr_data.seasons, Season); - handle_table_events!( - self, - series_history, - self - .app - .data - .sonarr_data - .series_history - .as_mut() - .expect("Series history is undefined"), - SonarrHistoryItem - ); - fn extract_series_id_season_number_tuple(&self) -> (i64, i64) { let series_id = self.app.data.sonarr_data.series.current_selection().id; let season_number = self @@ -71,7 +57,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler TableHandlingConfig::new(ActiveSonarrBlock::SeriesHistory.into()) .sorting_block(ActiveSonarrBlock::SeriesHistorySortPrompt.into()) .sort_options(history_sorting_options()) - .sort_by_fn(|a: &SonarrHistoryItem, b: &SonarrHistoryItem| a.id.cmp(&b.id)) .searching_block(ActiveSonarrBlock::SearchSeriesHistory.into()) .search_error_block(ActiveSonarrBlock::SearchSeriesHistoryError.into()) .search_field_fn(|history_item: &SonarrHistoryItem| &history_item.source_title.text) @@ -79,9 +64,22 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler .filter_error_block(ActiveSonarrBlock::FilterSeriesHistoryError.into()) .filter_field_fn(|history_item: &SonarrHistoryItem| &history_item.source_title.text); - if !self.handle_season_table_events(season_table_handling_config) - && !self.handle_series_history_table_events(series_history_table_handling_config) - { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.seasons, + season_table_handling_config, + ) && !handle_table( + self, + |app| { + app + .data + .sonarr_data + .series_history + .as_mut() + .expect("Series history is undefined") + }, + series_history_table_handling_config, + ) { self.handle_key_event(); } } @@ -339,4 +337,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs b/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs index 9d1ccda..048f512 100644 --- a/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs @@ -1,11 +1,13 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::library::series_details_handler::SeriesDetailsHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::{season, series}; - use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, SERIES_DETAILS_BLOCKS, }; @@ -69,7 +71,7 @@ mod tests { app.get_current_route(), app.data.sonarr_data.series_info_tabs.get_active_route() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); SeriesDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle(); @@ -77,15 +79,15 @@ mod tests { app.get_current_route(), app.data.sonarr_data.series_info_tabs.get_active_route() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } } mod test_handle_submit { use pretty_assertions::assert_eq; - use crate::extended_stateful_iterable_vec; use crate::network::sonarr_network::SonarrEvent; + use crate::{assert_navigation_popped, extended_stateful_iterable_vec}; use super::*; @@ -103,10 +105,7 @@ mod tests { SeriesDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::SeriesDetails, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeasonDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SeasonDetails.into()); } #[test] @@ -145,10 +144,7 @@ mod tests { SeriesDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::SeriesHistory, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesHistoryDetails.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SeriesHistoryDetails.into()); } #[test] @@ -200,13 +196,10 @@ mod tests { SeriesDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesDetails.into() - ); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_popped!(app, ActiveSonarrBlock::SeriesDetails.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); } @@ -225,16 +218,14 @@ mod tests { SeriesDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesDetails.into() - ); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); + assert_navigation_popped!(app, ActiveSonarrBlock::SeriesDetails.into()); + assert_none!(app.data.sonarr_data.prompt_confirm_action); } } mod test_handle_esc { use super::*; + use crate::assert_navigation_popped; use crate::models::stateful_table::StatefulTable; use pretty_assertions::assert_eq; use ratatui::widgets::TableState; @@ -255,10 +246,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesHistory.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::SeriesHistory.into()); } #[rstest] @@ -279,10 +267,7 @@ mod tests { SeriesDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SeriesDetails.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::SeriesDetails.into()); } #[test] @@ -304,40 +289,35 @@ mod tests { app.get_current_route(), ActiveSonarrBlock::SeriesHistory.into() ); - assert!(app - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .filter - .is_none()); - assert!(app - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .filtered_items - .is_none()); - assert!(app - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .filtered_state - .is_none()); + assert_none!(app.data.sonarr_data.series_history.as_ref().unwrap().filter); + assert_none!( + app + .data + .sonarr_data + .series_history + .as_ref() + .unwrap() + .filtered_items + ); + assert_none!( + app + .data + .sonarr_data + .series_history + .as_ref() + .unwrap() + .filtered_state + ); } } mod test_handle_key_char { use super::*; - use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::servarr_data::sonarr::sonarr_data::SonarrData; + use crate::models::servarr_data::sonarr::sonarr_data::sonarr_test_utils::utils::create_test_sonarr_data; use crate::models::sonarr_models::{Series, SeriesType}; use crate::network::sonarr_network::SonarrEvent; - use crate::test_edit_series_key; + use crate::{assert_navigation_popped, test_edit_series_key}; use pretty_assertions::{assert_eq, assert_str_eq}; use serde_json::Number; use strum::IntoEnumIterator; @@ -372,7 +352,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), active_sonarr_block.into()); - assert!(app.data.sonarr_data.edit_series_modal.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_series_modal); } #[test] @@ -396,9 +376,9 @@ mod tests { ); assert!(app.data.sonarr_data.prompt_confirm); assert!(app.is_routing); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::ToggleSeasonMonitoring((0, 0))) + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::ToggleSeasonMonitoring((0, 0)) ); } @@ -422,7 +402,7 @@ mod tests { ActiveSonarrBlock::SeriesDetails.into() ); assert!(!app.data.sonarr_data.prompt_confirm); - assert!(app.data.sonarr_data.prompt_confirm_action.is_none()); + assert_modal_absent!(app.data.sonarr_data.prompt_confirm_action); assert!(!app.is_routing); } @@ -445,8 +425,8 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), + assert_navigation_pushed!( + app, ActiveSonarrBlock::AutomaticallySearchSeriesPrompt.into() ); } @@ -490,10 +470,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::UpdateAndScanSeriesPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::UpdateAndScanSeriesPrompt.into()); } #[rstest] @@ -536,7 +513,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); + assert_navigation_pushed!(app, active_sonarr_block.into()); assert!(app.is_routing); } @@ -592,10 +569,10 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(expected_action) + assert_navigation_popped!(app, active_sonarr_block.into()); + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &expected_action ); } } diff --git a/src/handlers/sonarr_handlers/mod.rs b/src/handlers/sonarr_handlers/mod.rs index 2a05c69..033392e 100644 --- a/src/handlers/sonarr_handlers/mod.rs +++ b/src/handlers/sonarr_handlers/mod.rs @@ -110,6 +110,14 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SonarrHandler<'a, 'b fn handle_esc(&mut self) {} fn handle_char_key_event(&mut self) {} + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) { diff --git a/src/handlers/sonarr_handlers/root_folders/mod.rs b/src/handlers/sonarr_handlers/root_folders/mod.rs index 3d27a59..04da09c 100644 --- a/src/handlers/sonarr_handlers/root_folders/mod.rs +++ b/src/handlers/sonarr_handlers/root_folders/mod.rs @@ -1,15 +1,13 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; -use crate::handlers::table_handler::TableHandlingConfig; -use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler}; -use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS}; -use crate::models::servarr_models::{AddRootFolderBody, RootFolder}; +use crate::handlers::table_handler::{TableHandlingConfig, handle_table}; +use crate::handlers::{KeyEventHandler, handle_clear_errors, handle_prompt_toggle}; use crate::models::HorizontallyScrollableText; +use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS}; +use crate::models::servarr_models::AddRootFolderBody; use crate::network::sonarr_network::SonarrEvent; -use crate::{ - handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, -}; +use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key}; #[cfg(test)] #[path = "root_folders_handler_tests.rs"] @@ -23,13 +21,6 @@ pub(super) struct RootFoldersHandler<'a, 'b> { } impl RootFoldersHandler<'_, '_> { - handle_table_events!( - self, - root_folders, - self.app.data.sonarr_data.root_folders, - RootFolder - ); - fn build_add_root_folder_body(&mut self) -> AddRootFolderBody { let root_folder = self .app @@ -58,7 +49,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<' let root_folders_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::RootFolders.into()); - if !self.handle_root_folders_table_events(root_folders_table_handling_config) { + if !handle_table( + self, + |app| &mut app.data.sonarr_data.root_folders, + root_folders_table_handling_config, + ) { self.handle_key_event(); } } @@ -229,4 +224,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<' _ => (), } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/root_folders/root_folders_handler_tests.rs b/src/handlers/sonarr_handlers/root_folders/root_folders_handler_tests.rs index aeb3c50..4710f67 100644 --- a/src/handlers/sonarr_handlers/root_folders/root_folders_handler_tests.rs +++ b/src/handlers/sonarr_handlers/root_folders/root_folders_handler_tests.rs @@ -4,15 +4,18 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; + use crate::handlers::KeyEventHandler; use crate::handlers::sonarr_handlers::root_folders::RootFoldersHandler; use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::root_folder; - use crate::handlers::KeyEventHandler; + use crate::models::HorizontallyScrollableText; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::servarr_models::{AddRootFolderBody, RootFolder}; - use crate::models::HorizontallyScrollableText; mod test_handle_home_end { use crate::models::servarr_models::RootFolder; @@ -94,10 +97,7 @@ mod tests { RootFoldersHandler::new(DELETE_KEY, &mut app, ActiveSonarrBlock::RootFolders, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::DeleteRootFolderPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::DeleteRootFolderPrompt.into()); } #[test] @@ -127,6 +127,7 @@ mod tests { use rstest::rstest; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_root_folders_tab_left(#[values(true, false)] is_ready: bool) { @@ -147,7 +148,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::History.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::History.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::History.into()); } #[rstest] @@ -169,7 +170,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Indexers.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Indexers.into()); } #[rstest] @@ -254,6 +255,7 @@ mod tests { use crate::network::sonarr_network::SonarrEvent; use super::*; + use crate::{assert_modal_absent, assert_navigation_popped}; const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key; @@ -288,11 +290,8 @@ mod tests { app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::AddRootFolder(expected_add_root_folder_body)) ); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); - assert!(app.data.sonarr_data.edit_root_folder.is_none()); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); + assert_modal_absent!(app.data.sonarr_data.edit_root_folder); } #[test] @@ -314,7 +313,7 @@ mod tests { assert!(!app.data.sonarr_data.prompt_confirm); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.sonarr_data.prompt_confirm_action.is_none()); + assert_modal_absent!(app.data.sonarr_data.prompt_confirm_action); assert_eq!( app.get_current_route(), ActiveSonarrBlock::AddRootFolderPrompt.into() @@ -342,14 +341,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DeleteRootFolder(1)) - ); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DeleteRootFolder(1) ); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); } #[test] @@ -372,17 +368,14 @@ mod tests { .handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); + assert_none!(app.data.sonarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); } } mod test_handle_esc { use super::*; - use pretty_assertions::assert_eq; + use crate::assert_navigation_popped; use rstest::rstest; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -402,10 +395,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); assert!(!app.data.sonarr_data.prompt_confirm); } @@ -425,12 +415,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); - assert!(app.data.sonarr_data.edit_root_folder.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_root_folder); assert!(!app.data.sonarr_data.prompt_confirm); assert!(!app.ignore_special_keys_for_textbox_input); } @@ -445,18 +432,15 @@ mod tests { RootFoldersHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::RootFolders, None).handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); + assert_is_empty!(app.error.text); } } mod test_handle_key_char { - use pretty_assertions::{assert_eq, assert_str_eq}; - + use crate::assert_navigation_popped; use crate::network::sonarr_network::SonarrEvent; + use pretty_assertions::{assert_eq, assert_str_eq}; use super::*; @@ -478,12 +462,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::AddRootFolderPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::AddRootFolderPrompt.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.sonarr_data.edit_root_folder.is_some()); + assert_modal_present!(app.data.sonarr_data.edit_root_folder); } #[test] @@ -510,7 +491,7 @@ mod tests { ActiveSonarrBlock::RootFolders.into() ); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(app.data.sonarr_data.edit_root_folder.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_root_folder); } #[test] @@ -531,10 +512,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::RootFolders.into()); assert!(app.should_refresh); } @@ -634,14 +612,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::DeleteRootFolder(1)) - ); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::RootFolders.into() + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::DeleteRootFolder(1) ); + assert_navigation_popped!(app, ActiveSonarrBlock::RootFolders.into()); } } @@ -712,7 +687,7 @@ mod tests { .build_add_root_folder_body(); assert_eq!(root_folder, expected_add_root_folder_body); - assert!(app.data.sonarr_data.edit_root_folder.is_none()); + assert_modal_absent!(app.data.sonarr_data.edit_root_folder); } #[test] diff --git a/src/handlers/sonarr_handlers/sonarr_handler_test_utils.rs b/src/handlers/sonarr_handlers/sonarr_handler_test_utils.rs index 0790d59..08cefc2 100644 --- a/src/handlers/sonarr_handlers/sonarr_handler_test_utils.rs +++ b/src/handlers/sonarr_handlers/sonarr_handler_test_utils.rs @@ -1,6 +1,7 @@ #[cfg(test)] #[macro_use] pub(in crate::handlers::sonarr_handlers) mod utils { + use crate::models::HorizontallyScrollableText; use crate::models::servarr_models::{ Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder, }; @@ -9,9 +10,8 @@ pub(in crate::handlers::sonarr_handlers) mod utils { Episode, EpisodeFile, IndexerSettings, MediaInfo, Rating, Season, SeasonStatistics, Series, SeriesStatistics, SeriesStatus, SeriesType, }; - use crate::models::HorizontallyScrollableText; use chrono::DateTime; - use serde_json::{json, Number}; + use serde_json::{Number, json}; #[macro_export] macro_rules! test_edit_series_key { diff --git a/src/handlers/sonarr_handlers/sonarr_handler_tests.rs b/src/handlers/sonarr_handlers/sonarr_handler_tests.rs index 8dd160d..8cc007e 100644 --- a/src/handlers/sonarr_handlers/sonarr_handler_tests.rs +++ b/src/handlers/sonarr_handlers/sonarr_handler_tests.rs @@ -1,10 +1,11 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; - use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; - use crate::handlers::sonarr_handlers::SonarrHandler; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::SonarrHandler; + use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::test_handler_delegation; use pretty_assertions::assert_eq; @@ -33,7 +34,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), left_block.into() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); app.data.sonarr_data.main_tabs.set_index(index); @@ -43,7 +44,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), right_block.into() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } #[rstest] @@ -68,7 +69,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), left_block.into() ); - assert_eq!(app.get_current_route(), left_block.into()); + assert_navigation_pushed!(app, left_block.into()); app.data.sonarr_data.main_tabs.set_index(index); @@ -78,7 +79,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), right_block.into() ); - assert_eq!(app.get_current_route(), right_block.into()); + assert_navigation_pushed!(app, right_block.into()); } #[rstest] diff --git a/src/handlers/sonarr_handlers/system/mod.rs b/src/handlers/sonarr_handlers/system/mod.rs index f792f77..9c70ac4 100644 --- a/src/handlers/sonarr_handlers/system/mod.rs +++ b/src/handlers/sonarr_handlers/system/mod.rs @@ -2,10 +2,10 @@ use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys; use crate::handlers::sonarr_handlers::system::system_details_handler::SystemDetailsHandler; -use crate::handlers::{handle_clear_errors, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_clear_errors}; use crate::matches_key; -use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::Scrollable; +use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; mod system_details_handler; @@ -124,4 +124,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemHandler<'a, 'b } } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/system/system_details_handler.rs b/src/handlers/sonarr_handlers/system/system_details_handler.rs index 7615581..57879e2 100644 --- a/src/handlers/sonarr_handlers/system/system_details_handler.rs +++ b/src/handlers/sonarr_handlers/system/system_details_handler.rs @@ -1,11 +1,11 @@ use crate::app::App; use crate::event::Key; -use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::handlers::{KeyEventHandler, handle_prompt_toggle}; use crate::matches_key; +use crate::models::Scrollable; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS}; use crate::models::sonarr_models::SonarrTaskName; use crate::models::stateful_list::StatefulList; -use crate::models::Scrollable; use crate::network::sonarr_network::SonarrEvent; #[cfg(test)] @@ -196,4 +196,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler self.app.pop_navigation_stack(); } } + + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } diff --git a/src/handlers/sonarr_handlers/system/system_details_handler_tests.rs b/src/handlers/sonarr_handlers/system/system_details_handler_tests.rs index 57118c1..a7031da 100644 --- a/src/handlers/sonarr_handlers/system/system_details_handler_tests.rs +++ b/src/handlers/sonarr_handlers/system/system_details_handler_tests.rs @@ -4,11 +4,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::sonarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::system::system_details_handler::SystemDetailsHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS, }; @@ -652,9 +653,9 @@ mod tests { } mod test_handle_submit { - use pretty_assertions::assert_eq; - + use crate::assert_navigation_popped; use crate::network::sonarr_network::SonarrEvent; + use pretty_assertions::assert_eq; use super::*; @@ -669,10 +670,7 @@ mod tests { SystemDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveSonarrBlock::SystemTasks, None) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemTaskStartConfirmPrompt.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SystemTaskStartConfirmPrompt.into()); } #[test] @@ -713,14 +711,11 @@ mod tests { .handle(); assert!(app.data.sonarr_data.prompt_confirm); - assert_eq!( - app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::StartTask(SonarrTaskName::default())) - ); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemTasks.into() + assert_some_eq_x!( + &app.data.sonarr_data.prompt_confirm_action, + &SonarrEvent::StartTask(SonarrTaskName::default()) ); + assert_navigation_popped!(app, ActiveSonarrBlock::SystemTasks.into()); } #[test] @@ -739,20 +734,17 @@ mod tests { .handle(); assert!(!app.data.sonarr_data.prompt_confirm); - assert_eq!(app.data.sonarr_data.prompt_confirm_action, None); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemTasks.into() - ); + assert_none!(app.data.sonarr_data.prompt_confirm_action); + assert_navigation_popped!(app, ActiveSonarrBlock::SystemTasks.into()); } } mod test_handle_esc { use crate::models::HorizontallyScrollableText; - use pretty_assertions::assert_eq; use rstest::rstest; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -775,8 +767,8 @@ mod tests { SystemDetailsHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::SystemLogs, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); - assert!(app.data.sonarr_data.log_details.items.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::System.into()); + assert_is_empty!(app.data.sonarr_data.log_details.items); } #[rstest] @@ -793,7 +785,7 @@ mod tests { SystemDetailsHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::SystemTasks, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::System.into()); } #[rstest] @@ -816,7 +808,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::System.into()); } #[rstest] @@ -828,7 +820,7 @@ mod tests { SystemDetailsHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::SystemUpdates, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); + assert_navigation_popped!(app, ActiveSonarrBlock::System.into()); } #[test] @@ -846,10 +838,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemTasks.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::SystemTasks.into()); assert!(!app.data.sonarr_data.prompt_confirm); } } @@ -861,6 +850,7 @@ mod tests { use crate::network::sonarr_network::SonarrEvent; use super::*; + use crate::{assert_navigation_popped, assert_navigation_pushed}; #[rstest] fn test_refresh_key( @@ -885,7 +875,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), active_sonarr_block.into()); + assert_navigation_pushed!(app, active_sonarr_block.into()); assert!(app.should_refresh); } @@ -943,10 +933,7 @@ mod tests { app.data.sonarr_data.prompt_confirm_action, Some(SonarrEvent::StartTask(SonarrTaskName::default())) ); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemTasks.into() - ); + assert_navigation_popped!(app, ActiveSonarrBlock::SystemTasks.into()); } } diff --git a/src/handlers/sonarr_handlers/system/system_handler_tests.rs b/src/handlers/sonarr_handlers/system/system_handler_tests.rs index 2678086..d9903f6 100644 --- a/src/handlers/sonarr_handlers/system/system_handler_tests.rs +++ b/src/handlers/sonarr_handlers/system/system_handler_tests.rs @@ -3,11 +3,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handlers::sonarr_handlers::system::SystemHandler; use crate::handlers::KeyEventHandler; + use crate::handlers::sonarr_handlers::system::SystemHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS, }; @@ -19,6 +20,7 @@ mod tests { use pretty_assertions::assert_eq; use super::*; + use crate::assert_navigation_pushed; #[rstest] fn test_system_tab_left(#[values(true, false)] is_ready: bool) { @@ -39,7 +41,7 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Indexers.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Indexers.into()); } #[rstest] @@ -61,14 +63,14 @@ mod tests { app.data.sonarr_data.main_tabs.get_active_route(), ActiveSonarrBlock::Series.into() ); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::Series.into()); } } mod test_handle_esc { - use pretty_assertions::assert_eq; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -82,8 +84,8 @@ mod tests { SystemHandler::new(ESC_KEY, &mut app, ActiveSonarrBlock::System, None).handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); - assert!(app.error.text.is_empty()); + assert_navigation_popped!(app, ActiveSonarrBlock::System.into()); + assert_is_empty!(app.error.text); } } @@ -121,10 +123,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemUpdates.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SystemUpdates.into()); } #[test] @@ -185,10 +184,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemQueuedEvents.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SystemQueuedEvents.into()); } #[test] @@ -249,7 +245,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); + assert_navigation_pushed!(app, ActiveSonarrBlock::System.into()); assert!(app.should_refresh); } @@ -313,10 +309,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemLogs.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SystemLogs.into()); assert_eq!( app.data.sonarr_data.log_details.items, app.data.sonarr_data.logs.items @@ -356,7 +349,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveSonarrBlock::System.into()); - assert!(app.data.sonarr_data.log_details.is_empty()); + assert_is_empty!(app.data.sonarr_data.log_details); } #[test] @@ -386,10 +379,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveSonarrBlock::SystemTasks.into() - ); + assert_navigation_pushed!(app, ActiveSonarrBlock::SystemTasks.into()); } #[test] diff --git a/src/handlers/table_handler.rs b/src/handlers/table_handler.rs index fc7ae1a..028d6fb 100644 --- a/src/handlers/table_handler.rs +++ b/src/handlers/table_handler.rs @@ -1,8 +1,12 @@ -use crate::models::stateful_table::SortOption; -use crate::models::Route; +use crate::app::App; +use crate::app::key_binding::DEFAULT_KEYBINDINGS; +use crate::event::Key; +use crate::matches_key; +use crate::models::stateful_table::{SortOption, StatefulTable}; +use crate::models::{HorizontallyScrollableText, Paginated, Route, Scrollable}; use derive_setters::Setters; -use std::cmp::Ordering; use std::fmt::Debug; +use std::marker::PhantomData; #[cfg(test)] #[path = "table_handler_tests.rs"] @@ -18,8 +22,6 @@ where #[setters(strip_option)] pub sort_options: Option>>, #[setters(strip_option)] - pub sort_by_fn: Option Ordering>, - #[setters(strip_option)] pub searching_block: Option, #[setters(strip_option)] pub search_error_block: Option, @@ -35,409 +37,649 @@ where pub table_block: Route, } -#[macro_export] -macro_rules! handle_table_events { - ($self:expr, $name:ty, $table:expr, $row:ident) => { - paste::paste! { - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - if $self.is_ready() { - match $self.key { - _ if $crate::matches_key!(up, $self.key, $self.ignore_special_keys()) => $self.[](config), - _ if $crate::matches_key!(down, $self.key, $self.ignore_special_keys()) => $self.[](config), - _ if $crate::matches_key!(pg_up, $self.key, $self.ignore_special_keys()) => $self.[](config), - _ if $crate::matches_key!(pg_down, $self.key, $self.ignore_special_keys()) => $self.[](config), - _ if $crate::matches_key!(home, $self.key) => $self.[](config), - _ if $crate::matches_key!(end, $self.key) => $self.[](config), - _ if $crate::matches_key!(left, $self.key, $self.ignore_special_keys()) - || $crate::matches_key!(right, $self.key, $self.ignore_special_keys()) => - { - $self.[](config) - } - _ if $crate::matches_key!(submit, $self.key) => $self.[](config), - _ if $crate::matches_key!(esc, $self.key) => $self.[](config), - _ if config.searching_block.is_some() - && $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() => - { - $self.[]() - } - _ if config.filtering_block.is_some() - && $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() => - { - $self.[]() - } - _ if $crate::matches_key!(filter, $self.key) - && config.filtering_block.is_some() => $self.[](config), - _ if $crate::matches_key!(search, $self.key) - && config.searching_block.is_some() => $self.[](config), - _ if $crate::matches_key!(sort, $self.key) - && config.sorting_block.is_some() => $self.[](config), - _ => false, - } - } else { - false - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - use $crate::models::Scrollable; - - match $self.app.get_current_route() { - _ if config.table_block == $self.app.get_current_route() => { - $table.scroll_up(); - true - } - _ if config.sorting_block.is_some() - && $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() => - { - $table.sort.as_mut().unwrap().scroll_up(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - use $crate::models::Scrollable; - - match $self.app.get_current_route() { - _ if config.table_block == $self.app.get_current_route() => { - $table.scroll_down(); - true - } - _ if config.sorting_block.is_some() - && $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() => - { - $table - .sort - .as_mut() - .unwrap() - .scroll_down(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - use $crate::models::Paginated; - - match $self.app.get_current_route() { - _ if config.table_block == $self.app.get_current_route() => { - $table.page_down(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - use $crate::models::Paginated; - - match $self.app.get_current_route() { - _ if config.table_block == $self.app.get_current_route() => { - $table.page_up(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - use $crate::models::Scrollable; - - match $self.app.get_current_route() { - _ if config.table_block == $self.app.get_current_route() => { - $table.scroll_to_top(); - true - } - _ if config.sorting_block.is_some() - && $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() => - { - $table - .sort - .as_mut() - .unwrap() - .scroll_to_top(); - true - } - _ if config.searching_block.is_some() - && $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() => - { - $table - .search - .as_mut() - .unwrap() - .scroll_home(); - true - } - _ if config.filtering_block.is_some() - && $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() => - { - $table - .filter - .as_mut() - .unwrap() - .scroll_home(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - use $crate::models::Scrollable; - - match $self.app.get_current_route() { - _ if config.table_block == $self.app.get_current_route() => { - $table.scroll_to_bottom(); - true - } - _ if config.sorting_block.is_some() - && $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() => - { - $table - .sort - .as_mut() - .unwrap() - .scroll_to_bottom(); - true - } - _ if config.searching_block.is_some() - && $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() => - { - $table - .search - .as_mut() - .unwrap() - .reset_offset(); - true - } - _ if config.filtering_block.is_some() - && $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() => - { - $table - .filter - .as_mut() - .unwrap() - .reset_offset(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - match $self.app.get_current_route() { - _ if config.searching_block.is_some() - && $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() => - { - $crate::handle_text_box_left_right_keys!( - $self, - $self.key, - $table.search.as_mut().unwrap() - ); - true - } - _ if config.filtering_block.is_some() - && $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() => - { - $crate::handle_text_box_left_right_keys!( - $self, - $self.key, - $table.filter.as_mut().unwrap() - ); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - match $self.app.get_current_route() { - _ if config.sorting_block.is_some() - && $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() => - { - if let Some(sort_by_fn) = config.sort_by_fn { - $table.items.sort_by(sort_by_fn); - } - - $table.apply_sorting(); - $self.app.pop_navigation_stack(); - - true - } - _ if config.searching_block.is_some() - && $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() => - { - $self.app.pop_navigation_stack(); - $self.app.ignore_special_keys_for_textbox_input = false; - - if $table.search.is_some() { - let search_field_fn = config - .search_field_fn - .expect("Search field function is required"); - let has_match = $table.apply_search(search_field_fn); - - if !has_match { - $self.app.push_navigation_stack( - config - .search_error_block - .expect("Search error block is undefined"), - ); - } - } - - true - } - _ if config.filtering_block.is_some() - && $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() => - { - $self.app.pop_navigation_stack(); - $self.app.ignore_special_keys_for_textbox_input = false; - - if $table.filter.is_some() { - let filter_field_fn = config - .filter_field_fn - .expect("Search field function is required"); - let has_match = $table.apply_filter(filter_field_fn); - - if !has_match { - $self.app.push_navigation_stack( - config - .filter_error_block - .expect("Search error block is undefined"), - ); - } - } - - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - match $self.app.get_current_route() { - _ if config.sorting_block.is_some() - && $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() => - { - $self.app.pop_navigation_stack(); - true - } - _ if (config.searching_block.is_some() - && $self.app.get_current_route() == *config.searching_block.as_ref().unwrap()) - || (config.search_error_block.is_some() - && $self.app.get_current_route() == *config.search_error_block.as_ref().unwrap()) => - { - $self.app.pop_navigation_stack(); - $table.reset_search(); - $self.app.ignore_special_keys_for_textbox_input = false; - true - } - _ if (config.filtering_block.is_some() - && $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap()) - || (config.filter_error_block.is_some() - && $self.app.get_current_route() == *config.filter_error_block.as_ref().unwrap()) => - { - $self.app.pop_navigation_stack(); - $table.reset_filter(); - $self.app.ignore_special_keys_for_textbox_input = false; - true - } - _ if config.table_block == $self.app.get_current_route() - && $table.filtered_items.is_some() => - { - $table.reset_filter(); - true - } - _ => false, - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - if matches!($self.app.get_current_route(), _ if config.table_block == $self.app.get_current_route()) { - $self - .app - .push_navigation_stack(config.filtering_block.expect("Filtering block is undefined").into()); - $table.reset_filter(); - $table.filter = Some($crate::models::HorizontallyScrollableText::default()); - $self.app.ignore_special_keys_for_textbox_input = true; - - true - } else { - false - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - if matches!($self.app.get_current_route(), _ if config.table_block == $self.app.get_current_route()) { - $self - .app - .push_navigation_stack(config.searching_block.expect("Searching block is undefined")); - $table.search = Some($crate::models::HorizontallyScrollableText::default()); - $self.app.ignore_special_keys_for_textbox_input = true; - - true - } else { - false - } - } - - fn [](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool { - if matches!($self.app.get_current_route(), _ if config.table_block == $self.app.get_current_route()) { - $table.sorting( - config - .sort_options - .as_ref() - .expect("Sort options are undefined") - .clone(), - ); - $self - .app - .push_navigation_stack(config.sorting_block.expect("Sorting block is undefined")); - true - } else { - false - } - } - - fn [](&mut $self) -> bool { - $crate::handle_text_box_keys!( - $self, - $self.key, - $table.search.as_mut().unwrap() - ); - true - } - - fn [](&mut $self) -> bool { - $crate::handle_text_box_keys!( - $self, - $self.key, - $table.filter.as_mut().unwrap() - ); - true - } - } - }; -} - impl TableHandlingConfig where T: Clone + PartialEq + Eq + Debug + Default, { pub fn new(table_block: Route) -> Self { - TableHandlingConfig { + Self { + table_block, sorting_block: None, sort_options: None, - sort_by_fn: None, searching_block: None, search_error_block: None, search_field_fn: None, filtering_block: None, filter_error_block: None, filter_field_fn: None, - table_block, } } } + +pub trait TableEventHandler<'b, T> +where + T: Clone + PartialEq + Eq + Debug + Default, +{ + /// Returns a mutable reference to the table being managed. + fn table_mut(&mut self) -> &mut StatefulTable; + + /// Returns the configuration for this table's event handling. + fn config(&self) -> &TableHandlingConfig; + + /// Returns whether the handler is ready to process events. + /// + /// Typically, checks if data is loaded and the table is not empty. + fn is_ready(&self) -> bool; + + /// Returns the current navigation route. + fn current_route(&self) -> Route; + + /// Returns whether special keys should be ignored for textbox input. + fn ignore_special_keys(&self) -> bool; + + /// Returns a mutable reference to the application state. + fn app_mut(&mut self) -> &mut App<'b>; + + /// Returns the current key event being processed. + fn key(&self) -> Key; + + /// Main entry point for table event handling. + /// + /// Returns `true` if the event was handled by table logic, `false` otherwise. + /// When `false` is returned, the caller should delegate to other handlers. + fn handle_table_events(&mut self) -> bool { + if !self.is_ready() { + return false; + } + + let key = self.key(); + let config = self.config(); + let current_route = self.current_route(); + let ignore_special = self.ignore_special_keys(); + + match key { + _ if matches_key!(up, key, ignore_special) => self.handle_scroll_up(), + _ if matches_key!(down, key, ignore_special) => self.handle_scroll_down(), + _ if matches_key!(pg_up, key, ignore_special) => self.handle_page_up(), + _ if matches_key!(pg_down, key, ignore_special) => self.handle_page_down(), + _ if matches_key!(home, key) => self.handle_home(), + _ if matches_key!(end, key) => self.handle_end(), + _ if matches_key!(left, key, ignore_special) || matches_key!(right, key, ignore_special) => { + self.handle_left_right() + } + _ if matches_key!(submit, key) => self.handle_submit(), + _ if matches_key!(esc, key) => self.handle_esc(), + _ if config.searching_block.is_some() + && current_route == *config.searching_block.as_ref().unwrap() => + { + self.handle_search_box_input() + } + _ if config.filtering_block.is_some() + && current_route == *config.filtering_block.as_ref().unwrap() => + { + self.handle_filter_box_input() + } + _ if matches_key!(filter, key) && config.filtering_block.is_some() => { + self.handle_filter_key() + } + _ if matches_key!(search, key) && config.searching_block.is_some() => { + self.handle_search_key() + } + _ if matches_key!(sort, key) && config.sorting_block.is_some() => self.handle_sort_key(), + _ => false, + } + } + + fn handle_scroll_up(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + match current_route { + _ if config.table_block == current_route => { + self.table_mut().scroll_up(); + true + } + _ if config.sorting_block.is_some() + && current_route == *config.sorting_block.as_ref().unwrap() => + { + if let Some(ref mut sort) = self.table_mut().sort { + sort.scroll_up(); + } + true + } + _ => false, + } + } + + fn handle_scroll_down(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + match current_route { + _ if config.table_block == current_route => { + self.table_mut().scroll_down(); + true + } + _ if config.sorting_block.is_some() + && current_route == *config.sorting_block.as_ref().unwrap() => + { + if let Some(ref mut sort) = self.table_mut().sort { + sort.scroll_down(); + } + true + } + _ => false, + } + } + + fn handle_page_up(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + if config.table_block == current_route { + self.table_mut().page_up(); + true + } else { + false + } + } + + fn handle_page_down(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + if config.table_block == current_route { + self.table_mut().page_down(); + true + } else { + false + } + } + + fn handle_home(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + match current_route { + _ if config.table_block == current_route => { + self.table_mut().scroll_to_top(); + true + } + _ if config.sorting_block.is_some() + && current_route == *config.sorting_block.as_ref().unwrap() => + { + if let Some(ref mut sort) = self.table_mut().sort { + sort.scroll_to_top(); + } + true + } + _ if config.searching_block.is_some() + && current_route == *config.searching_block.as_ref().unwrap() => + { + if let Some(ref mut search) = self.table_mut().search { + search.scroll_home(); + } + true + } + _ if config.filtering_block.is_some() + && current_route == *config.filtering_block.as_ref().unwrap() => + { + if let Some(ref mut filter) = self.table_mut().filter { + filter.scroll_home(); + } + true + } + _ => false, + } + } + + fn handle_end(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + match current_route { + _ if config.table_block == current_route => { + self.table_mut().scroll_to_bottom(); + true + } + _ if config.sorting_block.is_some() + && current_route == *config.sorting_block.as_ref().unwrap() => + { + if let Some(ref mut sort) = self.table_mut().sort { + sort.scroll_to_bottom(); + } + true + } + _ if config.searching_block.is_some() + && current_route == *config.searching_block.as_ref().unwrap() => + { + if let Some(ref mut search) = self.table_mut().search { + search.reset_offset(); + } + true + } + _ if config.filtering_block.is_some() + && current_route == *config.filtering_block.as_ref().unwrap() => + { + if let Some(ref mut filter) = self.table_mut().filter { + filter.reset_offset(); + } + true + } + _ => false, + } + } + + fn handle_left_right(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + let key = self.key(); + + match current_route { + _ if config.searching_block.is_some() + && current_route == *config.searching_block.as_ref().unwrap() => + { + if let Some(ref mut search) = self.table_mut().search { + if key == DEFAULT_KEYBINDINGS.left.key { + search.scroll_left(); + } else if key == DEFAULT_KEYBINDINGS.right.key { + search.scroll_right(); + } + } + true + } + _ if config.filtering_block.is_some() + && current_route == *config.filtering_block.as_ref().unwrap() => + { + if let Some(ref mut filter) = self.table_mut().filter { + if key == DEFAULT_KEYBINDINGS.left.key { + filter.scroll_left(); + } else if key == DEFAULT_KEYBINDINGS.right.key { + filter.scroll_right(); + } + } + true + } + _ => false, + } + } + + fn handle_submit(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + let sorting_block = config.sorting_block; + let searching_block = config.searching_block; + let search_field_fn = config.search_field_fn; + let search_error_block = config.search_error_block; + let filtering_block = config.filtering_block; + let filter_field_fn = config.filter_field_fn; + let filter_error_block = config.filter_error_block; + + match current_route { + _ if sorting_block.is_some() && current_route == *sorting_block.as_ref().unwrap() => { + self.table_mut().apply_sorting(); + self.app_mut().pop_navigation_stack(); + true + } + _ if searching_block.is_some() && current_route == *searching_block.as_ref().unwrap() => { + let app = self.app_mut(); + app.pop_navigation_stack(); + app.ignore_special_keys_for_textbox_input = false; + + if self.table_mut().search.is_some() { + let search_fn = search_field_fn.expect("Search field function is required"); + let has_match = self.table_mut().apply_search(search_fn); + + if !has_match { + self + .app_mut() + .push_navigation_stack(search_error_block.expect("Search error block is undefined")); + } + } + + true + } + _ if filtering_block.is_some() && current_route == *filtering_block.as_ref().unwrap() => { + let app = self.app_mut(); + app.pop_navigation_stack(); + app.ignore_special_keys_for_textbox_input = false; + + if self.table_mut().filter.is_some() { + let filter_fn = filter_field_fn.expect("Filter field function is required"); + let has_match = self.table_mut().apply_filter(filter_fn); + + if !has_match { + self + .app_mut() + .push_navigation_stack(filter_error_block.expect("Filter error block is undefined")); + } + } + + true + } + _ => false, + } + } + + fn handle_esc(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + let sorting_block = config.sorting_block; + let searching_block = config.searching_block; + let search_error_block = config.search_error_block; + let filtering_block = config.filtering_block; + let filter_error_block = config.filter_error_block; + let table_block = config.table_block; + + match current_route { + _ if sorting_block.is_some() && current_route == *sorting_block.as_ref().unwrap() => { + self.app_mut().pop_navigation_stack(); + true + } + _ if (searching_block.is_some() && current_route == *searching_block.as_ref().unwrap()) + || (search_error_block.is_some() + && current_route == *search_error_block.as_ref().unwrap()) => + { + self.app_mut().pop_navigation_stack(); + self.table_mut().reset_search(); + self.app_mut().ignore_special_keys_for_textbox_input = false; + true + } + _ if (filtering_block.is_some() && current_route == *filtering_block.as_ref().unwrap()) + || (filter_error_block.is_some() + && current_route == *filter_error_block.as_ref().unwrap()) => + { + self.app_mut().pop_navigation_stack(); + self.table_mut().reset_filter(); + self.app_mut().ignore_special_keys_for_textbox_input = false; + true + } + _ if table_block == current_route && self.table_mut().filtered_items.is_some() => { + self.table_mut().reset_filter(); + true + } + _ => false, + } + } + + fn handle_search_box_input(&mut self) -> bool { + let key = self.key(); + let Some(ref mut search) = self.table_mut().search else { + return false; + }; + + match key { + _ if matches_key!(backspace, key) => { + search.pop(); + } + Key::Char(character) => { + search.push(character); + } + _ => (), + } + true + } + + fn handle_filter_box_input(&mut self) -> bool { + let key = self.key(); + let Some(ref mut filter) = self.table_mut().filter else { + return false; + }; + + match key { + _ if matches_key!(backspace, key) => { + filter.pop(); + } + Key::Char(character) => { + filter.push(character); + } + _ => (), + } + true + } + + fn handle_filter_key(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + if current_route != config.table_block { + return false; + } + + let Some(filtering_block) = config.filtering_block else { + return false; + }; + + let filter = HorizontallyScrollableText::default(); + self.table_mut().filter = Some(filter); + let app = self.app_mut(); + app.push_navigation_stack(filtering_block); + app.ignore_special_keys_for_textbox_input = true; + true + } + + fn handle_search_key(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + if current_route != config.table_block { + return false; + } + + let Some(searching_block) = config.searching_block else { + return false; + }; + + let search = HorizontallyScrollableText::default(); + self.table_mut().search = Some(search); + let app = self.app_mut(); + app.push_navigation_stack(searching_block); + app.ignore_special_keys_for_textbox_input = true; + true + } + + fn handle_sort_key(&mut self) -> bool { + let config = self.config(); + let current_route = self.current_route(); + + if current_route != config.table_block { + return false; + } + + let (Some(sorting_block), Some(sort_options)) = + (config.sorting_block, config.sort_options.as_ref()) + else { + return false; + }; + + let sort_options = sort_options.clone(); + self.table_mut().sorting(sort_options); + self.app_mut().push_navigation_stack(sorting_block); + true + } +} + +/// Adapter struct that implements `TableEventHandler` for any `KeyEventHandler`. +/// +/// This struct enables table handling for existing handlers via composition rather than +/// inheritance. It wraps a handler reference and uses a closure to access the table, +/// allowing flexible access patterns (direct, optional, nested). +/// +/// # Type Parameters +/// +/// - `'a`, `'b`: Lifetimes from the handler +/// - `'handler`: Lifetime of the handler reference +/// - `T`: The table row type +/// - `H`: The handler type that implements `KeyEventHandler` +/// - `R`: The route type that converts into `Route` +/// +/// # Usage +/// +/// This struct is typically created by the `handle_table` helper function and should +/// not be constructed directly: +/// +/// ```rust,ignore +/// if !handle_table(self, |h| &mut h.app.data.my_table, config) { +/// self.handle_key_event(); +/// } +/// ``` +pub struct TableHandlerAdapter<'handler, 'a, 'b, T, H, R, F> +where + T: Clone + PartialEq + Eq + Debug + Default, + H: crate::handlers::KeyEventHandler<'a, 'b, R>, + R: Into + Copy, + F: for<'c> FnMut(&'c mut App<'b>) -> &'c mut StatefulTable, +{ + handler: &'handler mut H, + table_accessor: F, + config: TableHandlingConfig, + _phantom: PhantomData<(&'a (), &'b (), R)>, +} + +impl<'handler, 'a, 'b, T, H, R, F> TableHandlerAdapter<'handler, 'a, 'b, T, H, R, F> +where + T: Clone + PartialEq + Eq + Debug + Default, + H: crate::handlers::KeyEventHandler<'a, 'b, R>, + R: Into + Copy, + F: for<'c> FnMut(&'c mut App<'b>) -> &'c mut StatefulTable, +{ + fn new(handler: &'handler mut H, table_accessor: F, config: TableHandlingConfig) -> Self { + Self { + handler, + table_accessor, + config, + _phantom: PhantomData, + } + } +} + +impl<'handler, 'a, 'b, T, H, R, F> TableEventHandler<'b, T> + for TableHandlerAdapter<'handler, 'a, 'b, T, H, R, F> +where + T: Clone + PartialEq + Eq + Debug + Default, + H: crate::handlers::KeyEventHandler<'a, 'b, R>, + R: Into + Copy, + F: for<'c> FnMut(&'c mut App<'b>) -> &'c mut StatefulTable, +{ + fn table_mut(&mut self) -> &mut StatefulTable { + (self.table_accessor)(self.handler.app_mut()) + } + + fn config(&self) -> &TableHandlingConfig { + &self.config + } + + fn is_ready(&self) -> bool { + self.handler.is_ready() + } + + fn current_route(&self) -> Route { + self.handler.current_route() + } + + fn ignore_special_keys(&self) -> bool { + self.handler.ignore_special_keys() + } + + fn app_mut(&mut self) -> &mut App<'b> { + self.handler.app_mut() + } + + fn key(&self) -> Key { + self.handler.get_key() + } +} + +/// Helper function for ergonomic table event handling. +/// +/// This is the primary entry point for using trait-based table handling. It creates +/// a `TableHandlerAdapter`, calls `handle_table_events()`, and returns the result. +/// +/// # Parameters +/// +/// - `handler`: Mutable reference to a handler implementing `KeyEventHandler` +/// - `table_accessor`: Closure that extracts the table from the handler +/// - `config`: Table handling configuration +/// +/// # Returns +/// +/// `true` if the event was handled by table logic, `false` otherwise. +/// When `false` is returned, the caller should delegate to other event handlers. +/// +/// # Examples +/// +/// ## Single Table Handler +/// +/// ```rust,ignore +/// use crate::handlers::table_handler::{handle_table, TableHandlingConfig}; +/// +/// impl KeyEventHandler for LibraryHandler { +/// fn handle(&mut self) { +/// let config = TableHandlingConfig::new(ActiveBlock::Movies.into()) +/// .sorting_block(ActiveBlock::MoviesSortPrompt.into()) +/// .sort_options(movies_sorting_options()) +/// .searching_block(ActiveBlock::SearchMovie.into()) +/// .search_field_fn(|movie| &movie.title.text) +/// .filtering_block(ActiveBlock::FilterMovies.into()) +/// .filter_field_fn(|movie| &movie.title.text); +/// +/// if !handle_table(self, |h| &mut h.app.data.radarr_data.movies, config) { +/// // Event not handled by table, delegate to other handlers +/// match self.active_block { +/// _ if SubHandler::accepts(self.active_block) => { +/// SubHandler::new(self.key, self.app, self.active_block, self.context).handle(); +/// } +/// _ => self.handle_key_event(), +/// } +/// } +/// } +/// } +/// ``` +/// +/// ## Multiple Tables Handler +/// +/// ```rust,ignore +/// fn handle(&mut self) { +/// let releases_config = TableHandlingConfig::new(ActiveBlock::Releases.into()); +/// let history_config = TableHandlingConfig::new(ActiveBlock::History.into()); +/// +/// // Short-circuit evaluation: try each table in sequence +/// if !handle_table(self, |h| &mut h.app.data.movie_releases, releases_config) +/// && !handle_table(self, |h| &mut h.app.data.movie_history, history_config) +/// { +/// self.handle_key_event(); +/// } +/// } +/// ``` +/// +/// ## Optional Table Access +/// +/// ```rust,ignore +/// fn handle(&mut self) { +/// let config = TableHandlingConfig::new(ActiveBlock::SearchResults.into()); +/// +/// if !handle_table( +/// self, +/// |h| h.app.data.add_searched_movies.as_mut().expect("modal should be initialized"), +/// config, +/// ) { +/// self.handle_key_event(); +/// } +/// } +/// ``` +pub fn handle_table<'a, 'b, T, H, R, F>( + handler: &mut H, + table_accessor: F, + config: TableHandlingConfig, +) -> bool +where + T: Clone + PartialEq + Eq + Debug + Default, + H: crate::handlers::KeyEventHandler<'a, 'b, R>, + R: Into + Copy, + F: for<'c> FnMut(&'c mut App<'b>) -> &'c mut StatefulTable, +{ + let mut adapter = TableHandlerAdapter::new(handler, table_accessor, config); + adapter.handle_table_events() +} diff --git a/src/handlers/table_handler_tests.rs b/src/handlers/table_handler_tests.rs index 688bfcd..4e5b9ab 100644 --- a/src/handlers/table_handler_tests.rs +++ b/src/handlers/table_handler_tests.rs @@ -1,11 +1,14 @@ #[cfg(test)] mod tests { - use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; + use crate::app::key_binding::DEFAULT_KEYBINDINGS; + use crate::assert_modal_absent; + use crate::assert_modal_present; + use crate::assert_navigation_pushed; use crate::event::Key; - use crate::handle_table_events; - use crate::handlers::table_handler::TableHandlingConfig; use crate::handlers::KeyEventHandler; + use crate::handlers::table_handler::TableHandlingConfig; + use crate::handlers::table_handler::handle_table; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_models::Language; @@ -23,7 +26,6 @@ mod tests { fn handle(&mut self) { let movie_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Movies.into()) .sorting_block(ActiveRadarrBlock::MoviesSortPrompt.into()) - .sort_by_fn(|a: &Movie, b: &Movie| a.id.cmp(&b.id)) .sort_options(sort_options()) .searching_block(ActiveRadarrBlock::SearchMovie.into()) .search_error_block(ActiveRadarrBlock::SearchMovieError.into()) @@ -34,13 +36,13 @@ mod tests { let minimal_movie_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Movies.into()); - match self.active_radarr_block { - ActiveRadarrBlock::MovieDetails => { - self.handle_movies_table_events(minimal_movie_table_handling_config); - } - _ => { - self.handle_movies_table_events(movie_table_handling_config); - } + let config = match self.active_radarr_block { + ActiveRadarrBlock::MovieDetails => minimal_movie_table_handling_config, + _ => movie_table_handling_config, + }; + + if !handle_table(self, |app| &mut app.data.radarr_data.movies, config) { + self.handle_key_event(); } } @@ -91,10 +93,14 @@ mod tests { fn handle_esc(&mut self) {} fn handle_char_key_event(&mut self) {} - } - impl TableHandlerUnit<'_, '_> { - handle_table_events!(self, movies, self.app.data.radarr_data.movies, Movie); + fn app_mut(&mut self) -> &mut App<'b> { + self.app + } + + fn current_route(&self) -> crate::models::Route { + self.app.get_current_route() + } } mod test_handle_scroll_up_and_down { @@ -199,6 +205,86 @@ mod tests { } } } + + #[test] + fn test_table_sort_scroll_up_with_sort_some() { + let movie_field_vec = sort_options(); + let mut app = App::test_default(); + app.data.radarr_data.movies.sorting(sort_options()); + app.push_navigation_stack(ActiveRadarrBlock::MoviesSortPrompt.into()); + + assert_eq!( + app + .data + .radarr_data + .movies + .sort + .as_ref() + .unwrap() + .current_selection(), + &movie_field_vec[0] + ); + + TableHandlerUnit::new( + DEFAULT_KEYBINDINGS.up.key, + &mut app, + ActiveRadarrBlock::MoviesSortPrompt, + None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .movies + .sort + .as_ref() + .unwrap() + .current_selection(), + &movie_field_vec[movie_field_vec.len() - 1] + ); + } + + #[test] + fn test_table_sort_scroll_down_with_sort_some() { + let movie_field_vec = sort_options(); + let mut app = App::test_default(); + app.data.radarr_data.movies.sorting(sort_options()); + app.push_navigation_stack(ActiveRadarrBlock::MoviesSortPrompt.into()); + + assert_eq!( + app + .data + .radarr_data + .movies + .sort + .as_ref() + .unwrap() + .current_selection(), + &movie_field_vec[0] + ); + + TableHandlerUnit::new( + DEFAULT_KEYBINDINGS.down.key, + &mut app, + ActiveRadarrBlock::MoviesSortPrompt, + None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .movies + .sort + .as_ref() + .unwrap() + .current_selection(), + &movie_field_vec[0] + ); + } } mod test_handle_home_end { @@ -427,6 +513,70 @@ mod tests { &movie_field_vec[0] ); } + + #[test] + fn test_table_sort_home_with_sort_some() { + let movie_field_vec = sort_options(); + let mut app = App::test_default(); + app.data.radarr_data.movies.sorting(sort_options()); + app.push_navigation_stack(ActiveRadarrBlock::MoviesSortPrompt.into()); + + TableHandlerUnit::new( + DEFAULT_KEYBINDINGS.down.key, + &mut app, + ActiveRadarrBlock::MoviesSortPrompt, + None, + ) + .handle(); + + TableHandlerUnit::new( + DEFAULT_KEYBINDINGS.home.key, + &mut app, + ActiveRadarrBlock::MoviesSortPrompt, + None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .movies + .sort + .as_ref() + .unwrap() + .current_selection(), + &movie_field_vec[0] + ); + } + + #[test] + fn test_table_sort_end_with_sort_some() { + let movie_field_vec = sort_options(); + let mut app = App::test_default(); + app.data.radarr_data.movies.sorting(sort_options()); + app.push_navigation_stack(ActiveRadarrBlock::MoviesSortPrompt.into()); + + TableHandlerUnit::new( + DEFAULT_KEYBINDINGS.end.key, + &mut app, + ActiveRadarrBlock::MoviesSortPrompt, + None, + ) + .handle(); + + assert_eq!( + app + .data + .radarr_data + .movies + .sort + .as_ref() + .unwrap() + .current_selection(), + &movie_field_vec[movie_field_vec.len() - 1] + ); + } } mod test_handle_pagination_scroll { @@ -589,8 +739,8 @@ mod tests { mod test_handle_submit { use pretty_assertions::{assert_eq, assert_str_eq}; - use crate::extended_stateful_iterable_vec; use crate::models::HorizontallyScrollableText; + use crate::{assert_navigation_popped, extended_stateful_iterable_vec}; use super::*; @@ -617,7 +767,7 @@ mod tests { app.data.radarr_data.movies.current_selection().title.text, "Test 2" ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } #[test] @@ -641,10 +791,7 @@ mod tests { app.data.radarr_data.movies.current_selection().title.text, "Test 1" ); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SearchMovieError.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SearchMovieError.into()); } #[test] @@ -673,7 +820,7 @@ mod tests { app.data.radarr_data.movies.current_selection().title.text, "Test 2" ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } #[test] @@ -693,7 +840,7 @@ mod tests { TableHandlerUnit::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::FilterMovies, None).handle(); - assert!(app.data.radarr_data.movies.filtered_items.is_some()); + assert_modal_present!(app.data.radarr_data.movies.filtered_items); assert!(!app.ignore_special_keys_for_textbox_input); assert_eq!( app @@ -710,7 +857,7 @@ mod tests { app.data.radarr_data.movies.current_selection().title.text, "Test 1" ); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); } #[test] @@ -731,11 +878,8 @@ mod tests { TableHandlerUnit::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::FilterMovies, None).handle(); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.movies.filtered_items.is_none()); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::FilterMoviesError.into() - ); + assert_modal_absent!(app.data.radarr_data.movies.filtered_items); + assert_navigation_pushed!(app, ActiveRadarrBlock::FilterMoviesError.into()); } #[test] @@ -759,7 +903,7 @@ mod tests { ) .handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert_eq!(app.data.radarr_data.movies.items, expected_vec); } } @@ -772,6 +916,7 @@ mod tests { use crate::models::stateful_table::StatefulTable; use super::*; + use crate::assert_navigation_popped; const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key; @@ -789,9 +934,9 @@ mod tests { TableHandlerUnit::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.data.radarr_data.movies.search, None); + assert_none!(app.data.radarr_data.movies.search); } #[rstest] @@ -818,11 +963,11 @@ mod tests { TableHandlerUnit::new(ESC_KEY, &mut app, active_radarr_block, None).handle(); - assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.data.radarr_data.movies.filter, None); - assert_eq!(app.data.radarr_data.movies.filtered_items, None); - assert_eq!(app.data.radarr_data.movies.filtered_state, None); + assert_none!(app.data.radarr_data.movies.filter); + assert_none!(app.data.radarr_data.movies.filtered_items); + assert_none!(app.data.radarr_data.movies.filtered_state); } #[test] @@ -834,13 +979,37 @@ mod tests { TableHandlerUnit::new(ESC_KEY, &mut app, ActiveRadarrBlock::MoviesSortPrompt, None).handle(); + assert_navigation_popped!(app, ActiveRadarrBlock::Movies.into()); + } + + #[test] + fn test_table_block_esc_with_filter_applied() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + app.data.radarr_data.movies = StatefulTable { + filter: Some("Test".into()), + filtered_items: Some(Vec::new()), + filtered_state: Some(TableState::default()), + ..StatefulTable::default() + }; + app + .data + .radarr_data + .movies + .set_items(vec![Movie::default()]); + + TableHandlerUnit::new(ESC_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle(); + assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); + assert_none!(app.data.radarr_data.movies.filter); + assert_none!(app.data.radarr_data.movies.filtered_items); + assert_none!(app.data.radarr_data.movies.filtered_state); } } mod test_handle_key_char { - use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::HorizontallyScrollableText; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use pretty_assertions::{assert_eq, assert_str_eq}; use super::*; @@ -862,14 +1031,11 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::SearchMovie.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::SearchMovie.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.data.radarr_data.movies.search, - Some(HorizontallyScrollableText::default()) + assert_some_eq_x!( + &app.data.radarr_data.movies.search, + &HorizontallyScrollableText::default() ); } @@ -894,7 +1060,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.data.radarr_data.movies.search, None); + assert_none!(app.data.radarr_data.movies.search); } #[test] @@ -916,7 +1082,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.data.radarr_data.movies.search, None); + assert_none!(app.data.radarr_data.movies.search); } #[test] @@ -936,12 +1102,9 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::FilterMovies.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::FilterMovies.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.movies.filter.is_some()); + assert_modal_present!(app.data.radarr_data.movies.filter); } #[test] @@ -965,7 +1128,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert!(app.data.radarr_data.movies.filter.is_none()); + assert_modal_absent!(app.data.radarr_data.movies.filter); } #[test] @@ -989,17 +1152,14 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::FilterMovies.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::FilterMovies.into()); assert!(app.ignore_special_keys_for_textbox_input); - assert_eq!( - app.data.radarr_data.movies.filter, - Some(HorizontallyScrollableText::default()) + assert_some_eq_x!( + &app.data.radarr_data.movies.filter, + &HorizontallyScrollableText::default() ); - assert!(app.data.radarr_data.movies.filtered_items.is_none()); - assert!(app.data.radarr_data.movies.filtered_state.is_none()); + assert_modal_absent!(app.data.radarr_data.movies.filtered_items); + assert_modal_absent!(app.data.radarr_data.movies.filtered_state); } #[test] @@ -1021,7 +1181,7 @@ mod tests { assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); assert!(!app.ignore_special_keys_for_textbox_input); - assert_eq!(app.data.radarr_data.movies.filter, None); + assert_none!(app.data.radarr_data.movies.filter); } #[test] @@ -1141,10 +1301,7 @@ mod tests { ) .handle(); - assert_eq!( - app.get_current_route(), - ActiveRadarrBlock::MoviesSortPrompt.into() - ); + assert_navigation_pushed!(app, ActiveRadarrBlock::MoviesSortPrompt.into()); assert_eq!( app.data.radarr_data.movies.sort.as_ref().unwrap().items, sort_options() @@ -1172,7 +1329,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert!(app.data.radarr_data.movies.sort.is_none()); + assert_modal_absent!(app.data.radarr_data.movies.sort); } #[test] @@ -1193,7 +1350,7 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into()); - assert!(app.data.radarr_data.movies.sort.is_none()); + assert_modal_absent!(app.data.radarr_data.movies.sort); } } diff --git a/src/main.rs b/src/main.rs index 45799a9..02c8083 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,35 +1,39 @@ +#[cfg(test)] +#[macro_use] +extern crate assertables; + use anyhow::Result; -use clap::{crate_authors, crate_description, crate_name, crate_version, CommandFactory, Parser}; +use clap::{CommandFactory, Parser, crate_authors, crate_description, crate_name, crate_version}; use clap_complete::generate; use crossterm::execute; use crossterm::terminal::{ - disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, + EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode, }; use log::{debug, error, warn}; use network::NetworkTrait; -use ratatui::backend::CrosstermBackend; use ratatui::Terminal; +use ratatui::backend::CrosstermBackend; use reqwest::Client; use std::panic::PanicHookInfo; use std::path::PathBuf; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::{io, panic, process}; use tokio::select; use tokio::sync::mpsc::Receiver; -use tokio::sync::{mpsc, Mutex}; +use tokio::sync::{Mutex, mpsc}; use tokio_util::sync::CancellationToken; use utils::{ build_network_client, load_config, start_cli_no_spinner, start_cli_with_spinner, tail_logs, }; -use crate::app::{log_and_print_error, App}; +use crate::app::{App, log_and_print_error}; use crate::cli::Command; -use crate::event::input_event::{Events, InputEvent}; use crate::event::Key; +use crate::event::input_event::{Events, InputEvent}; use crate::network::{Network, NetworkEvent}; use crate::ui::theme::{Theme, ThemeDefinitionsWrapper}; -use crate::ui::{ui, THEME}; +use crate::ui::{THEME, ui}; use crate::utils::load_theme_config; mod app; @@ -152,7 +156,7 @@ async fn main() -> Result<()> { let mut cli = Cli::command(); generate(shell, &mut cli, "managarr", &mut io::stdout()) } - Command::TailLogs { no_color } => tail_logs(no_color).await, + Command::TailLogs { no_color } => tail_logs(no_color).await?, }, None => { let app_nw = Arc::clone(&app); @@ -203,7 +207,7 @@ async fn start_ui( themes_file_arg: &Option, theme_name: String, ) -> Result<()> { - let theme_definitions_wrapper = if let Some(ref theme_file) = themes_file_arg { + let theme_definitions_wrapper = if let Some(theme_file) = themes_file_arg { load_theme_config(theme_file.to_str().expect("Invalid theme file specified"))? } else { confy::load("managarr", "themes").unwrap_or_else(|_| ThemeDefinitionsWrapper::default()) diff --git a/src/models/mod.rs b/src/models/mod.rs index ce52d16..fc8d5b6 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,12 +1,12 @@ use std::fmt::{Debug, Display, Formatter}; use std::sync::atomic::{AtomicUsize, Ordering}; -use crate::app::context_clues::ContextClue; use crate::app::ServarrConfig; +use crate::app::context_clues::ContextClue; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use radarr_models::RadarrSerdeable; use regex::Regex; -use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use serde_json::Number; use servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use sonarr_models::SonarrSerdeable; @@ -58,6 +58,7 @@ pub trait Paginated { } #[derive(Default)] +#[cfg_attr(test, derive(Debug))] pub struct ScrollableText { pub items: Vec, pub offset: u16, @@ -65,8 +66,7 @@ pub struct ScrollableText { impl ScrollableText { pub fn with_string(item: String) -> ScrollableText { - let items: Vec<&str> = item.split('\n').collect(); - let items: Vec = items.iter().map(|it| it.to_string()).collect(); + let items: Vec = item.split('\n').map(str::to_owned).collect(); ScrollableText { items, offset: 0 } } @@ -278,6 +278,7 @@ pub struct TabRoute { pub config: Option, } +#[cfg_attr(test, derive(Debug))] pub struct TabState { pub tabs: Vec, pub index: usize, diff --git a/src/models/model_tests.rs b/src/models/model_tests.rs index 5f3494d..1b8dc3e 100644 --- a/src/models/model_tests.rs +++ b/src/models/model_tests.rs @@ -3,20 +3,20 @@ mod tests { use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; + use crate::app::ServarrConfig; use crate::app::context_clues::ContextClue; use crate::app::key_binding::DEFAULT_KEYBINDINGS; - use crate::app::ServarrConfig; use crate::models::from_f64; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; - use crate::models::{from_i64, strip_non_search_characters}; use crate::models::{ BlockSelectionState, HorizontallyScrollableText, Scrollable, ScrollableText, TabRoute, TabState, }; + use crate::models::{from_i64, strip_non_search_characters}; use pretty_assertions::{assert_eq, assert_str_eq}; + use serde::de::IntoDeserializer; use serde::de::value::Error as ValueError; use serde::de::value::F64Deserializer; use serde::de::value::I64Deserializer; - use serde::de::IntoDeserializer; use serde_json::to_string; const BLOCKS: &[&[i32]] = &[&[11, 12], &[21, 22], &[31, 32]]; @@ -46,7 +46,7 @@ mod tests { fn test_scrollable_text_is_empty() { let scrollable_text = ScrollableText::default(); - assert!(scrollable_text.is_empty()); + assert_is_empty!(scrollable_text); let test_text = "Test \nString"; let scrollable_text = ScrollableText::with_string(test_text.to_owned()); @@ -151,7 +151,7 @@ mod tests { offset: AtomicUsize::new(test_text.len()), }; - assert!(horizontally_scrollable_text.to_string().is_empty()); + assert_is_empty!(horizontally_scrollable_text.to_string()); } #[test] @@ -228,7 +228,7 @@ mod tests { horizontally_scrollable_text.offset.load(Ordering::SeqCst), 2 ); - assert!(horizontally_scrollable_text.to_string().is_empty()); + assert_is_empty!(horizontally_scrollable_text.to_string()); } #[test] @@ -444,7 +444,7 @@ mod tests { horizontally_scrollable_text.pop(); - assert!(horizontally_scrollable_text.text.is_empty()); + assert_is_empty!(horizontally_scrollable_text.text); assert_eq!( horizontally_scrollable_text.offset.load(Ordering::SeqCst), 0 @@ -452,7 +452,7 @@ mod tests { horizontally_scrollable_text.pop(); - assert!(horizontally_scrollable_text.text.is_empty()); + assert_is_empty!(horizontally_scrollable_text.text); assert_eq!( horizontally_scrollable_text.offset.load(Ordering::SeqCst), 0 @@ -530,7 +530,7 @@ mod tests { let active_config = tab_state.get_active_config(); - assert!(active_config.is_some()); + assert_some!(active_config); assert_str_eq!(active_config.clone().unwrap().name.unwrap(), "Test"); } @@ -541,7 +541,7 @@ mod tests { let active_config = tab_state.get_active_config(); - assert!(active_config.is_none()); + assert_none!(active_config); } #[test] @@ -630,8 +630,7 @@ mod tests { let tab_help = tab_state.get_active_route_contextual_help(); - assert!(tab_help.is_some()); - assert_eq!(tab_help.unwrap(), second_tab_help.unwrap()); + assert_some_eq_x!(tab_help, second_tab_help.unwrap()); } #[test] @@ -784,7 +783,7 @@ mod tests { fn test_from_i64() { let deserializer: I64Deserializer = 1i64.into_deserializer(); - assert_eq!(from_i64(deserializer), Ok(1)); + assert_ok_eq_x!(from_i64(deserializer), 1); } #[test] @@ -801,7 +800,7 @@ mod tests { fn test_from_f64() { let deserializer: F64Deserializer = 1f64.into_deserializer(); - assert_eq!(from_f64(deserializer), Ok(1.0)); + assert_ok_eq_x!(from_f64(deserializer), 1.0); } #[test] diff --git a/src/models/radarr_models.rs b/src/models/radarr_models.rs index e9b1d0e..70b9bdd 100644 --- a/src/models/radarr_models.rs +++ b/src/models/radarr_models.rs @@ -10,11 +10,11 @@ use serde::{Deserialize, Serialize}; use serde_json::{Number, Value}; use strum_macros::{Display, EnumIter}; +use super::Serdeable; use super::servarr_models::{ DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper, QueueEvent, RootFolder, SecurityConfig, Tag, Update, }; -use super::Serdeable; #[cfg(test)] #[path = "radarr_models_tests.rs"] diff --git a/src/models/radarr_models_tests.rs b/src/models/radarr_models_tests.rs index 2a611e8..0820f39 100644 --- a/src/models/radarr_models_tests.rs +++ b/src/models/radarr_models_tests.rs @@ -4,6 +4,7 @@ mod tests { use serde_json::json; use crate::models::{ + Serdeable, radarr_models::{ AddMovieSearchResult, BlocklistItem, BlocklistResponse, Collection, Credit, DiskSpace, DownloadRecord, DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult, @@ -11,7 +12,6 @@ mod tests { RadarrSerdeable, RadarrTask, RadarrTaskName, SystemStatus, Tag, Update, }, servarr_models::{HostConfig, Log, LogResponse, QueueEvent, RootFolder, SecurityConfig}, - Serdeable, }; #[test] diff --git a/src/models/servarr_data/data_test_utils.rs b/src/models/servarr_data/data_test_utils.rs new file mode 100644 index 0000000..429ff7f --- /dev/null +++ b/src/models/servarr_data/data_test_utils.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! sort_option { + ($field:ident) => { + SortOption { + name: "Something", + cmp_fn: Some(|a, b| a.$field.cmp(&b.$field)), + } + }; +} diff --git a/src/models/servarr_data/mod.rs b/src/models/servarr_data/mod.rs index dcffb96..1545315 100644 --- a/src/models/servarr_data/mod.rs +++ b/src/models/servarr_data/mod.rs @@ -5,7 +5,8 @@ pub mod radarr; pub mod sonarr; #[cfg(test)] -#[path = "servarr_data_tests.rs"] +pub(in crate::models::servarr_data) mod data_test_utils; +#[cfg(test)] mod servarr_data_tests; #[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] diff --git a/src/models/servarr_data/radarr/modals.rs b/src/models/servarr_data/radarr/modals.rs index 55e3398..922757d 100644 --- a/src/models/servarr_data/radarr/modals.rs +++ b/src/models/servarr_data/radarr/modals.rs @@ -41,61 +41,56 @@ impl From<&RadarrData<'_>> for EditIndexerModal { } = radarr_data.indexers.current_selection(); let seed_ratio_field_option = fields .as_ref() - .unwrap() + .expect("indexer fields must exist") .iter() - .find(|field| field.name.as_ref().unwrap() == "seedCriteria.seedRatio"); + .find(|field| { + field.name.as_ref().expect("indexer field name must exist") == "seedCriteria.seedRatio" + }); let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option { seed_ratio_field.value.clone() } else { None }; - edit_indexer_modal.name = name.clone().unwrap().into(); + edit_indexer_modal.name = name.clone().expect("indexer name must exist").into(); edit_indexer_modal.enable_rss = Some(*enable_rss); edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search); edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search); edit_indexer_modal.priority = *priority; edit_indexer_modal.url = fields .as_ref() - .unwrap() + .expect("indexer fields must exist") .iter() - .find(|field| field.name.as_ref().unwrap() == "baseUrl") - .unwrap() + .find(|field| field.name.as_ref().expect("indexer field name must exist") == "baseUrl") + .expect("baseUrl field must exist") .value .clone() - .unwrap() + .expect("baseUrl field value must exist") .as_str() - .unwrap() + .expect("baseUrl field value must be a string") .into(); edit_indexer_modal.api_key = fields .as_ref() - .unwrap() + .expect("indexer fields must exist") .iter() - .find(|field| field.name.as_ref().unwrap() == "apiKey") - .unwrap() + .find(|field| field.name.as_ref().expect("indexer field name must exist") == "apiKey") + .expect("apiKey field must exist") .value .clone() - .unwrap() + .expect("apiKey field value must exist") .as_str() - .unwrap() + .expect("apiKey field value must be a string") .into(); if let Some(seed_ratio_value) = seed_ratio_value_option { - edit_indexer_modal.seed_ratio = seed_ratio_value.as_f64().unwrap().to_string().into(); + edit_indexer_modal.seed_ratio = seed_ratio_value + .as_f64() + .expect("Seed ratio value must be a valid f64") + .to_string() + .into(); } - edit_indexer_modal.tags = tags - .iter() - .map(|tag_id| { - radarr_data - .tags_map - .get_by_left(&tag_id.as_i64().unwrap()) - .unwrap() - .clone() - }) - .collect::>() - .join(", ") - .into(); + edit_indexer_modal.tags = radarr_data.tag_ids_to_display(tags).into(); edit_indexer_modal } @@ -126,18 +121,7 @@ impl From<&RadarrData<'_>> for EditMovieModal { .minimum_availability_list .set_items(Vec::from_iter(MinimumAvailability::iter())); edit_movie_modal.path = path.clone().into(); - edit_movie_modal.tags = tags - .iter() - .map(|tag_id| { - radarr_data - .tags_map - .get_by_left(&tag_id.as_i64().unwrap()) - .unwrap() - .clone() - }) - .collect::>() - .join(", ") - .into(); + edit_movie_modal.tags = radarr_data.tag_ids_to_display(tags).into(); edit_movie_modal.monitored = Some(*monitored); @@ -151,15 +135,9 @@ impl From<&RadarrData<'_>> for EditMovieModal { .state .select(minimum_availability_index); - let mut quality_profile_names: Vec = radarr_data - .quality_profile_map - .right_values() - .cloned() - .collect(); - quality_profile_names.sort(); edit_movie_modal .quality_profile_list - .set_items(quality_profile_names); + .set_items(radarr_data.sorted_quality_profile_names()); let quality_profile_name = radarr_data .quality_profile_map .get_by_left(quality_profile_id) @@ -196,15 +174,9 @@ impl From<&RadarrData<'_>> for AddMovieModal { add_movie_modal .minimum_availability_list .set_items(Vec::from_iter(MinimumAvailability::iter())); - let mut quality_profile_names: Vec = radarr_data - .quality_profile_map - .right_values() - .cloned() - .collect(); - quality_profile_names.sort(); add_movie_modal .quality_profile_list - .set_items(quality_profile_names); + .set_items(radarr_data.sorted_quality_profile_names()); add_movie_modal .root_folder_list .set_items(radarr_data.root_folders.items.to_vec()); @@ -240,15 +212,9 @@ impl From<&RadarrData<'_>> for EditCollectionModal { edit_collection_modal .minimum_availability_list .set_items(Vec::from_iter(MinimumAvailability::iter())); - let mut quality_profile_names: Vec = radarr_data - .quality_profile_map - .right_values() - .cloned() - .collect(); - quality_profile_names.sort(); edit_collection_modal .quality_profile_list - .set_items(quality_profile_names); + .set_items(radarr_data.sorted_quality_profile_names()); let minimum_availability_index = edit_collection_modal .minimum_availability_list diff --git a/src/models/servarr_data/radarr/modals_tests.rs b/src/models/servarr_data/radarr/modals_tests.rs index 91b920b..dabac4d 100644 --- a/src/models/servarr_data/radarr/modals_tests.rs +++ b/src/models/servarr_data/radarr/modals_tests.rs @@ -4,8 +4,8 @@ mod test { use crate::models::servarr_data::radarr::modals::{ AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, }; - use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::servarr_data::radarr::radarr_data::RadarrData; + use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data; use crate::models::servarr_models::{Indexer, IndexerField, RootFolder}; use crate::models::stateful_table::StatefulTable; use bimap::BiMap; diff --git a/src/models/servarr_data/radarr/radarr_data.rs b/src/models/servarr_data/radarr/radarr_data.rs index 1c43015..1d2d351 100644 --- a/src/models/servarr_data/radarr/radarr_data.rs +++ b/src/models/servarr_data/radarr/radarr_data.rs @@ -23,7 +23,25 @@ use crate::models::{ use crate::network::radarr_network::RadarrEvent; use bimap::BiMap; use chrono::{DateTime, Utc}; +use serde_json::Number; use strum::EnumIter; +#[cfg(test)] +use { + crate::models::radarr_models::{MinimumAvailability, MovieMonitor}, + crate::models::stateful_table::SortOption, + crate::network::radarr_network::radarr_network_test_utils::test_utils::root_folder, + crate::network::radarr_network::radarr_network_test_utils::test_utils::{ + add_movie_search_result, blocklist_item, cast_credit, collection, collection_movie, + crew_credit, download_record, indexer, log_line, movie, movie_history_item, + quality_profile_map, tags_map, task, torrent_release, updates, usenet_release, + }, + crate::network::servarr_test_utils::diskspace, + crate::network::servarr_test_utils::indexer_test_result, + crate::network::servarr_test_utils::queued_event, + crate::sort_option, + strum::IntoEnumIterator, + strum_macros::{Display, EnumString}, +}; #[cfg(test)] #[path = "radarr_data_tests.rs"] @@ -81,6 +99,23 @@ impl RadarrData<'_> { self.movie_details_modal = None; self.movie_info_tabs.index = 0; } + + pub fn tag_ids_to_display(&self, tag_ids: &[Number]) -> String { + tag_ids + .iter() + .filter_map(|tag_id| { + let id = tag_id.as_i64()?; + self.tags_map.get_by_left(&id).cloned() + }) + .collect::>() + .join(", ") + } + + pub fn sorted_quality_profile_names(&self) -> Vec { + let mut names: Vec = self.quality_profile_map.right_values().cloned().collect(); + names.sort(); + names + } } impl<'a> Default for RadarrData<'a> { @@ -205,7 +240,163 @@ impl<'a> Default for RadarrData<'a> { } } +#[cfg(test)] +impl RadarrData<'_> { + pub fn test_default_fully_populated() -> Self { + let quality_profile_name = "HD - 1080p".to_owned(); + let mut add_movie_modal = AddMovieModal { + tags: "alex".into(), + ..AddMovieModal::default() + }; + add_movie_modal + .root_folder_list + .set_items(vec![root_folder()]); + add_movie_modal + .monitor_list + .set_items(MovieMonitor::iter().collect()); + add_movie_modal + .minimum_availability_list + .set_items(MinimumAvailability::iter().collect()); + add_movie_modal + .quality_profile_list + .set_items(vec![quality_profile_name.clone()]); + + let mut add_movie_search_result_table = StatefulTable::default(); + add_movie_search_result_table.set_items(vec![add_movie_search_result()]); + add_movie_search_result_table.sorting(vec![sort_option!(tmdb_id)]); + add_movie_search_result_table.search = Some("something".into()); + add_movie_search_result_table.filter = Some("something".into()); + + let mut edit_movie_modal = EditMovieModal { + monitored: Some(true), + path: "/nfs/movies".into(), + tags: "alex".into(), + ..EditMovieModal::default() + }; + edit_movie_modal + .minimum_availability_list + .set_items(MinimumAvailability::iter().collect()); + edit_movie_modal + .quality_profile_list + .set_items(vec![quality_profile_name.clone()]); + + let mut edit_collection_modal = EditCollectionModal { + monitored: Some(true), + path: "/nfs/movies".into(), + search_on_add: Some(true), + ..EditCollectionModal::default() + }; + edit_collection_modal + .minimum_availability_list + .set_items(MinimumAvailability::iter().collect()); + edit_collection_modal + .quality_profile_list + .set_items(vec![quality_profile_name.clone()]); + + let edit_indexer_modal = EditIndexerModal { + name: "DrunkenSlug".into(), + enable_rss: Some(true), + enable_automatic_search: Some(true), + enable_interactive_search: Some(true), + url: "http://127.0.0.1:9696/1/".into(), + api_key: "someApiKey".into(), + seed_ratio: "ratio".into(), + tags: "25".into(), + priority: 1, + }; + + let indexer_settings = IndexerSettings { + allow_hardcoded_subs: true, + availability_delay: 0, + id: 1, + maximum_size: 1234, + minimum_age: 12, + prefer_indexer_flags: true, + retention: 30, + rss_sync_interval: 60, + whitelisted_hardcoded_subs: "eng".into(), + }; + + let mut indexer_test_results = StatefulTable::default(); + indexer_test_results.set_items(vec![indexer_test_result()]); + indexer_test_results.sorting(vec![sort_option!(name)]); + indexer_test_results.search = Some("something".into()); + indexer_test_results.filter = Some("something".into()); + + let mut movie_details_modal = MovieDetailsModal { + movie_details: ScrollableText::with_string("Some information".to_owned()), + file_details: "Some file info".to_owned(), + audio_details: "Some audio info".to_owned(), + video_details: "Some video info".to_owned(), + ..MovieDetailsModal::default() + }; + movie_details_modal + .movie_history + .set_items(vec![movie_history_item()]); + movie_details_modal + .movie_cast + .set_items(vec![cast_credit()]); + movie_details_modal + .movie_crew + .set_items(vec![crew_credit()]); + movie_details_modal + .movie_releases + .set_items(vec![torrent_release(), usenet_release()]); + movie_details_modal + .movie_releases + .sorting(vec![sort_option!(indexer_id)]); + + let mut radarr_data = RadarrData { + disk_space_vec: vec![diskspace()], + version: "1.2.3.4".to_owned(), + quality_profile_map: quality_profile_map(), + tags_map: tags_map(), + updates: updates(), + start_time: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T21:29:16Z").unwrap()), + add_movie_search: Some("test".into()), + add_movie_modal: Some(add_movie_modal), + add_searched_movies: Some(add_movie_search_result_table), + edit_movie_modal: Some(edit_movie_modal), + edit_collection_modal: Some(edit_collection_modal), + edit_indexer_modal: Some(edit_indexer_modal), + edit_root_folder: Some("/nfs/movies".into()), + indexer_settings: Some(indexer_settings), + indexer_test_errors: Some("error".into()), + indexer_test_all_results: Some(indexer_test_results), + movie_details_modal: Some(movie_details_modal), + delete_movie_files: true, + ..RadarrData::default() + }; + radarr_data.root_folders.set_items(vec![root_folder()]); + radarr_data.movies.set_items(vec![movie()]); + radarr_data.movies.sorting(vec![sort_option!(id)]); + radarr_data.movies.search = Some("Something".into()); + radarr_data.movies.filter = Some("Something".into()); + radarr_data.collections.set_items(vec![collection()]); + radarr_data.collections.sorting(vec![sort_option!(id)]); + radarr_data.collections.search = Some("Something".into()); + radarr_data.collections.filter = Some("Something".into()); + radarr_data + .collection_movies + .set_items(vec![collection_movie()]); + radarr_data.downloads.set_items(vec![download_record()]); + radarr_data.blocklist.set_items(vec![blocklist_item()]); + radarr_data.blocklist.sorting(vec![sort_option!(id)]); + radarr_data.indexers.set_items(vec![indexer()]); + radarr_data.indexers.sorting(vec![sort_option!(id)]); + radarr_data.indexers.search = Some("Something".into()); + radarr_data.indexers.filter = Some("Something".into()); + radarr_data.logs.set_items(vec![log_line().into()]); + radarr_data.log_details.set_items(vec![log_line().into()]); + radarr_data.tasks.set_items(vec![task()]); + radarr_data.queued_events.set_items(vec![queued_event()]); + + radarr_data + } +} + #[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)] +#[cfg_attr(test, derive(Display, EnumString))] pub enum ActiveRadarrBlock { AddMovieAlreadyInLibrary, AddMovieSearchInput, diff --git a/src/models/servarr_data/radarr/radarr_data_tests.rs b/src/models/servarr_data/radarr/radarr_data_tests.rs index cd2d67f..b56d232 100644 --- a/src/models/servarr_data/radarr/radarr_data_tests.rs +++ b/src/models/servarr_data/radarr/radarr_data_tests.rs @@ -13,9 +13,9 @@ mod tests { MOVIE_DETAILS_CONTEXT_CLUES, }; + use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData}; - use crate::models::Route; use crate::assert_movie_info_tabs_reset; use crate::models::BlockSelectionState; @@ -192,9 +192,11 @@ mod tests { radarr_data.movie_info_tabs.tabs[0].route, ActiveRadarrBlock::MovieDetails.into() ); - assert!(radarr_data.movie_info_tabs.tabs[0] - .contextual_help - .is_some()); + assert!( + radarr_data.movie_info_tabs.tabs[0] + .contextual_help + .is_some() + ); assert_eq!( radarr_data.movie_info_tabs.tabs[0].contextual_help.unwrap(), &MOVIE_DETAILS_CONTEXT_CLUES @@ -206,9 +208,11 @@ mod tests { radarr_data.movie_info_tabs.tabs[1].route, ActiveRadarrBlock::MovieHistory.into() ); - assert!(radarr_data.movie_info_tabs.tabs[1] - .contextual_help - .is_some()); + assert!( + radarr_data.movie_info_tabs.tabs[1] + .contextual_help + .is_some() + ); assert_eq!( radarr_data.movie_info_tabs.tabs[1].contextual_help.unwrap(), &MOVIE_DETAILS_CONTEXT_CLUES @@ -220,9 +224,11 @@ mod tests { radarr_data.movie_info_tabs.tabs[2].route, ActiveRadarrBlock::FileInfo.into() ); - assert!(radarr_data.movie_info_tabs.tabs[2] - .contextual_help - .is_some()); + assert!( + radarr_data.movie_info_tabs.tabs[2] + .contextual_help + .is_some() + ); assert_eq!( radarr_data.movie_info_tabs.tabs[2].contextual_help.unwrap(), &MOVIE_DETAILS_CONTEXT_CLUES @@ -234,9 +240,11 @@ mod tests { radarr_data.movie_info_tabs.tabs[3].route, ActiveRadarrBlock::Cast.into() ); - assert!(radarr_data.movie_info_tabs.tabs[3] - .contextual_help - .is_some()); + assert!( + radarr_data.movie_info_tabs.tabs[3] + .contextual_help + .is_some() + ); assert_eq!( radarr_data.movie_info_tabs.tabs[3].contextual_help.unwrap(), &MOVIE_DETAILS_CONTEXT_CLUES @@ -248,9 +256,11 @@ mod tests { radarr_data.movie_info_tabs.tabs[4].route, ActiveRadarrBlock::Crew.into() ); - assert!(radarr_data.movie_info_tabs.tabs[4] - .contextual_help - .is_some()); + assert!( + radarr_data.movie_info_tabs.tabs[4] + .contextual_help + .is_some() + ); assert_eq!( radarr_data.movie_info_tabs.tabs[4].contextual_help.unwrap(), &MOVIE_DETAILS_CONTEXT_CLUES @@ -262,9 +272,11 @@ mod tests { radarr_data.movie_info_tabs.tabs[5].route, ActiveRadarrBlock::ManualSearch.into() ); - assert!(radarr_data.movie_info_tabs.tabs[5] - .contextual_help - .is_some()); + assert!( + radarr_data.movie_info_tabs.tabs[5] + .contextual_help + .is_some() + ); assert_eq!( radarr_data.movie_info_tabs.tabs[5].contextual_help.unwrap(), &MANUAL_MOVIE_SEARCH_CONTEXT_CLUES @@ -277,12 +289,12 @@ mod tests { use pretty_assertions::assert_eq; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, BLOCKLIST_BLOCKS, - COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, DELETE_MOVIE_BLOCKS, + ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, ActiveRadarrBlock, BLOCKLIST_BLOCKS, + COLLECTION_DETAILS_BLOCKS, COLLECTIONS_BLOCKS, DELETE_MOVIE_BLOCKS, DELETE_MOVIE_SELECTION_BLOCKS, DOWNLOADS_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, - INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, LIBRARY_BLOCKS, + INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, ROOT_FOLDERS_BLOCKS, SYSTEM_DETAILS_BLOCKS, }; @@ -359,8 +371,10 @@ mod tests { assert!( EDIT_COLLECTION_BLOCKS.contains(&ActiveRadarrBlock::EditCollectionRootFolderPathInput) ); - assert!(EDIT_COLLECTION_BLOCKS - .contains(&ActiveRadarrBlock::EditCollectionSelectMinimumAvailability)); + assert!( + EDIT_COLLECTION_BLOCKS + .contains(&ActiveRadarrBlock::EditCollectionSelectMinimumAvailability) + ); assert!( EDIT_COLLECTION_BLOCKS.contains(&ActiveRadarrBlock::EditCollectionSelectQualityProfile) ); @@ -447,18 +461,26 @@ mod tests { INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput) ); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsConfirmPrompt)); - assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsMaximumSizeInput)); + assert!( + INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsMaximumSizeInput) + ); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsMinimumAgeInput)); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsRetentionInput)); assert!( INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput) ); - assert!(INDEXER_SETTINGS_BLOCKS - .contains(&ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs)); - assert!(INDEXER_SETTINGS_BLOCKS - .contains(&ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags)); - assert!(INDEXER_SETTINGS_BLOCKS - .contains(&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput)); + assert!( + INDEXER_SETTINGS_BLOCKS + .contains(&ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs) + ); + assert!( + INDEXER_SETTINGS_BLOCKS + .contains(&ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags) + ); + assert!( + INDEXER_SETTINGS_BLOCKS + .contains(&ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput) + ); } #[test] diff --git a/src/models/servarr_data/servarr_data_tests.rs b/src/models/servarr_data/servarr_data_tests.rs index 5ee250e..d7bc539 100644 --- a/src/models/servarr_data/servarr_data_tests.rs +++ b/src/models/servarr_data/servarr_data_tests.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { - use crate::models::servarr_data::ActiveKeybindingBlock; use crate::models::Route; + use crate::models::servarr_data::ActiveKeybindingBlock; use pretty_assertions::assert_eq; #[test] diff --git a/src/models/servarr_data/sonarr/modals.rs b/src/models/servarr_data/sonarr/modals.rs index 0f6f043..026c974 100644 --- a/src/models/servarr_data/sonarr/modals.rs +++ b/src/models/servarr_data/sonarr/modals.rs @@ -9,12 +9,12 @@ use crate::{ MANUAL_SEASON_SEARCH_CONTEXT_CLUES, SEASON_DETAILS_CONTEXT_CLUES, SEASON_HISTORY_CONTEXT_CLUES, }, models::{ + HorizontallyScrollableText, ScrollableText, TabRoute, TabState, servarr_data::modals::EditIndexerModal, servarr_models::{Indexer, RootFolder}, sonarr_models::{Episode, Series, SeriesMonitor, SeriesType, SonarrHistoryItem, SonarrRelease}, stateful_list::StatefulList, stateful_table::StatefulTable, - HorizontallyScrollableText, ScrollableText, TabRoute, TabState, }, }; @@ -45,24 +45,12 @@ impl From<&SonarrData<'_>> for AddSeriesModal { add_series_modal .series_type_list .set_items(Vec::from_iter(SeriesType::iter())); - let mut quality_profile_names: Vec = sonarr_data - .quality_profile_map - .right_values() - .cloned() - .collect(); - quality_profile_names.sort(); add_series_modal .quality_profile_list - .set_items(quality_profile_names); - let mut language_profile_names: Vec = sonarr_data - .language_profiles_map - .right_values() - .cloned() - .collect(); - language_profile_names.sort(); + .set_items(sonarr_data.sorted_quality_profile_names()); add_series_modal .language_profile_list - .set_items(language_profile_names); + .set_items(sonarr_data.sorted_language_profile_names()); add_series_modal .root_folder_list .set_items(sonarr_data.root_folders.items.to_vec()); @@ -86,61 +74,56 @@ impl From<&SonarrData<'_>> for EditIndexerModal { } = sonarr_data.indexers.current_selection(); let seed_ratio_field_option = fields .as_ref() - .unwrap() + .expect("indexer fields must exist") .iter() - .find(|field| field.name.as_ref().unwrap() == "seedCriteria.seedRatio"); + .find(|field| { + field.name.as_ref().expect("indexer field name must exist") == "seedCriteria.seedRatio" + }); let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option { seed_ratio_field.value.clone() } else { None }; - edit_indexer_modal.name = name.clone().unwrap().into(); + edit_indexer_modal.name = name.clone().expect("indexer name must exist").into(); edit_indexer_modal.enable_rss = Some(*enable_rss); edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search); edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search); edit_indexer_modal.priority = *priority; edit_indexer_modal.url = fields .as_ref() - .unwrap() + .expect("indexer fields must exist") .iter() - .find(|field| field.name.as_ref().unwrap() == "baseUrl") - .unwrap() + .find(|field| field.name.as_ref().expect("indexer field name must exist") == "baseUrl") + .expect("baseUrl field must exist") .value .clone() - .unwrap() + .expect("baseUrl field value must exist") .as_str() - .unwrap() + .expect("baseUrl field value must be a string") .into(); edit_indexer_modal.api_key = fields .as_ref() - .unwrap() + .expect("indexer fields must exist") .iter() - .find(|field| field.name.as_ref().unwrap() == "apiKey") - .unwrap() + .find(|field| field.name.as_ref().expect("indexer field name must exist") == "apiKey") + .expect("apiKey field must exist") .value .clone() - .unwrap() + .expect("apiKey field value must exist") .as_str() - .unwrap() + .expect("apiKey field value must be a string") .into(); if let Some(seed_ratio_value) = seed_ratio_value_option { - edit_indexer_modal.seed_ratio = seed_ratio_value.as_f64().unwrap().to_string().into(); + edit_indexer_modal.seed_ratio = seed_ratio_value + .as_f64() + .expect("Seed ratio value must be a valid f64") + .to_string() + .into(); } - edit_indexer_modal.tags = tags - .iter() - .map(|tag_id| { - sonarr_data - .tags_map - .get_by_left(&tag_id.as_i64().unwrap()) - .unwrap() - .clone() - }) - .collect::>() - .join(", ") - .into(); + edit_indexer_modal.tags = sonarr_data.tag_ids_to_display(tags).into(); edit_indexer_modal } @@ -175,18 +158,7 @@ impl From<&SonarrData<'_>> for EditSeriesModal { .series_type_list .set_items(Vec::from_iter(SeriesType::iter())); edit_series_modal.path = path.clone().into(); - edit_series_modal.tags = tags - .iter() - .map(|tag_id| { - sonarr_data - .tags_map - .get_by_left(&tag_id.as_i64().unwrap()) - .unwrap() - .clone() - }) - .collect::>() - .join(", ") - .into(); + edit_series_modal.tags = sonarr_data.tag_ids_to_display(tags).into(); edit_series_modal.monitored = Some(*monitored); edit_series_modal.use_season_folders = Some(*season_folder); @@ -201,15 +173,9 @@ impl From<&SonarrData<'_>> for EditSeriesModal { .state .select(series_type_index); - let mut quality_profile_names: Vec = sonarr_data - .quality_profile_map - .right_values() - .cloned() - .collect(); - quality_profile_names.sort(); edit_series_modal .quality_profile_list - .set_items(quality_profile_names); + .set_items(sonarr_data.sorted_quality_profile_names()); let quality_profile_name = sonarr_data .quality_profile_map .get_by_left(quality_profile_id) @@ -223,15 +189,9 @@ impl From<&SonarrData<'_>> for EditSeriesModal { .quality_profile_list .state .select(quality_profile_index); - let mut language_profile_names: Vec = sonarr_data - .language_profiles_map - .right_values() - .cloned() - .collect(); - language_profile_names.sort(); edit_series_modal .language_profile_list - .set_items(language_profile_names); + .set_items(sonarr_data.sorted_language_profile_names()); let language_profile_name = sonarr_data .language_profiles_map .get_by_left(language_profile_id) @@ -250,6 +210,7 @@ impl From<&SonarrData<'_>> for EditSeriesModal { } } +#[cfg_attr(test, derive(Debug))] pub struct EpisodeDetailsModal { pub episode_details: ScrollableText, pub file_details: String, diff --git a/src/models/servarr_data/sonarr/modals_tests.rs b/src/models/servarr_data/sonarr/modals_tests.rs index 5aa259a..0a867c8 100644 --- a/src/models/servarr_data/sonarr/modals_tests.rs +++ b/src/models/servarr_data/sonarr/modals_tests.rs @@ -255,9 +255,11 @@ mod tests { episode_details_modal.episode_details_tabs.tabs[0].route, ActiveSonarrBlock::EpisodeDetails.into() ); - assert!(episode_details_modal.episode_details_tabs.tabs[0] - .contextual_help - .is_some()); + assert!( + episode_details_modal.episode_details_tabs.tabs[0] + .contextual_help + .is_some() + ); assert_eq!( episode_details_modal.episode_details_tabs.tabs[0] .contextual_help @@ -277,9 +279,11 @@ mod tests { episode_details_modal.episode_details_tabs.tabs[1].route, ActiveSonarrBlock::EpisodeHistory.into() ); - assert!(episode_details_modal.episode_details_tabs.tabs[1] - .contextual_help - .is_some()); + assert!( + episode_details_modal.episode_details_tabs.tabs[1] + .contextual_help + .is_some() + ); assert_eq!( episode_details_modal.episode_details_tabs.tabs[1] .contextual_help @@ -299,9 +303,11 @@ mod tests { episode_details_modal.episode_details_tabs.tabs[2].route, ActiveSonarrBlock::EpisodeFile.into() ); - assert!(episode_details_modal.episode_details_tabs.tabs[2] - .contextual_help - .is_some()); + assert!( + episode_details_modal.episode_details_tabs.tabs[2] + .contextual_help + .is_some() + ); assert_eq!( episode_details_modal.episode_details_tabs.tabs[2] .contextual_help @@ -321,9 +327,11 @@ mod tests { episode_details_modal.episode_details_tabs.tabs[3].route, ActiveSonarrBlock::ManualEpisodeSearch.into() ); - assert!(episode_details_modal.episode_details_tabs.tabs[3] - .contextual_help - .is_some()); + assert!( + episode_details_modal.episode_details_tabs.tabs[3] + .contextual_help + .is_some() + ); assert_eq!( episode_details_modal.episode_details_tabs.tabs[3] .contextual_help @@ -356,9 +364,11 @@ mod tests { season_details_modal.season_details_tabs.tabs[0].route, ActiveSonarrBlock::SeasonDetails.into() ); - assert!(season_details_modal.season_details_tabs.tabs[0] - .contextual_help - .is_some()); + assert!( + season_details_modal.season_details_tabs.tabs[0] + .contextual_help + .is_some() + ); assert_eq!( season_details_modal.season_details_tabs.tabs[0] .contextual_help @@ -378,9 +388,11 @@ mod tests { season_details_modal.season_details_tabs.tabs[1].route, ActiveSonarrBlock::SeasonHistory.into() ); - assert!(season_details_modal.season_details_tabs.tabs[1] - .contextual_help - .is_some()); + assert!( + season_details_modal.season_details_tabs.tabs[1] + .contextual_help + .is_some() + ); assert_eq!( season_details_modal.season_details_tabs.tabs[1] .contextual_help @@ -400,9 +412,11 @@ mod tests { season_details_modal.season_details_tabs.tabs[2].route, ActiveSonarrBlock::ManualSeasonSearch.into() ); - assert!(season_details_modal.season_details_tabs.tabs[2] - .contextual_help - .is_some()); + assert!( + season_details_modal.season_details_tabs.tabs[2] + .contextual_help + .is_some() + ); assert_eq!( season_details_modal.season_details_tabs.tabs[2] .contextual_help diff --git a/src/models/servarr_data/sonarr/sonarr_data.rs b/src/models/servarr_data/sonarr/sonarr_data.rs index 6caa97d..8713468 100644 --- a/src/models/servarr_data/sonarr/sonarr_data.rs +++ b/src/models/servarr_data/sonarr/sonarr_data.rs @@ -1,7 +1,4 @@ -use bimap::BiMap; -use chrono::{DateTime, Utc}; -use strum::EnumIter; - +use super::modals::{AddSeriesModal, EditSeriesModal, SeasonDetailsModal}; use crate::{ app::{ context_clues::{ @@ -14,6 +11,7 @@ use crate::{ }, }, models::{ + BlockSelectionState, HorizontallyScrollableText, Route, ScrollableText, TabRoute, TabState, servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem}, servarr_models::{DiskSpace, Indexer, QueueEvent, RootFolder}, sonarr_models::{ @@ -22,12 +20,33 @@ use crate::{ }, stateful_list::StatefulList, stateful_table::StatefulTable, - BlockSelectionState, HorizontallyScrollableText, Route, ScrollableText, TabRoute, TabState, }, network::sonarr_network::SonarrEvent, }; - -use super::modals::{AddSeriesModal, EditSeriesModal, SeasonDetailsModal}; +use bimap::BiMap; +use chrono::{DateTime, Utc}; +use serde_json::Number; +use strum::EnumIter; +#[cfg(test)] +use { + super::modals::EpisodeDetailsModal, + crate::models::sonarr_models::{SeriesMonitor, SeriesType}, + crate::models::stateful_table::SortOption, + crate::network::servarr_test_utils::diskspace, + crate::network::servarr_test_utils::indexer_test_result, + crate::network::servarr_test_utils::queued_event, + crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ + add_series_search_result, blocklist_item, download_record, history_item, indexer, + indexer_settings, log_line, root_folder, + }, + crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ + episode, episode_file, language_profiles_map, quality_profile_map, season, series, tags_map, + task, torrent_release, updates, usenet_release, + }, + crate::sort_option, + strum::IntoEnumIterator, + strum_macros::{Display, EnumString}, +}; #[cfg(test)] #[path = "sonarr_data_tests.rs"] @@ -87,6 +106,29 @@ impl SonarrData<'_> { self.seasons = StatefulTable::default(); self.series_info_tabs.index = 0; } + + pub fn tag_ids_to_display(&self, tag_ids: &[Number]) -> String { + tag_ids + .iter() + .filter_map(|tag_id| { + let id = tag_id.as_i64()?; + self.tags_map.get_by_left(&id).cloned() + }) + .collect::>() + .join(", ") + } + + pub fn sorted_quality_profile_names(&self) -> Vec { + let mut names: Vec = self.quality_profile_map.right_values().cloned().collect(); + names.sort(); + names + } + + pub fn sorted_language_profile_names(&self) -> Vec { + let mut names: Vec = self.language_profiles_map.right_values().cloned().collect(); + names.sort(); + names + } } impl<'a> Default for SonarrData<'a> { @@ -188,7 +230,164 @@ impl<'a> Default for SonarrData<'a> { } } +#[cfg(test)] +impl SonarrData<'_> { + pub fn test_default_fully_populated() -> Self { + let quality_profile_name = "Bluray-1080p".to_owned(); + let language_profile_name = "English".to_owned(); + let mut add_searched_series = StatefulTable::default(); + add_searched_series.set_items(vec![add_series_search_result()]); + + let mut add_series_modal = AddSeriesModal { + use_season_folder: true, + tags: "alex".into(), + ..AddSeriesModal::default() + }; + add_series_modal + .root_folder_list + .set_items(vec![root_folder()]); + add_series_modal + .monitor_list + .set_items(SeriesMonitor::iter().collect()); + add_series_modal + .quality_profile_list + .set_items(vec![quality_profile_name.clone()]); + add_series_modal + .language_profile_list + .set_items(vec![language_profile_name.clone()]); + add_series_modal + .series_type_list + .set_items(SeriesType::iter().collect()); + + let edit_indexer_modal = EditIndexerModal { + name: "DrunkenSlug".into(), + enable_rss: Some(true), + enable_automatic_search: Some(true), + enable_interactive_search: Some(true), + url: "http://127.0.0.1:9696/1/".into(), + api_key: "someApiKey".into(), + seed_ratio: "ratio".into(), + tags: "25".into(), + priority: 1, + }; + + let mut edit_series_modal = EditSeriesModal { + monitored: Some(true), + use_season_folders: Some(true), + path: "/nfs/tv".into(), + tags: "alex".into(), + ..EditSeriesModal::default() + }; + edit_series_modal + .series_type_list + .set_items(SeriesType::iter().collect()); + edit_series_modal + .quality_profile_list + .set_items(vec![quality_profile_name.clone()]); + edit_series_modal + .language_profile_list + .set_items(vec![language_profile_name.clone()]); + + let mut indexer_test_all_results = StatefulTable::default(); + indexer_test_all_results.set_items(vec![indexer_test_result()]); + + let mut episode_details_modal = EpisodeDetailsModal { + episode_details: ScrollableText::with_string("Some episode details".into()), + file_details: "Some file details".to_owned(), + audio_details: "Some audio details".to_owned(), + video_details: "Some video details".to_owned(), + ..EpisodeDetailsModal::default() + }; + episode_details_modal + .episode_history + .set_items(vec![history_item()]); + episode_details_modal + .episode_releases + .set_items(vec![torrent_release(), usenet_release()]); + episode_details_modal + .episode_releases + .sorting(vec![sort_option!(indexer_id)]); + + let mut season_details_modal = SeasonDetailsModal { + episode_details_modal: Some(episode_details_modal), + ..SeasonDetailsModal::default() + }; + season_details_modal.episodes.set_items(vec![episode()]); + season_details_modal.episodes.search = Some("episode search".into()); + season_details_modal + .episode_files + .set_items(vec![episode_file()]); + season_details_modal + .season_history + .set_items(vec![history_item()]); + season_details_modal.season_history.search = Some("season history search".into()); + season_details_modal.season_history.filter = Some("season history filter".into()); + season_details_modal + .season_history + .sorting(vec![sort_option!(id)]); + season_details_modal + .season_releases + .set_items(vec![torrent_release(), usenet_release()]); + season_details_modal + .season_releases + .sorting(vec![sort_option!(indexer_id)]); + + let mut series_history = StatefulTable::default(); + series_history.set_items(vec![history_item()]); + series_history.sorting(vec![sort_option!(id)]); + series_history.search = Some("series history search".into()); + series_history.filter = Some("series history filter".into()); + + let mut sonarr_data = SonarrData { + add_list_exclusion: true, + add_searched_series: Some(add_searched_series), + add_series_modal: Some(add_series_modal), + add_series_search: Some("something".into()), + delete_series_files: true, + disk_space_vec: vec![diskspace()], + edit_indexer_modal: Some(edit_indexer_modal), + edit_root_folder: Some("/nfs/tv".into()), + edit_series_modal: Some(edit_series_modal), + indexer_settings: Some(indexer_settings()), + indexer_test_all_results: Some(indexer_test_all_results), + indexer_test_errors: Some("error".to_string()), + language_profiles_map: language_profiles_map(), + quality_profile_map: quality_profile_map(), + season_details_modal: Some(season_details_modal), + series_history: Some(series_history), + start_time: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T21:29:16Z").unwrap()), + tags_map: tags_map(), + updates: updates(), + version: "1.2.3.4".to_owned(), + ..SonarrData::default() + }; + + sonarr_data.blocklist.set_items(vec![blocklist_item()]); + sonarr_data.blocklist.sorting(vec![sort_option!(id)]); + sonarr_data.downloads.set_items(vec![download_record()]); + sonarr_data.history.set_items(vec![history_item()]); + sonarr_data.history.sorting(vec![sort_option!(id)]); + sonarr_data.history.search = Some("test search".into()); + sonarr_data.history.filter = Some("test filter".into()); + sonarr_data.indexers.set_items(vec![indexer()]); + sonarr_data.queued_events.set_items(vec![queued_event()]); + sonarr_data.root_folders.set_items(vec![root_folder()]); + sonarr_data.seasons.set_items(vec![season()]); + sonarr_data.seasons.search = Some("season search".into()); + sonarr_data.series.set_items(vec![series()]); + sonarr_data.series.sorting(vec![sort_option!(id)]); + sonarr_data.series.search = Some("series search".into()); + sonarr_data.series.filter = Some("series filter".into()); + sonarr_data.logs.set_items(vec![log_line().into()]); + sonarr_data.log_details.set_items(vec![log_line().into()]); + sonarr_data.tasks.set_items(vec![task()]); + + sonarr_data + } +} + #[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)] +#[cfg_attr(test, derive(Display, EnumString))] pub enum ActiveSonarrBlock { AddRootFolderPrompt, AddSeriesAlreadyInLibrary, diff --git a/src/models/servarr_data/sonarr/sonarr_data_tests.rs b/src/models/servarr_data/sonarr/sonarr_data_tests.rs index 9b666dd..92b9275 100644 --- a/src/models/servarr_data/sonarr/sonarr_data_tests.rs +++ b/src/models/servarr_data/sonarr/sonarr_data_tests.rs @@ -18,8 +18,8 @@ mod tests { }, }, models::{ - servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}, BlockSelectionState, Route, + servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData}, }, }; @@ -209,9 +209,11 @@ mod tests { sonarr_data.series_info_tabs.tabs[0].route, ActiveSonarrBlock::SeriesDetails.into() ); - assert!(sonarr_data.series_info_tabs.tabs[0] - .contextual_help - .is_some()); + assert!( + sonarr_data.series_info_tabs.tabs[0] + .contextual_help + .is_some() + ); assert_eq!( sonarr_data.series_info_tabs.tabs[0] .contextual_help @@ -225,9 +227,11 @@ mod tests { sonarr_data.series_info_tabs.tabs[1].route, ActiveSonarrBlock::SeriesHistory.into() ); - assert!(sonarr_data.series_info_tabs.tabs[1] - .contextual_help - .is_some()); + assert!( + sonarr_data.series_info_tabs.tabs[1] + .contextual_help + .is_some() + ); assert_eq!( sonarr_data.series_info_tabs.tabs[1] .contextual_help @@ -240,11 +244,11 @@ mod tests { mod active_sonarr_block_tests { use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, ADD_SERIES_BLOCKS, ADD_SERIES_SELECTION_BLOCKS, BLOCKLIST_BLOCKS, + ADD_SERIES_BLOCKS, ADD_SERIES_SELECTION_BLOCKS, ActiveSonarrBlock, BLOCKLIST_BLOCKS, DELETE_SERIES_BLOCKS, DELETE_SERIES_SELECTION_BLOCKS, DOWNLOADS_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, EDIT_SERIES_BLOCKS, - EDIT_SERIES_SELECTION_BLOCKS, EPISODE_DETAILS_BLOCKS, HISTORY_BLOCKS, INDEXERS_BLOCKS, - INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, LIBRARY_BLOCKS, + EDIT_SERIES_SELECTION_BLOCKS, EPISODE_DETAILS_BLOCKS, HISTORY_BLOCKS, + INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, INDEXERS_BLOCKS, LIBRARY_BLOCKS, ROOT_FOLDERS_BLOCKS, SEASON_DETAILS_BLOCKS, SERIES_DETAILS_BLOCKS, SYSTEM_DETAILS_BLOCKS, }; @@ -394,7 +398,9 @@ mod tests { assert!(DELETE_SERIES_BLOCKS.contains(&ActiveSonarrBlock::DeleteSeriesPrompt)); assert!(DELETE_SERIES_BLOCKS.contains(&ActiveSonarrBlock::DeleteSeriesConfirmPrompt)); assert!(DELETE_SERIES_BLOCKS.contains(&ActiveSonarrBlock::DeleteSeriesToggleDeleteFile)); - assert!(DELETE_SERIES_BLOCKS.contains(&ActiveSonarrBlock::DeleteSeriesToggleAddListExclusion)); + assert!( + DELETE_SERIES_BLOCKS.contains(&ActiveSonarrBlock::DeleteSeriesToggleAddListExclusion) + ); } #[test] @@ -533,7 +539,9 @@ mod tests { assert_eq!(INDEXER_SETTINGS_BLOCKS.len(), 6); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveSonarrBlock::AllIndexerSettingsPrompt)); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveSonarrBlock::IndexerSettingsConfirmPrompt)); - assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveSonarrBlock::IndexerSettingsMaximumSizeInput)); + assert!( + INDEXER_SETTINGS_BLOCKS.contains(&ActiveSonarrBlock::IndexerSettingsMaximumSizeInput) + ); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveSonarrBlock::IndexerSettingsMinimumAgeInput)); assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveSonarrBlock::IndexerSettingsRetentionInput)); assert!( @@ -652,8 +660,12 @@ mod tests { assert!(EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::EpisodeFile)); assert!(EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::ManualEpisodeSearch)); assert!(EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::ManualEpisodeSearchSortPrompt)); - assert!(EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt)); - assert!(EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::AutomaticallySearchEpisodePrompt)); + assert!( + EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt) + ); + assert!( + EPISODE_DETAILS_BLOCKS.contains(&ActiveSonarrBlock::AutomaticallySearchEpisodePrompt) + ); } } } diff --git a/src/models/servarr_data/sonarr/sonarr_test_utils.rs b/src/models/servarr_data/sonarr/sonarr_test_utils.rs index 2dd552a..7e3ea53 100644 --- a/src/models/servarr_data/sonarr/sonarr_test_utils.rs +++ b/src/models/servarr_data/sonarr/sonarr_test_utils.rs @@ -3,13 +3,13 @@ pub mod utils { use crate::models::servarr_models::{Indexer, RootFolder}; use crate::models::sonarr_models::{BlocklistItem, Series}; use crate::models::{ + HorizontallyScrollableText, ScrollableText, servarr_data::sonarr::{ modals::{EpisodeDetailsModal, SeasonDetailsModal}, sonarr_data::SonarrData, }, sonarr_models::{AddSeriesSearchResult, Episode, Season, SonarrHistoryItem, SonarrRelease}, stateful_table::StatefulTable, - HorizontallyScrollableText, ScrollableText, }; pub fn create_test_sonarr_data<'a>() -> SonarrData<'a> { diff --git a/src/models/sonarr_models.rs b/src/models/sonarr_models.rs index 57c7476..3dda720 100644 --- a/src/models/sonarr_models.rs +++ b/src/models/sonarr_models.rs @@ -11,11 +11,11 @@ use strum::EnumIter; use strum_macros::Display; use super::{ + HorizontallyScrollableText, Serdeable, servarr_models::{ DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper, QueueEvent, RootFolder, SecurityConfig, Tag, Update, }, - HorizontallyScrollableText, Serdeable, }; #[cfg(test)] diff --git a/src/models/sonarr_models_tests.rs b/src/models/sonarr_models_tests.rs index 632bacb..30c96fb 100644 --- a/src/models/sonarr_models_tests.rs +++ b/src/models/sonarr_models_tests.rs @@ -4,6 +4,7 @@ mod tests { use serde_json::json; use crate::models::{ + Serdeable, servarr_models::{ DiskSpace, HostConfig, Indexer, IndexerTestResult, Language, Log, LogResponse, QualityProfile, QueueEvent, RootFolder, SecurityConfig, Tag, Update, @@ -14,7 +15,6 @@ mod tests { SeriesStatus, SeriesType, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease, SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus, }, - Serdeable, }; #[test] diff --git a/src/models/stateful_list.rs b/src/models/stateful_list.rs index d31d79f..ab41dcd 100644 --- a/src/models/stateful_list.rs +++ b/src/models/stateful_list.rs @@ -7,6 +7,7 @@ use std::fmt::Debug; mod stateful_list_tests; #[derive(Default)] +#[cfg_attr(test, derive(Debug))] pub struct StatefulList { pub state: ListState, pub items: Vec, diff --git a/src/models/stateful_list_tests.rs b/src/models/stateful_list_tests.rs index 3101cfe..a798d09 100644 --- a/src/models/stateful_list_tests.rs +++ b/src/models/stateful_list_tests.rs @@ -1,26 +1,26 @@ #[cfg(test)] mod tests { - use crate::models::stateful_list::StatefulList; use crate::models::Scrollable; - use pretty_assertions::{assert_eq, assert_str_eq}; + use crate::models::stateful_list::StatefulList; + use pretty_assertions::assert_str_eq; #[test] fn test_stateful_list_scrolling_on_empty_list_performs_no_op() { let mut stateful_list: StatefulList = StatefulList::default(); - assert_eq!(stateful_list.state.selected(), None); + assert_none!(stateful_list.state.selected()); stateful_list.scroll_up(); - assert_eq!(stateful_list.state.selected(), None); + assert_none!(stateful_list.state.selected()); stateful_list.scroll_down(); - assert_eq!(stateful_list.state.selected(), None); + assert_none!(stateful_list.state.selected()); stateful_list.scroll_to_top(); - assert_eq!(stateful_list.state.selected(), None); + assert_none!(stateful_list.state.selected()); stateful_list.scroll_to_bottom(); } @@ -29,31 +29,31 @@ mod tests { fn test_stateful_list_scroll() { let mut stateful_list = create_test_stateful_list(); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); stateful_list.scroll_down(); - assert_eq!(stateful_list.state.selected(), Some(1)); + assert_some_eq_x!(stateful_list.state.selected(), 1); stateful_list.scroll_down(); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); stateful_list.scroll_up(); - assert_eq!(stateful_list.state.selected(), Some(1)); + assert_some_eq_x!(stateful_list.state.selected(), 1); stateful_list.scroll_up(); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); stateful_list.scroll_to_bottom(); - assert_eq!(stateful_list.state.selected(), Some(1)); + assert_some_eq_x!(stateful_list.state.selected(), 1); stateful_list.scroll_to_top(); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); } #[test] @@ -63,17 +63,17 @@ mod tests { stateful_list.set_items(items_vec.clone()); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); stateful_list.state.select(Some(1)); stateful_list.set_items(items_vec.clone()); - assert_eq!(stateful_list.state.selected(), Some(1)); + assert_some_eq_x!(stateful_list.state.selected(), 1); stateful_list.state.select(Some(3)); stateful_list.set_items(items_vec); - assert_eq!(stateful_list.state.selected(), Some(2)); + assert_some_eq_x!(stateful_list.state.selected(), 2); } #[test] @@ -91,15 +91,15 @@ mod tests { fn test_stateful_list_scroll_up() { let mut stateful_list = create_test_stateful_list(); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); stateful_list.scroll_up(); - assert_eq!(stateful_list.state.selected(), Some(1)); + assert_some_eq_x!(stateful_list.state.selected(), 1); stateful_list.scroll_up(); - assert_eq!(stateful_list.state.selected(), Some(0)); + assert_some_eq_x!(stateful_list.state.selected(), 0); } #[test] @@ -110,7 +110,7 @@ mod tests { stateful_list = StatefulList::default(); - assert!(stateful_list.is_empty()); + assert_is_empty!(stateful_list); } fn create_test_stateful_list() -> StatefulList<&'static str> { diff --git a/src/models/stateful_table.rs b/src/models/stateful_table.rs index cd2cc28..a029570 100644 --- a/src/models/stateful_table.rs +++ b/src/models/stateful_table.rs @@ -1,6 +1,6 @@ use crate::models::stateful_list::StatefulList; use crate::models::{ - strip_non_search_characters, HorizontallyScrollableText, Paginated, Scrollable, + HorizontallyScrollableText, Paginated, Scrollable, strip_non_search_characters, }; use ratatui::widgets::TableState; use std::cmp::Ordering; @@ -31,6 +31,7 @@ where impl Eq for SortOption where T: Clone + PartialEq + Eq + Debug {} #[derive(Default)] +#[cfg_attr(test, derive(Debug))] pub struct StatefulTable where T: Clone + PartialEq + Eq + Debug, @@ -50,117 +51,46 @@ where T: Clone + PartialEq + Eq + Debug, { fn scroll_down(&mut self) { - if let Some(filtered_items) = self.filtered_items.as_ref() { - if filtered_items.is_empty() { - return; - } - - match self.filtered_state.as_ref().unwrap().selected() { - Some(i) => { - if i >= filtered_items.len() - 1 { - self.filtered_state.as_mut().unwrap().select_first(); - } else { - self.filtered_state.as_mut().unwrap().select_next(); - } - } - None => self.filtered_state.as_mut().unwrap().select_first(), - }; - + let items_len = self.active_items().len(); + if items_len == 0 { return; } - if self.items.is_empty() { - return; + let state = self.active_state_mut(); + match state.selected() { + Some(i) if i >= items_len - 1 => state.select_first(), + Some(_) => state.select_next(), + None => state.select_first(), } - - match self.state.selected() { - Some(i) => { - if i >= self.items.len() - 1 { - self.state.select_first(); - } else { - self.state.select_next(); - } - } - None => self.state.select_first(), - }; } fn scroll_up(&mut self) { - if let Some(filtered_items) = self.filtered_items.as_ref() { - if filtered_items.is_empty() { - return; - } - - match self.filtered_state.as_ref().unwrap().selected() { - Some(i) => { - if i == 0 { - self - .filtered_state - .as_mut() - .unwrap() - .select(Some(filtered_items.len() - 1)); - } else { - self.filtered_state.as_mut().unwrap().select_previous(); - } - } - None => self.filtered_state.as_mut().unwrap().select_first(), - }; - + let items_len = self.active_items().len(); + if items_len == 0 { return; } - if self.items.is_empty() { - return; + let state = self.active_state_mut(); + match state.selected() { + Some(0) => state.select(Some(items_len - 1)), + Some(_) => state.select_previous(), + None => state.select_first(), } - - match self.state.selected() { - Some(i) => { - if i == 0 { - self.state.select(Some(self.items.len() - 1)); - } else { - self.state.select_previous(); - } - } - None => self.state.select_first(), - }; } fn scroll_to_top(&mut self) { - if let Some(filtered_items) = self.filtered_items.as_ref() { - if filtered_items.is_empty() { - return; - } - - self.filtered_state.as_mut().unwrap().select_first(); + if self.active_items().is_empty() { return; } - - if self.items.is_empty() { - return; - } - - self.state.select_first(); + self.active_state_mut().select_first(); } fn scroll_to_bottom(&mut self) { - if let Some(filtered_items) = self.filtered_items.as_ref() { - if filtered_items.is_empty() { - return; - } - - self - .filtered_state - .as_mut() - .unwrap() - .select(Some(filtered_items.len() - 1)); + let items_len = self.active_items().len(); + if items_len == 0 { return; } - - if self.items.is_empty() { - return; - } - - self.state.select(Some(self.items.len() - 1)); + self.active_state_mut().select(Some(items_len - 1)); } } @@ -169,71 +99,56 @@ where T: Clone + PartialEq + Eq + Debug, { fn page_down(&mut self) { - if let Some(filtered_items) = self.filtered_items.as_ref() { - if filtered_items.is_empty() { - return; - } - - match self.filtered_state.as_ref().unwrap().selected() { - Some(i) => { - self - .filtered_state - .as_mut() - .unwrap() - .select(Some(i.saturating_add(20) % (filtered_items.len() - 1))); - } - None => self.filtered_state.as_mut().unwrap().select_first(), - }; - + let items_len = self.active_items().len(); + if items_len == 0 { return; } - if self.items.is_empty() { - return; + let state = self.active_state_mut(); + match state.selected() { + Some(i) => state.select(Some(i.saturating_add(20) % (items_len - 1))), + None => state.select_first(), } - - match self.state.selected() { - Some(i) => { - self - .state - .select(Some(i.saturating_add(20) % (self.items.len() - 1))); - } - None => self.state.select_first(), - }; } fn page_up(&mut self) { - if let Some(filtered_items) = self.filtered_items.as_ref() { - if filtered_items.is_empty() { - return; - } - - match self.filtered_state.as_ref().unwrap().selected() { - Some(i) => { - let len = filtered_items.len() - 1; - self - .filtered_state - .as_mut() - .unwrap() - .select(Some((i + len - (20 % len)) % len)); - } - None => self.filtered_state.as_mut().unwrap().select_last(), - }; - + let items_len = self.active_items().len(); + if items_len == 0 { return; } - if self.items.is_empty() { - return; - } - - match self.state.selected() { + let state = self.active_state_mut(); + match state.selected() { Some(i) => { - let len = self.items.len() - 1; - self.state.select(Some((i + len - (20 % len)) % len)); + let len = items_len - 1; + state.select(Some((i + len - (20 % len)) % len)); } - None => self.state.select_last(), - }; + None => state.select_last(), + } + } +} + +impl StatefulTable +where + T: Clone + PartialEq + Eq + Debug, +{ + fn active_items(&self) -> &[T] { + self + .filtered_items + .as_ref() + .map_or(&self.items[..], |items| &items[..]) + } + + fn active_state_mut(&mut self) -> &mut TableState { + if let Some(ref mut filtered_state) = self.filtered_state { + filtered_state + } else { + &mut self.state + } + } + + fn active_state(&self) -> &TableState { + self.filtered_state.as_ref().unwrap_or(&self.state) } } @@ -266,24 +181,13 @@ where } pub fn select_index(&mut self, index: Option) { - if let Some(filtered_state) = &mut self.filtered_state { - filtered_state.select(index); - } else { - self.state.select(index); - } + self.active_state_mut().select(index); } pub fn current_selection(&self) -> &T { - if let Some(filtered_items) = &self.filtered_items { - &filtered_items[self - .filtered_state - .as_ref() - .unwrap() - .selected() - .unwrap_or(0)] - } else { - &self.items[self.state.selected().unwrap_or(0)] - } + let items = self.active_items(); + let index = self.active_state().selected().unwrap_or(0); + &items[index] } pub fn sorting(&mut self, sort_options: Vec>) { diff --git a/src/models/stateful_table_tests.rs b/src/models/stateful_table_tests.rs index 924160b..4cb823e 100644 --- a/src/models/stateful_table_tests.rs +++ b/src/models/stateful_table_tests.rs @@ -10,19 +10,19 @@ mod tests { fn test_stateful_table_scrolling_on_empty_table_performs_no_op() { let mut stateful_table: StatefulTable = StatefulTable::default(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); stateful_table.scroll_up(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); stateful_table.scroll_down(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); stateful_table.scroll_to_top(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); stateful_table.scroll_to_bottom(); } @@ -35,46 +35,42 @@ mod tests { ..StatefulTable::default() }; - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); filtered_stateful_table.scroll_up(); - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); filtered_stateful_table.scroll_down(); - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); filtered_stateful_table.scroll_to_top(); - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); filtered_stateful_table.scroll_to_bottom(); @@ -84,110 +80,110 @@ mod tests { fn test_stateful_table_scroll() { let mut stateful_table = create_test_stateful_table(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.scroll_down(); - assert_eq!(stateful_table.state.selected(), Some(1)); + assert_some_eq_x!(stateful_table.state.selected(), 1); stateful_table.scroll_down(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.scroll_up(); - assert_eq!(stateful_table.state.selected(), Some(1)); + assert_some_eq_x!(stateful_table.state.selected(), 1); stateful_table.scroll_up(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.scroll_to_bottom(); - assert_eq!(stateful_table.state.selected(), Some(1)); + assert_some_eq_x!(stateful_table.state.selected(), 1); stateful_table.scroll_to_top(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); } #[test] fn test_stateful_table_filtered_items_scroll() { let mut filtered_stateful_table = create_test_filtered_stateful_table(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); filtered_stateful_table.scroll_down(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(1) + 1 ); filtered_stateful_table.scroll_down(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); filtered_stateful_table.scroll_up(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(1) + 1 ); filtered_stateful_table.scroll_up(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); filtered_stateful_table.scroll_to_bottom(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(1) + 1 ); filtered_stateful_table.scroll_to_top(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); } @@ -195,15 +191,15 @@ mod tests { fn test_stateful_table_pagination_on_empty_table_performs_no_op() { let mut stateful_table: StatefulTable = StatefulTable::default(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); stateful_table.page_down(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); stateful_table.page_up(); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); } #[test] @@ -214,35 +210,32 @@ mod tests { ..StatefulTable::default() }; - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); filtered_stateful_table.page_down(); - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); filtered_stateful_table.page_up(); - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); } @@ -260,53 +253,53 @@ mod tests { .collect(), ); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(0) + 0 ); stateful_table.page_down(); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(20) + 20 ); stateful_table.page_up(); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(0) + 0 ); stateful_table.page_up(); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(stateful_table.filtered_items.as_ref().unwrap().len() - 21) + stateful_table.filtered_items.as_ref().unwrap().len() - 21 ); stateful_table.page_down(); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(0) + 0 ); stateful_table.scroll_down(); stateful_table.page_up(); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(stateful_table.filtered_items.as_ref().unwrap().len() - 20) + stateful_table.filtered_items.as_ref().unwrap().len() - 20 ); stateful_table.scroll_down(); stateful_table.page_down(); - assert_eq!( + assert_some_eq_x!( stateful_table.filtered_state.as_ref().unwrap().selected(), - Some(2) + 2 ); } @@ -324,39 +317,39 @@ mod tests { .collect(), ); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.page_down(); - assert_eq!(stateful_table.state.selected(), Some(20)); + assert_some_eq_x!(stateful_table.state.selected(), 20); stateful_table.page_up(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.page_up(); - assert_eq!( + assert_some_eq_x!( stateful_table.state.selected(), - Some(stateful_table.items.len() - 21) + stateful_table.items.len() - 21 ); stateful_table.page_down(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.scroll_down(); stateful_table.page_up(); - assert_eq!( + assert_some_eq_x!( stateful_table.state.selected(), - Some(stateful_table.items.len() - 20) + stateful_table.items.len() - 20 ); stateful_table.scroll_down(); stateful_table.page_down(); - assert_eq!(stateful_table.state.selected(), Some(2)); + assert_some_eq_x!(stateful_table.state.selected(), 2); } #[test] @@ -366,17 +359,17 @@ mod tests { stateful_table.set_items(items_vec.clone()); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.state.select(Some(1)); stateful_table.set_items(items_vec.clone()); - assert_eq!(stateful_table.state.selected(), Some(1)); + assert_some_eq_x!(stateful_table.state.selected(), 1); stateful_table.state.select(Some(3)); stateful_table.set_items(items_vec); - assert_eq!(stateful_table.state.selected(), Some(2)); + assert_some_eq_x!(stateful_table.state.selected(), 2); } #[test] @@ -386,18 +379,15 @@ mod tests { filtered_stateful_table.set_filtered_items(filtered_items_vec.clone()); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) - ); - assert_eq!( - filtered_stateful_table.filtered_items, - Some(filtered_items_vec.clone()) + 0 ); + assert_some_eq_x!(&filtered_stateful_table.filtered_items, &filtered_items_vec); } #[test] @@ -602,50 +592,49 @@ mod tests { fn test_stateful_table_select_index() { let mut stateful_table = create_test_stateful_table(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.select_index(Some(1)); - assert_eq!(stateful_table.state.selected(), Some(1)); + assert_some_eq_x!(stateful_table.state.selected(), 1); stateful_table.select_index(None); - assert_eq!(stateful_table.state.selected(), None); + assert_none!(stateful_table.state.selected()); } #[test] fn test_filtered_stateful_table_select_index() { let mut filtered_stateful_table = create_test_filtered_stateful_table(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); filtered_stateful_table.select_index(Some(1)); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(1) + 1 ); filtered_stateful_table.select_index(None); - assert_eq!( + assert_none!( filtered_stateful_table .filtered_state .as_ref() .unwrap() - .selected(), - None + .selected() ); } @@ -653,50 +642,50 @@ mod tests { fn test_stateful_table_scroll_up() { let mut stateful_table = create_test_stateful_table(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); stateful_table.scroll_up(); - assert_eq!(stateful_table.state.selected(), Some(1)); + assert_some_eq_x!(stateful_table.state.selected(), 1); stateful_table.scroll_up(); - assert_eq!(stateful_table.state.selected(), Some(0)); + assert_some_eq_x!(stateful_table.state.selected(), 0); } #[test] fn test_filtered_stateful_table_scroll_up() { let mut filtered_stateful_table = create_test_filtered_stateful_table(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); filtered_stateful_table.scroll_up(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(1) + 1 ); filtered_stateful_table.scroll_up(); - assert_eq!( + assert_some_eq_x!( filtered_stateful_table .filtered_state .as_ref() .unwrap() .selected(), - Some(0) + 0 ); } @@ -711,9 +700,9 @@ mod tests { let has_matches = stateful_table.apply_filter(|&item| item); - assert_eq!(stateful_table.filter, None); - assert_eq!(stateful_table.filtered_items, Some(expected_items)); - assert_eq!(stateful_table.filtered_state, Some(expected_state)); + assert_none!(stateful_table.filter); + assert_some_eq_x!(&stateful_table.filtered_items, &expected_items); + assert_some_eq_x!(&stateful_table.filtered_state, &expected_state); assert!(has_matches); } @@ -725,9 +714,9 @@ mod tests { let has_matches = stateful_table.apply_filter(|&item| item); - assert_eq!(stateful_table.filter, None); - assert_eq!(stateful_table.filtered_items, None); - assert_eq!(stateful_table.filtered_state, None); + assert_none!(stateful_table.filter); + assert_none!(stateful_table.filtered_items); + assert_none!(stateful_table.filtered_state); assert!(!has_matches); } @@ -736,9 +725,9 @@ mod tests { let mut stateful_table = create_test_filtered_stateful_table(); stateful_table.reset_filter(); - assert_eq!(stateful_table.filter, None); - assert_eq!(stateful_table.filtered_items, None); - assert_eq!(stateful_table.filtered_state, None); + assert_none!(stateful_table.filter); + assert_none!(stateful_table.filtered_items); + assert_none!(stateful_table.filtered_state); } #[test] @@ -751,7 +740,7 @@ mod tests { let has_match = stateful_table.apply_search(|&item| item); - assert_eq!(stateful_table.search, None); + assert_none!(stateful_table.search); assert_eq!(stateful_table.state, expected_state); assert!(has_match); } @@ -764,7 +753,7 @@ mod tests { let has_match = stateful_table.apply_search(|&item| item); - assert_eq!(stateful_table.search, None); + assert_none!(stateful_table.search); assert!(!has_match); } @@ -778,8 +767,8 @@ mod tests { let has_match = stateful_table.apply_search(|&item| item); - assert_eq!(stateful_table.search, None); - assert_eq!(stateful_table.filtered_state, Some(expected_state)); + assert_none!(stateful_table.search); + assert_some_eq_x!(&stateful_table.filtered_state, &expected_state); assert!(has_match); } @@ -793,8 +782,8 @@ mod tests { let has_match = stateful_table.apply_search(|&item| item); - assert_eq!(stateful_table.search, None); - assert_eq!(stateful_table.filtered_state, Some(expected_state)); + assert_none!(stateful_table.search); + assert_some_eq_x!(&stateful_table.filtered_state, &expected_state); assert!(!has_match); } @@ -804,7 +793,7 @@ mod tests { stateful_table.search = Some("test".into()); stateful_table.reset_search(); - assert_eq!(stateful_table.search, None); + assert_none!(stateful_table.search); } #[test] @@ -815,7 +804,7 @@ mod tests { stateful_table = StatefulTable::default(); - assert!(stateful_table.is_empty()); + assert_is_empty!(stateful_table); } fn create_test_stateful_table() -> StatefulTable<&'static str> { diff --git a/src/models/stateful_tree_tests.rs b/src/models/stateful_tree_tests.rs index dcedf07..4548017 100644 --- a/src/models/stateful_tree_tests.rs +++ b/src/models/stateful_tree_tests.rs @@ -2,8 +2,8 @@ mod tests { use std::hash::{DefaultHasher, Hash, Hasher}; - use crate::models::stateful_tree::StatefulTree; use crate::models::Scrollable; + use crate::models::stateful_tree::StatefulTree; use managarr_tree_widget::{Tree, TreeItem, TreeState}; use pretty_assertions::{assert_eq, assert_str_eq}; use ratatui::buffer::Buffer; diff --git a/src/network/mod.rs b/src/network/mod.rs index 8f28b1f..b3bf0f4 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -1,13 +1,13 @@ use std::fmt::Debug; use std::sync::Arc; -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use async_trait::async_trait; use log::{debug, error, warn}; use regex::Regex; use reqwest::{Client, RequestBuilder}; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use sonarr_network::SonarrEvent; use strum_macros::Display; use tokio::select; @@ -26,8 +26,9 @@ pub mod sonarr_network; mod utils; #[cfg(test)] -#[path = "network_tests.rs"] mod network_tests; +#[cfg(test)] +pub mod servarr_test_utils; #[cfg_attr(test, automock)] #[async_trait] diff --git a/src/network/network_tests.rs b/src/network/network_tests.rs index 6329fb1..7b83b9c 100644 --- a/src/network/network_tests.rs +++ b/src/network/network_tests.rs @@ -6,54 +6,41 @@ mod tests { use mockito::{Mock, Server, ServerGuard}; use pretty_assertions::assert_str_eq; - use reqwest::header::HeaderMap; use reqwest::Client; + use reqwest::header::HeaderMap; use rstest::rstest; use serde::{Deserialize, Serialize}; - use tokio::sync::{mpsc, Mutex}; + use serde_json::json; + use tokio::sync::{Mutex, mpsc}; use tokio_util::sync::CancellationToken; + use super::test_utils; use crate::app::{App, AppConfig, ServarrConfig}; use crate::models::HorizontallyScrollableText; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::test_network; use crate::network::radarr_network::RadarrEvent; use crate::network::sonarr_network::SonarrEvent; - use crate::network::NetworkResource; use crate::network::{Network, NetworkEvent, NetworkTrait, RequestMethod, RequestProps}; #[tokio::test] async fn test_handle_network_event_radarr_event() { - let mut server = Server::new_async().await; - let radarr_server = server - .mock("GET", "/api/v3/health") - .with_status(200) - .with_body("{}") - .create_async() + use test_utils::{MockServarrApi, test_network}; + + let (mock, app, _server) = MockServarrApi::get() + .returns(json!({})) + .build_for(RadarrEvent::HealthCheck) .await; - let host = Some(server.host_with_port().split(':').collect::>()[0].to_owned()); - let port = Some( - server.host_with_port().split(':').collect::>()[1] - .parse() - .unwrap(), - ); - let mut app = App::test_default(); - app.is_loading = true; - let radarr_config = ServarrConfig { - host, - api_token: Some(String::new()), - port, - ssl_cert_path: None, - ..ServarrConfig::default() - }; - app.server_tabs.tabs[0].config = Some(radarr_config); - let app_arc = Arc::new(Mutex::new(app)); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + app.lock().await.is_loading = true; + let mut network = test_network(&app); let _ = network .handle_network_event(RadarrEvent::HealthCheck.into()) .await; - radarr_server.assert_async().await; - assert!(!app_arc.lock().await.is_loading); + mock.assert_async().await; + assert!(!app.lock().await.is_loading); } #[rstest] @@ -70,7 +57,7 @@ mod tests { .create_async() .await; let app_arc = Arc::new(Mutex::new(App::test_default())); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let _ = network .handle_request::( @@ -97,7 +84,7 @@ mod tests { #[values(RequestMethod::Get, RequestMethod::Post)] request_method: RequestMethod, ) { let (async_server, app_arc, server) = mock_api(request_method, 200, true).await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let resp = network .handle_request::<(), Test>( @@ -130,7 +117,7 @@ mod tests { #[values(RequestMethod::Get, RequestMethod::Post)] request_method: RequestMethod, ) { let (async_server, app_arc, server) = mock_api(request_method, 400, true).await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let mut test_result = String::new(); let resp = network @@ -224,7 +211,7 @@ mod tests { .create_async() .await; let app_arc = Arc::new(Mutex::new(App::test_default())); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let resp = network .handle_request::<(), Test>( @@ -241,23 +228,27 @@ mod tests { .await; async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .error - .text - .starts_with("Failed to parse response!")); + assert!( + app_arc + .lock() + .await + .error + .text + .starts_with("Failed to parse response!") + ); assert!(resp.is_err()); - assert!(resp - .unwrap_err() - .to_string() - .starts_with("Failed to parse response!")); + assert!( + resp + .unwrap_err() + .to_string() + .starts_with("Failed to parse response!") + ); } #[tokio::test] async fn test_handle_request_failure_to_send_request() { let app_arc = Arc::new(Mutex::new(App::test_default())); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let resp = network .handle_request::<(), Test>( @@ -273,17 +264,21 @@ mod tests { ) .await; - assert!(app_arc - .lock() - .await - .error - .text - .starts_with("Failed to send request.")); + assert!( + app_arc + .lock() + .await + .error + .text + .starts_with("Failed to send request.") + ); assert!(resp.is_err()); - assert!(resp - .unwrap_err() - .to_string() - .starts_with("Failed to send request.")); + assert!( + resp + .unwrap_err() + .to_string() + .starts_with("Failed to send request.") + ); } #[rstest] @@ -298,7 +293,7 @@ mod tests { request_method: RequestMethod, ) { let (async_server, app_arc, server) = mock_api(request_method, 404, true).await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let resp = network .handle_request::<(), Test>( @@ -329,7 +324,7 @@ mod tests { #[tokio::test] async fn test_handle_request_non_success_code_empty_response_body() { let (async_server, app_arc, server) = mock_api(RequestMethod::Post, 404, false).await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); let resp = network .handle_request::<(), Test>( @@ -391,7 +386,7 @@ mod tests { async_server = async_server.create_async().await; let app_arc = Arc::new(Mutex::new(App::test_default())); - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); network .call_api(RequestProps { @@ -415,10 +410,10 @@ mod tests { #[rstest] async fn test_request_props_from_requires_radarr_config_to_be_present_for_all_network_events( #[values(RadarrEvent::HealthCheck, SonarrEvent::HealthCheck)] network_event: impl Into - + NetworkResource, + + NetworkResource, ) { let app_arc = Arc::new(Mutex::new(App::default())); - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); network .request_props_from(network_event, RequestMethod::Get, None::<()>, None, None) @@ -434,7 +429,7 @@ mod tests { #[case] default_port: u16, ) { let app_arc = Arc::new(Mutex::new(App::test_default())); - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let resource = network_event.resource(); { let mut app = app_arc.lock().await; @@ -460,7 +455,7 @@ mod tests { #[tokio::test] async fn test_request_props_from_custom_config( #[values(RadarrEvent::GetMovies, SonarrEvent::ListSeries)] network_event: impl Into - + NetworkResource, + + NetworkResource, ) { let api_token = "testToken1234".to_owned(); let app_arc = Arc::new(Mutex::new(App::test_default())); @@ -477,7 +472,7 @@ mod tests { app.server_tabs.tabs[0].config = Some(servarr_config.clone()); app.server_tabs.tabs[1].config = Some(servarr_config); } - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let request_props = network .request_props_from(network_event, RequestMethod::Get, None::<()>, None, None) @@ -497,7 +492,7 @@ mod tests { #[tokio::test] async fn test_request_props_from_custom_config_custom_headers( #[values(RadarrEvent::GetMovies, SonarrEvent::ListSeries)] network_event: impl Into - + NetworkResource, + + NetworkResource, ) { let api_token = "testToken1234".to_owned(); let app_arc = Arc::new(Mutex::new(App::test_default())); @@ -517,7 +512,7 @@ mod tests { app.server_tabs.tabs[0].config = Some(servarr_config.clone()); app.server_tabs.tabs[1].config = Some(servarr_config); } - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let request_props = network .request_props_from(network_event, RequestMethod::Get, None::<()>, None, None) @@ -537,7 +532,7 @@ mod tests { #[tokio::test] async fn test_request_props_from_custom_config_using_uri_instead_of_host_and_port( #[values(RadarrEvent::GetMovies, SonarrEvent::ListSeries)] network_event: impl Into - + NetworkResource, + + NetworkResource, ) { let api_token = "testToken1234".to_owned(); let app_arc = Arc::new(Mutex::new(App::test_default())); @@ -552,7 +547,7 @@ mod tests { app.server_tabs.tabs[0].config = Some(servarr_config.clone()); app.server_tabs.tabs[1].config = Some(servarr_config); } - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let request_props = network .request_props_from(network_event, RequestMethod::Get, None::<()>, None, None) @@ -577,7 +572,7 @@ mod tests { #[case] default_port: u16, ) { let app_arc = Arc::new(Mutex::new(App::test_default())); - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let resource = network_event.resource(); { let mut app = app_arc.lock().await; @@ -609,7 +604,7 @@ mod tests { #[tokio::test] async fn test_request_props_from_custom_config_with_path_and_query_params( #[values(RadarrEvent::GetMovies, SonarrEvent::ListSeries)] network_event: impl Into - + NetworkResource, + + NetworkResource, ) { let api_token = "testToken1234".to_owned(); let app_arc = Arc::new(Mutex::new(App::test_default())); @@ -626,7 +621,7 @@ mod tests { app.server_tabs.tabs[0].config = Some(servarr_config.clone()); app.server_tabs.tabs[1].config = Some(servarr_config); } - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let request_props = network .request_props_from( @@ -652,7 +647,7 @@ mod tests { #[tokio::test] async fn test_request_props_from_custom_config_using_uri_instead_of_host_and_port_with_path_and_query_params( #[values(RadarrEvent::GetMovies, SonarrEvent::ListSeries)] network_event: impl Into - + NetworkResource, + + NetworkResource, ) { let api_token = "testToken1234".to_owned(); let app_arc = Arc::new(Mutex::new(App::test_default())); @@ -667,7 +662,7 @@ mod tests { app.server_tabs.tabs[0].config = Some(servarr_config.clone()); app.server_tabs.tabs[1].config = Some(servarr_config); } - let network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let network = test_network(&app_arc); let request_props = network .request_props_from( @@ -725,72 +720,147 @@ pub(in crate::network) mod test_utils { use std::sync::Arc; use mockito::{Matcher, Mock, Server, ServerGuard}; + use reqwest::Client; use serde_json::Value; use tokio::sync::Mutex; + use tokio_util::sync::CancellationToken; use crate::{ app::{App, ServarrConfig}, - network::{NetworkEvent, NetworkResource, RequestMethod}, + network::{Network, NetworkEvent, NetworkResource, RequestMethod}, }; - pub async fn mock_servarr_api<'a>( + pub fn test_client() -> Client { + Client::new() + } + + pub fn test_cancellation_token() -> CancellationToken { + CancellationToken::new() + } + + pub fn test_network<'a, 'b>(app: &'a Arc>>) -> Network<'a, 'b> { + Network::new(app, test_cancellation_token(), test_client()) + } + + pub struct MockServarrApi { method: RequestMethod, request_body: Option, response_body: Option, - response_status: Option, - network_event: impl Into + NetworkResource, - path: Option<&str>, - query_params: Option<&str>, - ) -> (Mock, Arc>>, ServerGuard) { - let status = response_status.unwrap_or(200); - let resource = network_event.resource(); - let mut server = Server::new_async().await; - let mut uri = format!("/api/v3{resource}"); + response_status: usize, + path: Option, + query_params: Option, + } - if let Some(path) = path { - uri = format!("{uri}{path}"); + impl MockServarrApi { + pub fn get() -> Self { + Self::new(RequestMethod::Get) } - if let Some(params) = query_params { - uri = format!("{uri}?{params}"); + pub fn post() -> Self { + Self::new(RequestMethod::Post) } - let mut async_server = server - .mock(&method.to_string().to_uppercase(), uri.as_str()) - .match_header("X-Api-Key", "test1234") - .with_status(status); - - if let Some(body) = request_body { - async_server = async_server.match_body(Matcher::Json(body)); + #[allow(dead_code)] + pub fn put() -> Self { + Self::new(RequestMethod::Put) } - if let Some(body) = response_body { - async_server = async_server.with_body(body.to_string()); + pub fn delete() -> Self { + Self::new(RequestMethod::Delete) } - async_server = async_server.create_async().await; - - let host = Some(server.host_with_port().split(':').collect::>()[0].to_owned()); - let port = Some( - server.host_with_port().split(':').collect::>()[1] - .parse() - .unwrap(), - ); - let mut app = App::test_default(); - let servarr_config = ServarrConfig { - host, - port, - api_token: Some("test1234".to_owned()), - ..ServarrConfig::default() - }; - - match network_event.into() { - NetworkEvent::Radarr(_) => app.server_tabs.tabs[0].config = Some(servarr_config), - NetworkEvent::Sonarr(_) => app.server_tabs.tabs[1].config = Some(servarr_config), + pub fn new(method: RequestMethod) -> Self { + Self { + method, + request_body: None, + response_body: None, + response_status: 200, + path: None, + query_params: None, + } } - let app_arc = Arc::new(Mutex::new(app)); + pub fn with_request_body(mut self, body: Value) -> Self { + self.request_body = Some(body); + self + } - (async_server, app_arc, server) + pub fn returns(mut self, body: Value) -> Self { + self.response_body = Some(body); + self + } + + pub fn status(mut self, status: usize) -> Self { + self.response_status = status; + self + } + + pub fn path(mut self, path: impl Into) -> Self { + self.path = Some(path.into()); + self + } + + pub fn query(mut self, params: impl Into) -> Self { + self.query_params = Some(params.into()); + self + } + + pub async fn build_for( + self, + network_event: E, + ) -> (Mock, Arc>>, ServerGuard) + where + E: Into + NetworkResource, + { + let resource = network_event.resource(); + let mut server = Server::new_async().await; + let mut uri = format!("/api/v3{resource}"); + + if let Some(path) = &self.path { + uri = format!("{uri}{path}"); + } + + if let Some(params) = &self.query_params { + uri = format!("{uri}?{params}"); + } + + let mut mock_builder = server + .mock(&self.method.to_string().to_uppercase(), uri.as_str()) + .match_header("X-Api-Key", "test1234") + .with_status(self.response_status); + + if let Some(body) = &self.request_body { + mock_builder = mock_builder.match_body(Matcher::Json(body.clone())); + } + + if let Some(body) = &self.response_body { + mock_builder = mock_builder.with_body(body.to_string()); + } + + let mock = mock_builder.create_async().await; + + let host = Some(server.host_with_port().split(':').collect::>()[0].to_owned()); + let port = Some( + server.host_with_port().split(':').collect::>()[1] + .parse() + .unwrap(), + ); + let mut app = App::test_default(); + let servarr_config = ServarrConfig { + host, + port, + api_token: Some("test1234".to_owned()), + ..ServarrConfig::default() + }; + + match network_event.into() { + NetworkEvent::Radarr(_) => app.server_tabs.tabs[0].config = Some(servarr_config), + NetworkEvent::Sonarr(_) => app.server_tabs.tabs[1].config = Some(servarr_config), + } + + let app_arc = Arc::new(Mutex::new(app)); + + (mock, app_arc, server) + } } } diff --git a/src/network/radarr_network/blocklist/mod.rs b/src/network/radarr_network/blocklist/mod.rs index 477b658..333b05a 100644 --- a/src/network/radarr_network/blocklist/mod.rs +++ b/src/network/radarr_network/blocklist/mod.rs @@ -1,11 +1,11 @@ +use crate::models::Route; use crate::models::radarr_models::BlocklistResponse; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; -use crate::models::Route; use crate::network::radarr_network::RadarrEvent; use crate::network::{Network, RequestMethod}; use anyhow::Result; use log::info; -use serde_json::{json, Value}; +use serde_json::{Value, json}; #[cfg(test)] #[path = "radarr_blocklist_network_tests.rs"] diff --git a/src/network/radarr_network/blocklist/radarr_blocklist_network_tests.rs b/src/network/radarr_network/blocklist/radarr_blocklist_network_tests.rs index 86e8885..d74b5d0 100644 --- a/src/network/radarr_network/blocklist/radarr_blocklist_network_tests.rs +++ b/src/network/radarr_network/blocklist/radarr_blocklist_network_tests.rs @@ -5,16 +5,13 @@ mod tests { use crate::models::radarr_models::BlocklistResponse; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::stateful_table::SortOption; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::radarr_network::radarr_network_test_utils::test_utils::blocklist_item; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::RadarrSerdeable; - use crate::network::{Network, RequestMethod}; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::blocklist_item; use pretty_assertions::assert_eq; - use reqwest::Client; use rstest::rstest; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_clear_radarr_blocklist_event() { @@ -33,53 +30,45 @@ mod tests { }, ]; let expected_request_json = json!({ "ids": [1, 2, 3]}); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - Some(expected_request_json), - None, - None, - RadarrEvent::ClearBlocklist, - None, - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::delete() + .with_request_body(expected_request_json) + .build_for(RadarrEvent::ClearBlocklist) + .await; + app .lock() .await .data .radarr_data .blocklist .set_items(blocklist_items); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::ClearBlocklist) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::ClearBlocklist) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_delete_radarr_blocklist_item_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - RadarrEvent::DeleteBlocklistItem(1), - Some("/1"), - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(RadarrEvent::DeleteBlocklistItem(1)) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::DeleteBlocklistItem(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::DeleteBlocklistItem(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[rstest] @@ -179,17 +168,11 @@ mod tests { ..blocklist_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(blocklist_json), - None, - RadarrEvent::GetBlocklist, - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.blocklist.sort_asc = true; + let (mock, app, _server) = MockServarrApi::get() + .returns(blocklist_json) + .build_for(RadarrEvent::GetBlocklist) + .await; + app.lock().await.data.radarr_data.blocklist.sort_asc = true; if use_custom_sorting { let cmp_fn = |a: &BlocklistItem, b: &BlocklistItem| { a.source_title @@ -202,7 +185,7 @@ mod tests { name: "Source Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data @@ -210,21 +193,22 @@ mod tests { .blocklist .sorting(vec![blocklist_sort_option]); } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - if let RadarrSerdeable::BlocklistResponse(blocklist) = network + let RadarrSerdeable::BlocklistResponse(blocklist) = network .handle_radarr_event(RadarrEvent::GetBlocklist) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.blocklist.items, - expected_blocklist - ); - assert!(app_arc.lock().await.data.radarr_data.blocklist.sort_asc); - assert_eq!(blocklist, response); - } + else { + panic!("Expected BlocklistResponse") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.blocklist.items, + expected_blocklist + ); + assert!(app.lock().await.data.radarr_data.blocklist.sort_asc); + assert_eq!(blocklist, response); } #[tokio::test] @@ -302,18 +286,12 @@ mod tests { }, }, }]}); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(blocklist_json), - None, - RadarrEvent::GetBlocklist, - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.blocklist.sort_asc = true; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(blocklist_json) + .build_for(RadarrEvent::GetBlocklist) + .await; + app.lock().await.data.radarr_data.blocklist.sort_asc = true; + app .lock() .await .push_navigation_stack(ActiveRadarrBlock::BlocklistSortPrompt.into()); @@ -326,29 +304,24 @@ mod tests { name: "Source Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data .radarr_data .blocklist .sorting(vec![blocklist_sort_option]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::GetBlocklist) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetBlocklist) + .await + .is_ok() + ); - async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .radarr_data - .blocklist - .items - .is_empty()); - assert!(app_arc.lock().await.data.radarr_data.blocklist.sort_asc); + mock.assert_async().await; + assert!(app.lock().await.data.radarr_data.blocklist.items.is_empty()); + assert!(app.lock().await.data.radarr_data.blocklist.sort_asc); } } diff --git a/src/network/radarr_network/collections/mod.rs b/src/network/radarr_network/collections/mod.rs index 6003098..7c04146 100644 --- a/src/network/radarr_network/collections/mod.rs +++ b/src/network/radarr_network/collections/mod.rs @@ -1,12 +1,12 @@ +use crate::models::Route; use crate::models::radarr_models::{Collection, EditCollectionParams}; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_models::CommandBody; -use crate::models::Route; use crate::network::radarr_network::RadarrEvent; use crate::network::{Network, RequestMethod}; use anyhow::Result; use log::{debug, info}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; #[cfg(test)] #[path = "radarr_collections_network_tests.rs"] diff --git a/src/network/radarr_network/collections/radarr_collections_network_tests.rs b/src/network/radarr_network/collections/radarr_collections_network_tests.rs index 9c9b95f..903cc51 100644 --- a/src/network/radarr_network/collections/radarr_collections_network_tests.rs +++ b/src/network/radarr_network/collections/radarr_collections_network_tests.rs @@ -5,16 +5,14 @@ mod tests { }; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::stateful_table::SortOption; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::radarr_network::radarr_network_test_utils::test_utils::collection; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::radarr_network::RadarrEvent; - use crate::network::{Network, NetworkResource, RequestMethod}; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::collection; use mockito::Matcher; use pretty_assertions::assert_eq; - use reqwest::Client; use rstest::rstest; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_edit_collection_event() { @@ -43,7 +41,7 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } } @@ -64,17 +62,12 @@ mod tests { search_on_add: Some(false), }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(detailed_collection_body), - None, - RadarrEvent::GetCollections, - Some("/123"), - None, - ) - .await; - let async_edit_server = server + let (mock_details, app, mut server) = MockServarrApi::get() + .returns(detailed_collection_body) + .path("/123") + .build_for(RadarrEvent::GetCollections) + .await; + let mock_edit = server .mock( "PUT", format!( @@ -88,20 +81,22 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditCollection(edit_collection_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditCollection(edit_collection_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details.assert_async().await; + mock_edit.assert_async().await; } #[tokio::test] - async fn test_handle_edit_collection_event_defaults_to_previous_values_when_no_params_are_provided( - ) { + async fn test_handle_edit_collection_event_defaults_to_previous_values_when_no_params_are_provided() + { let detailed_collection_body = json!({ "id": 123, "title": "Test Collection", @@ -127,7 +122,7 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } } @@ -140,21 +135,16 @@ mod tests { *expected_body.get_mut("rootFolderPath").unwrap() = json!("/nfs/movies"); *expected_body.get_mut("searchOnAdd").unwrap() = json!(true); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(detailed_collection_body), - None, - RadarrEvent::GetCollections, - Some("/123"), - None, - ) - .await; + let (mock_details, app, mut server) = MockServarrApi::get() + .returns(detailed_collection_body) + .path("/123") + .build_for(RadarrEvent::GetCollections) + .await; let edit_collection_params = EditCollectionParams { collection_id: 123, ..EditCollectionParams::default() }; - let async_edit_server = server + let mock_edit = server .mock( "PUT", format!( @@ -172,15 +162,17 @@ mod tests { collection_id: 123, ..EditCollectionParams::default() }; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditCollection(edit_collection_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditCollection(edit_collection_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details.assert_async().await; + mock_edit.assert_async().await; } #[rstest] @@ -210,7 +202,7 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } }], @@ -239,7 +231,7 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } }], @@ -257,17 +249,11 @@ mod tests { ..collection() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(collections_json), - None, - RadarrEvent::GetCollections, - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.collections.sort_asc = true; + let (mock, app, _server) = MockServarrApi::get() + .returns(collections_json) + .build_for(RadarrEvent::GetCollections) + .await; + app.lock().await.data.radarr_data.collections.sort_asc = true; if use_custom_sorting { let cmp_fn = |a: &Collection, b: &Collection| { a.title @@ -281,7 +267,7 @@ mod tests { name: "Collection", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data @@ -289,21 +275,22 @@ mod tests { .collections .sorting(vec![collection_sort_option]); } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - if let RadarrSerdeable::Collections(collections) = network + let RadarrSerdeable::Collections(collections) = network .handle_radarr_event(RadarrEvent::GetCollections) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.collections.items, - expected_collections - ); - assert!(app_arc.lock().await.data.radarr_data.collections.sort_asc); - assert_eq!(collections, response); - } + else { + panic!("Expected Collections") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.collections.items, + expected_collections + ); + assert!(app.lock().await.data.radarr_data.collections.sort_asc); + assert_eq!(collections, response); } #[tokio::test] @@ -332,7 +319,7 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } }], @@ -361,23 +348,17 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } }], }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(collections_json), - None, - RadarrEvent::GetCollections, - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.collections.sort_asc = true; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(collections_json) + .build_for(RadarrEvent::GetCollections) + .await; + app.lock().await.data.radarr_data.collections.sort_asc = true; + app .lock() .await .push_navigation_stack(ActiveRadarrBlock::CollectionsSortPrompt.into()); @@ -391,53 +372,54 @@ mod tests { name: "Collection", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data .radarr_data .collections .sorting(vec![collection_sort_option]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::GetCollections) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetCollections) + .await + .is_ok() + ); - async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .radarr_data - .collections - .items - .is_empty()); - assert!(app_arc.lock().await.data.radarr_data.collections.sort_asc); + mock.assert_async().await; + assert!( + app + .lock() + .await + .data + .radarr_data + .collections + .items + .is_empty() + ); + assert!(app.lock().await.data.radarr_data.collections.sort_asc); } #[tokio::test] async fn test_handle_update_collections_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "RefreshCollections" - })), - Some(json!({})), - None, - RadarrEvent::UpdateCollections, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(RadarrEvent::UpdateCollections) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::UpdateCollections) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::UpdateCollections) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } } diff --git a/src/network/radarr_network/downloads/radarr_downloads_network_tests.rs b/src/network/radarr_network/downloads/radarr_downloads_network_tests.rs index b5e5d18..0bb6ad3 100644 --- a/src/network/radarr_network/downloads/radarr_downloads_network_tests.rs +++ b/src/network/radarr_network/downloads/radarr_downloads_network_tests.rs @@ -1,34 +1,27 @@ #[cfg(test)] mod tests { use crate::models::radarr_models::{DownloadsResponse, RadarrSerdeable}; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::radarr_network::radarr_network_test_utils::test_utils::downloads_response; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::radarr_network::RadarrEvent; - use crate::network::{Network, RequestMethod}; - use reqwest::Client; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::downloads_response; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_delete_radarr_download_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - RadarrEvent::DeleteDownload(1), - Some("/1"), - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(RadarrEvent::DeleteDownload(1)) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::DeleteDownload(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::DeleteDownload(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -48,53 +41,46 @@ mod tests { }); let response: DownloadsResponse = serde_json::from_value(downloads_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(downloads_response_json), - None, - RadarrEvent::GetDownloads(500), - None, - Some("pageSize=500"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(downloads_response_json) + .path("?pageSize=500") + .build_for(RadarrEvent::GetDownloads(500)) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::DownloadsResponse(downloads) = network + let RadarrSerdeable::DownloadsResponse(downloads) = network .handle_radarr_event(RadarrEvent::GetDownloads(500)) .await .unwrap() - { - async_server.assert_async().await; - pretty_assertions::assert_eq!( - app_arc.lock().await.data.radarr_data.downloads.items, - downloads_response().records - ); - pretty_assertions::assert_eq!(downloads, response); - } + else { + panic!("Expected DownloadsResponse") + }; + mock.assert_async().await; + pretty_assertions::assert_eq!( + app.lock().await.data.radarr_data.downloads.items, + downloads_response().records + ); + pretty_assertions::assert_eq!(downloads, response); } #[tokio::test] async fn test_handle_update_radarr_downloads_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "RefreshMonitoredDownloads" - })), - Some(json!({})), - None, - RadarrEvent::UpdateDownloads, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(RadarrEvent::UpdateDownloads) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::UpdateDownloads) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::UpdateDownloads) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } } diff --git a/src/network/radarr_network/indexers/mod.rs b/src/network/radarr_network/indexers/mod.rs index b06d5f5..e9c67ee 100644 --- a/src/network/radarr_network/indexers/mod.rs +++ b/src/network/radarr_network/indexers/mod.rs @@ -4,9 +4,9 @@ use crate::models::servarr_models::{EditIndexerParams, Indexer, IndexerTestResul use crate::models::stateful_table::StatefulTable; use crate::network::radarr_network::RadarrEvent; use crate::network::{Network, RequestMethod}; -use anyhow::Result; +use anyhow::{Context, Result}; use log::{debug, info}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; #[cfg(test)] #[path = "radarr_indexers_network_tests.rs"] @@ -103,57 +103,57 @@ impl Network<'_, '_> { ) = { let priority = detailed_indexer_body["priority"] .as_i64() - .expect("Unable to deserialize 'priority'"); + .context("Failed to deserialize indexer 'priority' field")?; let seed_ratio_field_option = detailed_indexer_body["fields"] .as_array() - .unwrap() + .context("Failed to get indexer 'fields' array")? .iter() .find(|field| field["name"] == "seedCriteria.seedRatio"); let name = edit_indexer_params.name.unwrap_or( detailed_indexer_body["name"] .as_str() - .expect("Unable to deserialize 'name'") + .context("Failed to deserialize indexer 'name' field")? .to_owned(), ); let enable_rss = edit_indexer_params.enable_rss.unwrap_or( detailed_indexer_body["enableRss"] .as_bool() - .expect("Unable to deserialize 'enableRss'"), + .context("Failed to deserialize indexer 'enableRss' field")?, ); let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or( detailed_indexer_body["enableAutomaticSearch"] .as_bool() - .expect("Unable to deserialize 'enableAutomaticSearch"), + .context("Failed to deserialize indexer 'enableAutomaticSearch' field")?, ); let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or( detailed_indexer_body["enableInteractiveSearch"] .as_bool() - .expect("Unable to deserialize 'enableInteractiveSearch'"), + .context("Failed to deserialize indexer 'enableInteractiveSearch' field")?, ); let url = edit_indexer_params.url.unwrap_or( detailed_indexer_body["fields"] .as_array() - .expect("Unable to deserialize 'fields'") + .context("Failed to get indexer 'fields' array for baseUrl")? .iter() .find(|field| field["name"] == "baseUrl") - .expect("Field 'baseUrl' was not found in the 'fields' array") + .context("Field 'baseUrl' was not found in the indexer fields array")? .get("value") .unwrap_or(&json!("")) .as_str() - .expect("Unable to deserialize 'baseUrl value'") + .context("Failed to deserialize indexer 'baseUrl' value")? .to_owned(), ); let api_key = edit_indexer_params.api_key.unwrap_or( detailed_indexer_body["fields"] .as_array() - .expect("Unable to deserialize 'fields'") + .context("Failed to get indexer 'fields' array for apiKey")? .iter() .find(|field| field["name"] == "apiKey") - .expect("Field 'apiKey' was not found in the 'fields' array") + .context("Field 'apiKey' was not found in the indexer fields array")? .get("value") .unwrap_or(&json!("")) .as_str() - .expect("Unable to deserialize 'apiKey value'") + .context("Failed to deserialize indexer 'apiKey' value")? .to_owned(), ); let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| { @@ -162,7 +162,7 @@ impl Network<'_, '_> { .get("value") .unwrap_or(&json!("")) .as_str() - .expect("Unable to deserialize 'seedCriteria.seedRatio value'") + .unwrap_or("") .to_owned(); } @@ -174,10 +174,14 @@ impl Network<'_, '_> { edit_indexer_params.tags.unwrap_or( detailed_indexer_body["tags"] .as_array() - .expect("Unable to deserialize 'tags'") + .context("Failed to get indexer 'tags' array")? .iter() - .map(|item| item.as_i64().expect("Unable to deserialize tag ID")) - .collect(), + .map(|item| { + item + .as_i64() + .context("Failed to deserialize indexer tag ID") + }) + .collect::>>()?, ) }; let priority = edit_indexer_params.priority.unwrap_or(priority); @@ -195,47 +199,54 @@ impl Network<'_, '_> { ) }; - *detailed_indexer_body.get_mut("name").unwrap() = json!(name); - *detailed_indexer_body.get_mut("priority").unwrap() = json!(priority); - *detailed_indexer_body.get_mut("enableRss").unwrap() = json!(enable_rss); + *detailed_indexer_body + .get_mut("name") + .context("Failed to get mutable reference to indexer 'name' field")? = json!(name); + *detailed_indexer_body + .get_mut("priority") + .context("Failed to get mutable reference to indexer 'priority' field")? = json!(priority); + *detailed_indexer_body + .get_mut("enableRss") + .context("Failed to get mutable reference to indexer 'enableRss' field")? = json!(enable_rss); *detailed_indexer_body .get_mut("enableAutomaticSearch") - .unwrap() = json!(enable_automatic_search); + .context("Failed to get mutable reference to indexer 'enableAutomaticSearch' field")? = + json!(enable_automatic_search); *detailed_indexer_body .get_mut("enableInteractiveSearch") - .unwrap() = json!(enable_interactive_search); + .context("Failed to get mutable reference to indexer 'enableInteractiveSearch' field")? = + json!(enable_interactive_search); *detailed_indexer_body .get_mut("fields") - .unwrap() - .as_array_mut() - .unwrap() + .and_then(|f| f.as_array_mut()) + .context("Failed to get mutable reference to indexer 'fields' array")? .iter_mut() .find(|field| field["name"] == "baseUrl") - .unwrap() + .context("Failed to find 'baseUrl' field in indexer fields array")? .get_mut("value") - .unwrap() = json!(url); + .context("Failed to get mutable reference to 'baseUrl' value")? = json!(url); *detailed_indexer_body .get_mut("fields") - .unwrap() - .as_array_mut() - .unwrap() + .and_then(|f| f.as_array_mut()) + .context("Failed to get mutable reference to indexer 'fields' array for apiKey")? .iter_mut() .find(|field| field["name"] == "apiKey") - .unwrap() + .context("Failed to find 'apiKey' field in indexer fields array")? .get_mut("value") - .unwrap() = json!(api_key); - *detailed_indexer_body.get_mut("tags").unwrap() = json!(tags); + .context("Failed to get mutable reference to 'apiKey' value")? = json!(api_key); + *detailed_indexer_body + .get_mut("tags") + .context("Failed to get mutable reference to indexer 'tags' field")? = json!(tags); let seed_ratio_field_option = detailed_indexer_body .get_mut("fields") - .unwrap() - .as_array_mut() - .unwrap() + .and_then(|f| f.as_array_mut()) + .context("Failed to get mutable reference to indexer 'fields' array for seed ratio")? .iter_mut() .find(|field| field["name"] == "seedCriteria.seedRatio"); if let Some(seed_ratio_field) = seed_ratio_field_option { seed_ratio_field .as_object_mut() - .unwrap() + .context("Failed to get mutable reference to 'seedCriteria.seedRatio' object")? .insert("value".to_string(), json!(seed_ratio)); } @@ -332,12 +343,13 @@ impl Network<'_, '_> { self .handle_request::(request_props, |test_results, mut app| { if test_results.as_object().is_none() { - app.data.radarr_data.indexer_test_errors = Some( - test_results.as_array().unwrap()[0] - .get("errorMessage") - .unwrap() - .to_string(), - ); + let error_message = test_results + .as_array() + .and_then(|arr| arr.first()) + .and_then(|item| item.get("errorMessage")) + .map(|msg| msg.to_string()) + .unwrap_or_else(|| "Unknown indexer test error".to_string()); + app.data.radarr_data.indexer_test_errors = Some(error_message); } else { app.data.radarr_data.indexer_test_errors = Some(String::new()); }; diff --git a/src/network/radarr_network/indexers/radarr_indexers_network_tests.rs b/src/network/radarr_network/indexers/radarr_indexers_network_tests.rs index 675931b..4c0c228 100644 --- a/src/network/radarr_network/indexers/radarr_indexers_network_tests.rs +++ b/src/network/radarr_network/indexers/radarr_indexers_network_tests.rs @@ -1,40 +1,34 @@ #[cfg(test)] mod tests { + use crate::models::HorizontallyScrollableText; use crate::models::radarr_models::{IndexerSettings, RadarrSerdeable}; use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_models::{EditIndexerParams, Indexer, IndexerTestResult}; - use crate::models::HorizontallyScrollableText; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::radarr_network::RadarrEvent; use crate::network::radarr_network::radarr_network_test_utils::test_utils::{ indexer, indexer_settings, }; - use crate::network::radarr_network::RadarrEvent; - use crate::network::{Network, NetworkResource, RequestMethod}; use bimap::BiMap; use mockito::Matcher; use pretty_assertions::assert_eq; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_delete_radarr_indexer_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - RadarrEvent::DeleteIndexer(1), - Some("/1"), - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(RadarrEvent::DeleteIndexer(1)) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::DeleteIndexer(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::DeleteIndexer(1)) + .await + .is_ok() + ); async_server.assert_async().await; } @@ -52,22 +46,18 @@ mod tests { "whitelistedHardcodedSubs": "", "id": 1 }); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Put, - Some(indexer_settings_json), - None, - None, - RadarrEvent::EditAllIndexerSettings(indexer_settings()), - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::put() + .with_request_body(indexer_settings_json) + .build_for(RadarrEvent::EditAllIndexerSettings(indexer_settings())) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditAllIndexerSettings(indexer_settings())) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditAllIndexerSettings(indexer_settings())) + .await + .is_ok() + ); async_server.assert_async().await; } @@ -133,16 +123,11 @@ mod tests { priority: Some(0), ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -157,22 +142,24 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.radarr_data.tags_map = + app.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_radarr_indexer_event_does_not_overwrite_tags_vec_if_tag_input_string_is_none( - ) { + async fn test_handle_edit_radarr_indexer_event_does_not_overwrite_tags_vec_if_tag_input_string_is_none() + { let indexer_details_json = json!({ "enableRss": true, "enableAutomaticSearch": true, @@ -232,16 +219,11 @@ mod tests { priority: Some(0), ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -256,22 +238,24 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.radarr_data.tags_map = + app.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_radarr_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details( - ) { + async fn test_handle_edit_radarr_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details() + { let indexer_details_json = json!({ "enableRss": true, "enableAutomaticSearch": true, @@ -323,16 +307,11 @@ mod tests { priority: Some(0), ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -347,22 +326,24 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.radarr_data.tags_map = + app.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_radarr_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details( - ) { + async fn test_handle_edit_radarr_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details() + { let indexer_details_json = json!({ "enableRss": true, "enableAutomaticSearch": true, @@ -421,16 +402,11 @@ mod tests { priority: Some(0), ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -445,14 +421,16 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.radarr_data.tags_map = + app.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -488,16 +466,11 @@ mod tests { ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json.clone()), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json.clone()) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -512,12 +485,14 @@ mod tests { .match_body(Matcher::Json(indexer_details_json)) .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -577,16 +552,11 @@ mod tests { ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -601,12 +571,14 @@ mod tests { .match_body(Matcher::Json(expected_edit_indexer_body)) .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -645,30 +617,25 @@ mod tests { "id": 1 }]); let response: Vec = serde_json::from_value(indexers_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexers_response_json), - None, - RadarrEvent::GetIndexers, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(indexers_response_json) + .build_for(RadarrEvent::GetIndexers) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::Indexers(indexers) = network + let RadarrSerdeable::Indexers(indexers) = network .handle_radarr_event(RadarrEvent::GetIndexers) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.indexers.items, - vec![indexer()] - ); - assert_eq!(indexers, response); - } + else { + panic!("Expected Indexers") + }; + async_server.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.indexers.items, + vec![indexer()] + ); + assert_eq!(indexers, response); } #[tokio::test] @@ -686,30 +653,25 @@ mod tests { }); let response: IndexerSettings = serde_json::from_value(indexer_settings_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_settings_response_json), - None, - RadarrEvent::GetAllIndexerSettings, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(indexer_settings_response_json) + .build_for(RadarrEvent::GetAllIndexerSettings) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::IndexerSettings(settings) = network + let RadarrSerdeable::IndexerSettings(settings) = network .handle_radarr_event(RadarrEvent::GetAllIndexerSettings) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.indexer_settings, - Some(indexer_settings()) - ); - assert_eq!(settings, response); - } + else { + panic!("Expected IndexerSettings") + }; + async_server.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.indexer_settings, + Some(indexer_settings()) + ); + assert_eq!(settings, response); } #[tokio::test] @@ -725,27 +687,23 @@ mod tests { "whitelistedHardcodedSubs": "", "id": 1 }); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_settings_response_json), - None, - RadarrEvent::GetAllIndexerSettings, - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.indexer_settings = Some(IndexerSettings::default()); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(indexer_settings_response_json) + .build_for(RadarrEvent::GetAllIndexerSettings) + .await; + app.lock().await.data.radarr_data.indexer_settings = Some(IndexerSettings::default()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::GetAllIndexerSettings) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetAllIndexerSettings) + .await + .is_ok() + ); async_server.assert_async().await; assert_eq!( - app_arc.lock().await.data.radarr_data.indexer_settings, + app.lock().await.data.radarr_data.indexer_settings, Some(IndexerSettings::default()) ); } @@ -781,16 +739,11 @@ mod tests { "errorMessage": "test failure", "severity": "error" }]); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json.clone()), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json.clone()) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_test_server = server .mock( "POST", @@ -802,21 +755,22 @@ mod tests { .with_body(response_json.to_string()) .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - if let RadarrSerdeable::Value(value) = network + let RadarrSerdeable::Value(value) = network .handle_radarr_event(RadarrEvent::TestIndexer(1)) .await .unwrap() - { - async_details_server.assert_async().await; - async_test_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.indexer_test_errors, - Some("\"test failure\"".to_owned()) - ); - assert_eq!(value, response_json) - } + else { + panic!("Expected Value") + }; + async_details_server.assert_async().await; + async_test_server.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.indexer_test_errors, + Some("\"test failure\"".to_owned()) + ); + assert_eq!(value, response_json); } #[tokio::test] @@ -843,16 +797,11 @@ mod tests { "tags": [1], "id": 1 }); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json.clone()), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json.clone()) + .path("/1") + .build_for(RadarrEvent::GetIndexers) + .await; let async_test_server = server .mock( "POST", @@ -864,21 +813,22 @@ mod tests { .with_body("{}") .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - if let RadarrSerdeable::Value(value) = network + let RadarrSerdeable::Value(value) = network .handle_radarr_event(RadarrEvent::TestIndexer(1)) .await .unwrap() - { - async_details_server.assert_async().await; - async_test_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.indexer_test_errors, - Some(String::new()) - ); - assert_eq!(value, json!({})); - } + else { + panic!("Expected Value") + }; + async_details_server.assert_async().await; + async_test_server.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.indexer_test_errors, + Some(String::new()) + ); + assert_eq!(value, json!({})); } #[tokio::test] @@ -930,51 +880,49 @@ mod tests { ] }]); let response: Vec = serde_json::from_value(response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - None, - Some(response_json), - Some(400), - RadarrEvent::TestAllIndexers, - None, - None, - ) - .await; - app_arc + let (async_server, app, _server) = MockServarrApi::post() + .returns(response_json) + .status(400) + .build_for(RadarrEvent::TestAllIndexers) + .await; + app .lock() .await .data .radarr_data .indexers .set_items(indexers); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - if let RadarrSerdeable::IndexerTestResults(results) = network + let RadarrSerdeable::IndexerTestResults(results) = network .handle_radarr_event(RadarrEvent::TestAllIndexers) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected IndexerTestResults") + }; + async_server.assert_async().await; + assert!( + app .lock() .await .data .radarr_data .indexer_test_all_results - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .radarr_data - .indexer_test_all_results - .as_ref() - .unwrap() - .items, - indexer_test_results_modal_items - ); - assert_eq!(results, response); - } + .is_some() + ); + assert_eq!( + app + .lock() + .await + .data + .radarr_data + .indexer_test_all_results + .as_ref() + .unwrap() + .items, + indexer_test_results_modal_items + ); + assert_eq!(results, response); } } diff --git a/src/network/radarr_network/library/mod.rs b/src/network/radarr_network/library/mod.rs index b71b338..6d08957 100644 --- a/src/network/radarr_network/library/mod.rs +++ b/src/network/radarr_network/library/mod.rs @@ -13,7 +13,7 @@ use crate::utils::{convert_runtime, convert_to_gb}; use anyhow::Result; use indoc::formatdoc; use log::{debug, info, warn}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use urlencoding::encode; #[cfg(test)] @@ -53,7 +53,9 @@ impl Network<'_, '_> { delete_movie_files, add_list_exclusion, } = delete_movie_params; - info!("Deleting Radarr movie with ID: {id} with deleteFiles={delete_movie_files} and addImportExclusion={add_list_exclusion}"); + info!( + "Deleting Radarr movie with ID: {id} with deleteFiles={delete_movie_files} and addImportExclusion={add_list_exclusion}" + ); let request_props = self .request_props_from( @@ -223,26 +225,14 @@ impl Network<'_, '_> { .cloned() .collect(); - if app.data.radarr_data.movie_details_modal.is_none() { - app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default()); - } + let modal = app + .data + .radarr_data + .movie_details_modal + .get_or_insert_default(); - app - .data - .radarr_data - .movie_details_modal - .as_mut() - .unwrap() - .movie_cast - .set_items(cast_vec); - app - .data - .radarr_data - .movie_details_modal - .as_mut() - .unwrap() - .movie_crew - .set_items(crew_vec); + modal.movie_cast.set_items(cast_vec); + modal.movie_crew.set_items(crew_vec); }) .await } @@ -450,16 +440,11 @@ impl Network<'_, '_> { let mut reversed_movie_history_vec = movie_history_vec.to_vec(); reversed_movie_history_vec.reverse(); - if app.data.radarr_data.movie_details_modal.is_none() { - app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default()) - } - app .data .radarr_data .movie_details_modal - .as_mut() - .unwrap() + .get_or_insert_default() .movie_history .set_items(reversed_movie_history_vec) }) @@ -485,16 +470,11 @@ impl Network<'_, '_> { self .handle_request::<(), Vec>(request_props, |release_vec, mut app| { - if app.data.radarr_data.movie_details_modal.is_none() { - app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default()); - } - app .data .radarr_data .movie_details_modal - .as_mut() - .unwrap() + .get_or_insert_default() .movie_releases .set_items(release_vec); }) diff --git a/src/network/radarr_network/library/radarr_library_network_tests.rs b/src/network/radarr_network/library/radarr_library_network_tests.rs index 3199972..24288c2 100644 --- a/src/network/radarr_network/library/radarr_library_network_tests.rs +++ b/src/network/radarr_network/library/radarr_library_network_tests.rs @@ -7,50 +7,44 @@ mod tests { use crate::models::servarr_data::radarr::modals::MovieDetailsModal; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::stateful_table::SortOption; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::radarr_network::RadarrEvent; + use crate::network::radarr_network::RadarrSerdeable; use crate::network::radarr_network::library::get_movie_status; use crate::network::radarr_network::radarr_network_test_utils::test_utils::MOVIE_JSON; use crate::network::radarr_network::radarr_network_test_utils::test_utils::{ add_movie_search_result, cast_credit, crew_credit, movie, movie_history_item, release, }; - use crate::network::radarr_network::RadarrEvent; - use crate::network::radarr_network::RadarrSerdeable; - use crate::network::{Network, NetworkResource, RequestMethod}; use bimap::BiMap; use indoc::formatdoc; use mockito::Matcher; use pretty_assertions::{assert_eq, assert_str_eq}; - use reqwest::Client; use rstest::rstest; - use serde_json::{json, Value}; + use serde_json::{Value, json}; use std::slice; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_add_movie_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "tmdbId": 1234, - "title": "Test", - "rootFolderPath": "/nfs2", - "minimumAvailability": "announced", - "monitored": true, - "qualityProfileId": 2222, - "tags": [1, 2], - "addOptions": { - "monitor": "movieOnly", - "searchForMovie": true - } - })), - Some(json!({})), - None, - RadarrEvent::AddMovie(AddMovieBody::default()), - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.tags_map = + let body = json!({ + "tmdbId": 1234, + "title": "Test", + "rootFolderPath": "/nfs2", + "minimumAvailability": "announced", + "monitored": true, + "qualityProfileId": 2222, + "tags": [1, 2], + "addOptions": { + "monitor": "movieOnly", + "searchForMovie": true + } + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(RadarrEvent::AddMovie(AddMovieBody::default())) + .await; + app.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); let add_movie_body = AddMovieBody { tmdb_id: 1234, @@ -67,41 +61,39 @@ mod tests { }, }; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::AddMovie(add_movie_body)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::AddMovie(add_movie_body)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_add_movie_event_does_not_overwrite_tags_field_if_tag_input_string_is_none() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "tmdbId": 1234, - "title": "Test", - "rootFolderPath": "/nfs2", - "minimumAvailability": "announced", - "monitored": true, - "qualityProfileId": 2222, - "tags": [1, 2], - "addOptions": { - "monitor": "movieOnly", - "searchForMovie": true - } - })), - Some(json!({})), - None, - RadarrEvent::AddMovie(AddMovieBody::default()), - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.tags_map = + let body = json!({ + "tmdbId": 1234, + "title": "Test", + "rootFolderPath": "/nfs2", + "minimumAvailability": "announced", + "monitored": true, + "qualityProfileId": 2222, + "tags": [1, 2], + "addOptions": { + "monitor": "movieOnly", + "searchForMovie": true + } + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(RadarrEvent::AddMovie(AddMovieBody::default())) + .await; + app.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); let add_movie_body = AddMovieBody { tmdb_id: 1234, @@ -117,14 +109,16 @@ mod tests { search_for_movie: true, }, }; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::AddMovie(add_movie_body)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::AddMovie(add_movie_body)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -134,22 +128,19 @@ mod tests { delete_movie_files: true, add_list_exclusion: true, }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - RadarrEvent::DeleteMovie(delete_movie_params.clone()), - Some("/1"), - Some("deleteFiles=true&addImportExclusion=true"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app_arc, _server) = MockServarrApi::delete() + .path("/1") + .query("deleteFiles=true&addImportExclusion=true") + .build_for(RadarrEvent::DeleteMovie(delete_movie_params.clone())) + .await; + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::DeleteMovie(delete_movie_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::DeleteMovie(delete_movie_params)) + .await + .is_ok() + ); async_server.assert_async().await; } @@ -161,28 +152,26 @@ mod tests { indexer_id: 2, movie_id: 1, }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "guid": "1234", - "indexerId": 2, - "movieId": 1 - })), - Some(json!({})), - None, - RadarrEvent::DownloadRelease(expected_body.clone()), - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let body = json!({ + "guid": "1234", + "indexerId": 2, + "movieId": 1 + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(RadarrEvent::DownloadRelease(expected_body.clone())) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::DownloadRelease(expected_body)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::DownloadRelease(expected_body)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -203,16 +192,11 @@ mod tests { ..EditMovieParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(MOVIE_JSON).unwrap()), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app_arc, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(MOVIE_JSON).unwrap()) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; let async_edit_server = server .mock( "PUT", @@ -229,12 +213,14 @@ mod tests { .await; app_arc.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -257,16 +243,11 @@ mod tests { tags: Some(vec![1, 2]), ..EditMovieParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(MOVIE_JSON).unwrap()), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app_arc, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(MOVIE_JSON).unwrap()) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; let async_edit_server = server .mock( "PUT", @@ -283,12 +264,14 @@ mod tests { .await; app_arc.lock().await.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -297,16 +280,11 @@ mod tests { #[tokio::test] async fn test_handle_edit_movie_event_defaults_to_previous_values() { let expected_body: Value = serde_json::from_str(MOVIE_JSON).unwrap(); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(MOVIE_JSON).unwrap()), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app_arc, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(MOVIE_JSON).unwrap()) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; let edit_movie_params = EditMovieParams { movie_id: 1, ..EditMovieParams::default() @@ -325,32 +303,29 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_movie_event_uses_provided_parameters_returns_empty_tags_vec_when_clear_tags_is_true( - ) { + async fn test_handle_edit_movie_event_uses_provided_parameters_returns_empty_tags_vec_when_clear_tags_is_true() + { let mut expected_body: Value = serde_json::from_str(MOVIE_JSON).unwrap(); *expected_body.get_mut("tags").unwrap() = json!([]); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(MOVIE_JSON).unwrap()), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app_arc, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(MOVIE_JSON).unwrap()) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; let edit_movie_params = EditMovieParams { movie_id: 1, clear_tags: true, @@ -370,12 +345,14 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::EditMovie(edit_movie_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -397,32 +374,28 @@ mod tests { } ]); let response: Vec = serde_json::from_value(credits_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(credits_json), - None, - RadarrEvent::GetMovieCredits(1), - None, - Some("movieId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(credits_json) + .query("movieId=1") + .build_for(RadarrEvent::GetMovieCredits(1)) + .await; app_arc.lock().await.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default()); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let RadarrSerdeable::Credits(credits) = network + let RadarrSerdeable::Credits(credits) = network .handle_radarr_event(RadarrEvent::GetMovieCredits(1)) .await .unwrap() - { - let app = app_arc.lock().await; - let movie_details_modal = app.data.radarr_data.movie_details_modal.as_ref().unwrap(); + else { + panic!("Expected Credits") + }; + let app = app_arc.lock().await; + let movie_details_modal = app.data.radarr_data.movie_details_modal.as_ref().unwrap(); - async_server.assert_async().await; - assert_eq!(movie_details_modal.movie_cast.items, vec![cast_credit()]); - assert_eq!(movie_details_modal.movie_crew.items, vec![crew_credit()]); - assert_eq!(credits, response); - } + async_server.assert_async().await; + assert_eq!(movie_details_modal.movie_cast.items, vec![cast_credit()]); + assert_eq!(movie_details_modal.movie_crew.items, vec![crew_credit()]); + assert_eq!(credits, response); } #[tokio::test] @@ -440,22 +413,19 @@ mod tests { "type": "crew", } ]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(credits_json), - None, - RadarrEvent::GetMovieCredits(1), - None, - Some("movieId=1"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(credits_json) + .query("movieId=1") + .build_for(RadarrEvent::GetMovieCredits(1)) + .await; + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::GetMovieCredits(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetMovieCredits(1)) + .await + .is_ok() + ); let app = app_arc.lock().await; let movie_details_modal = app.data.radarr_data.movie_details_modal.as_ref().unwrap(); @@ -498,17 +468,11 @@ mod tests { ..movie() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([movie_1, movie_2])), - None, - RadarrEvent::GetMovies, - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.movies.sort_asc = true; + let (mock, app, _server) = MockServarrApi::get() + .returns(json!([movie_1, movie_2])) + .build_for(RadarrEvent::GetMovies) + .await; + app.lock().await.data.radarr_data.movies.sort_asc = true; if use_custom_sorting { let cmp_fn = |a: &Movie, b: &Movie| { a.title @@ -521,7 +485,7 @@ mod tests { name: "Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data @@ -529,21 +493,22 @@ mod tests { .movies .sorting(vec![title_sort_option]); } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - if let RadarrSerdeable::Movies(movies) = network - .handle_radarr_event(RadarrEvent::GetMovies) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.movies.items, - expected_sorted_movies - ); - assert!(app_arc.lock().await.data.radarr_data.movies.sort_asc); - assert_eq!(movies, expected_movies); - } + let result = network.handle_radarr_event(RadarrEvent::GetMovies).await; + + mock.assert_async().await; + + let RadarrSerdeable::Movies(movies) = result.unwrap() else { + panic!("Expected Movies variant") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.movies.items, + expected_sorted_movies + ); + assert!(app.lock().await.data.radarr_data.movies.sort_asc); + assert_eq!(movies, expected_movies); } #[tokio::test] @@ -554,21 +519,15 @@ mod tests { *movie_1.get_mut("title").unwrap() = json!("z test"); *movie_2.get_mut("id").unwrap() = json!(2); *movie_2.get_mut("title").unwrap() = json!("A test"); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([movie_1, movie_2])), - None, - RadarrEvent::GetMovies, - None, - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(json!([movie_1, movie_2])) + .build_for(RadarrEvent::GetMovies) + .await; + app .lock() .await .push_navigation_stack(ActiveRadarrBlock::MoviesSortPrompt.into()); - app_arc.lock().await.data.radarr_data.movies.sort_asc = true; + app.lock().await.data.radarr_data.movies.sort_asc = true; let cmp_fn = |a: &Movie, b: &Movie| { a.title .text @@ -579,118 +538,111 @@ mod tests { name: "Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data .radarr_data .movies .sorting(vec![title_sort_option]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::GetMovies) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetMovies) + .await + .is_ok() + ); - async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .radarr_data - .movies - .items - .is_empty()); - assert!(app_arc.lock().await.data.radarr_data.movies.sort_asc); + mock.assert_async().await; + assert!(app.lock().await.data.radarr_data.movies.items.is_empty()); + assert!(app.lock().await.data.radarr_data.movies.sort_asc); } #[tokio::test] async fn test_handle_get_movie_details_event() { let response: Movie = serde_json::from_str(MOVIE_JSON).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(MOVIE_JSON).unwrap()), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(serde_json::from_str(MOVIE_JSON).unwrap()) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; app_arc.lock().await.data.radarr_data.quality_profile_map = BiMap::from_iter([(2222, "HD - 1080p".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let RadarrSerdeable::Movie(movie) = network + let RadarrSerdeable::Movie(movie) = network .handle_radarr_event(RadarrEvent::GetMovieDetails(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected Movie") + }; + async_server.assert_async().await; + assert!( + app_arc .lock() .await .data .radarr_data .movie_details_modal - .is_some()); - assert_eq!(movie, response); + .is_some() + ); + assert_eq!(movie, response); - let app = app_arc.lock().await; - let movie_details_modal = app.data.radarr_data.movie_details_modal.as_ref().unwrap(); - assert_str_eq!( - movie_details_modal.movie_details.get_text(), - formatdoc!( - "Title: Test - Year: 2023 - Runtime: 2h 0m - Rating: R - Collection: Test Collection - Status: Downloaded - Description: Blah blah blah - TMDB: 99% - IMDB: 9.9 - Rotten Tomatoes: - Quality Profile: HD - 1080p - Size: 3.30 GB - Path: /nfs/movies - Studio: 21st Century Alex - Genres: cool, family, fun" - ) - ); - assert_str_eq!( - movie_details_modal.file_details, - formatdoc!( - "Relative Path: Test.mkv - Absolute Path: /nfs/movies/Test.mkv + let app = app_arc.lock().await; + let movie_details_modal = app.data.radarr_data.movie_details_modal.as_ref().unwrap(); + assert_str_eq!( + movie_details_modal.movie_details.get_text(), + formatdoc!( + "Title: Test + Year: 2023 + Runtime: 2h 0m + Rating: R + Collection: Test Collection + Status: Downloaded + Description: Blah blah blah + TMDB: 99% + IMDB: 9.9 + Rotten Tomatoes: 99% + Quality Profile: HD - 1080p Size: 3.30 GB - Date Added: 2022-12-30 07:37:56 UTC" - ) - ); - assert_str_eq!( - movie_details_modal.audio_details, - formatdoc!( - "Bitrate: 0 - Channels: 7.1 - Codec: AAC - Languages: eng - Stream Count: 1" - ) - ); - assert_str_eq!( - movie_details_modal.video_details, - formatdoc!( - "Bit Depth: 10 - Bitrate: 0 - Codec: x265 - FPS: 23.976 - Resolution: 1920x804 - Scan Type: Progressive - Runtime: 2:00:00" - ) - ); - } + Path: /nfs/movies + Studio: 21st Century Alex + Genres: cool, family, fun" + ) + ); + assert_str_eq!( + movie_details_modal.file_details, + formatdoc!( + "Relative Path: Test.mkv + Absolute Path: /nfs/movies/Test.mkv + Size: 3.30 GB + Date Added: 2022-12-30 07:37:56 UTC" + ) + ); + assert_str_eq!( + movie_details_modal.audio_details, + formatdoc!( + "Bitrate: 0 + Channels: 7.1 + Codec: AAC + Languages: eng + Stream Count: 1" + ) + ); + assert_str_eq!( + movie_details_modal.video_details, + formatdoc!( + "Bit Depth: 10 + Bitrate: 0 + Codec: x265 + FPS: 23.976 + Resolution: 1920x804 + Scan Type: Progressive + Runtime: 2:00:00" + ) + ); } #[tokio::test] @@ -718,33 +670,32 @@ mod tests { "minimumAvailability": "released", "ratings": {} }); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(movie_json_with_missing_fields), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(movie_json_with_missing_fields) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; app_arc.lock().await.data.radarr_data.quality_profile_map = BiMap::from_iter([(2222, "HD - 1080p".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::GetMovieDetails(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetMovieDetails(1)) + .await + .is_ok() + ); async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .radarr_data - .movie_details_modal - .is_some()); + assert!( + app_arc + .lock() + .await + .data + .radarr_data + .movie_details_modal + .is_some() + ); let app = app_arc.lock().await; let movie_details_modal = app.data.radarr_data.movie_details_modal.as_ref().unwrap(); @@ -784,40 +735,36 @@ mod tests { }]); let response: Vec = serde_json::from_value(movie_history_item_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(movie_history_item_json), - None, - RadarrEvent::GetMovieHistory(1), - None, - Some("movieId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(movie_history_item_json) + .query("movieId=1") + .build_for(RadarrEvent::GetMovieHistory(1)) + .await; app_arc.lock().await.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default()); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let RadarrSerdeable::MovieHistoryItems(history) = network + let RadarrSerdeable::MovieHistoryItems(history) = network .handle_radarr_event(RadarrEvent::GetMovieHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .radarr_data - .movie_details_modal - .as_ref() - .unwrap() - .movie_history - .items, - vec![movie_history_item()] - ); - assert_eq!(history, response); - } + else { + panic!("Expected MovieHistoryItems") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .radarr_data + .movie_details_modal + .as_ref() + .unwrap() + .movie_history + .items, + vec![movie_history_item()] + ); + assert_eq!(history, response); } #[tokio::test] @@ -829,22 +776,19 @@ mod tests { "date": "2022-12-30T07:37:56Z", "eventType": "grabbed" }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(movie_history_item_json), - None, - RadarrEvent::GetMovieHistory(1), - None, - Some("movieId=1"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(movie_history_item_json) + .query("movieId=1") + .build_for(RadarrEvent::GetMovieHistory(1)) + .await; + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::GetMovieHistory(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetMovieHistory(1)) + .await + .is_ok() + ); async_server.assert_async().await; assert_eq!( @@ -879,40 +823,36 @@ mod tests { "languages": [ { "id": 1, "name": "English" } ], "quality": { "quality": { "name": "HD - 1080p" }} }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(release_json), - None, - RadarrEvent::GetReleases(1), - None, - Some("movieId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(release_json) + .query("movieId=1") + .build_for(RadarrEvent::GetReleases(1)) + .await; app_arc.lock().await.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default()); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let RadarrSerdeable::Releases(releases_vec) = network + let RadarrSerdeable::Releases(releases_vec) = network .handle_radarr_event(RadarrEvent::GetReleases(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .radarr_data - .movie_details_modal - .as_ref() - .unwrap() - .movie_releases - .items, - vec![release()] - ); - assert_eq!(releases_vec, vec![release()]); - } + else { + panic!("Expected Releases") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .radarr_data + .movie_details_modal + .as_ref() + .unwrap() + .movie_releases + .items, + vec![release()] + ); + assert_eq!(releases_vec, vec![release()]); } #[tokio::test] @@ -932,22 +872,19 @@ mod tests { "languages": [ { "id": 1, "name": "English" } ], "quality": { "quality": { "name": "HD - 1080p" }} }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(release_json), - None, - RadarrEvent::GetReleases(1), - None, - Some("movieId=1"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(release_json) + .query("movieId=1") + .build_for(RadarrEvent::GetReleases(1)) + .await; + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::GetReleases(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::GetReleases(1)) + .await + .is_ok() + ); async_server.assert_async().await; assert_eq!( @@ -984,78 +921,75 @@ mod tests { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(add_movie_search_result_json), - None, - RadarrEvent::SearchNewMovie("test term".into()), - None, - Some("term=test%20term"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(add_movie_search_result_json) + .query("term=test%20term") + .build_for(RadarrEvent::SearchNewMovie("test term".into())) + .await; + let mut network = test_network(&app_arc); - if let RadarrSerdeable::AddMovieSearchResults(add_movie_search_results) = network + let RadarrSerdeable::AddMovieSearchResults(add_movie_search_results) = network .handle_radarr_event(RadarrEvent::SearchNewMovie("test term".into())) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected AddMovieSearchResults") + }; + async_server.assert_async().await; + assert!( + app_arc .lock() .await .data .radarr_data .add_searched_movies - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .radarr_data - .add_searched_movies - .as_ref() - .unwrap() - .items, - vec![add_movie_search_result()] - ); - assert_eq!(add_movie_search_results, vec![add_movie_search_result()]); - } + .is_some() + ); + assert_eq!( + app_arc + .lock() + .await + .data + .radarr_data + .add_searched_movies + .as_ref() + .unwrap() + .items, + vec![add_movie_search_result()] + ); + assert_eq!(add_movie_search_results, vec![add_movie_search_result()]); } #[tokio::test] async fn test_handle_search_new_movie_event_no_results() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([])), - None, - RadarrEvent::SearchNewMovie("test term".into()), - None, - Some("term=test%20term"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(json!([])) + .query("term=test%20term") + .build_for(RadarrEvent::SearchNewMovie("test term".into())) + .await; + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::SearchNewMovie("test term".into())) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::SearchNewMovie("test term".into())) + .await + .is_ok() + ); async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .radarr_data - .add_searched_movies - .is_none()); + assert!( + app_arc + .lock() + .await + .data + .radarr_data + .add_searched_movies + .is_none() + ); assert_eq!( app_arc.lock().await.get_current_route(), ActiveRadarrBlock::AddMovieEmptySearchResults.into() @@ -1067,16 +1001,11 @@ mod tests { let mut expected_body: Value = serde_json::from_str(MOVIE_JSON).unwrap(); *expected_body.get_mut("monitored").unwrap() = json!(false); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(MOVIE_JSON).unwrap()), - None, - RadarrEvent::GetMovieDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app_arc, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(MOVIE_JSON).unwrap()) + .path("/1") + .build_for(RadarrEvent::GetMovieDetails(1)) + .await; let async_toggle_server = server .mock( "PUT", @@ -1095,12 +1024,14 @@ mod tests { let mut app = app_arc.lock().await; app.data.radarr_data.movies.set_items(vec![movie()]); } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_radarr_event(RadarrEvent::ToggleMovieMonitoring(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::ToggleMovieMonitoring(1)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_toggle_server.assert_async().await; @@ -1108,77 +1039,71 @@ mod tests { #[tokio::test] async fn test_handle_trigger_automatic_movie_search_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "name": "MoviesSearch", - "movieIds": [ 1 ] - })), - Some(json!({})), - None, - RadarrEvent::TriggerAutomaticSearch(1), - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let body = json!({ + "name": "MoviesSearch", + "movieIds": [ 1 ] + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(RadarrEvent::TriggerAutomaticSearch(1)) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::TriggerAutomaticSearch(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::TriggerAutomaticSearch(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_update_all_movies_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "name": "RefreshMovie", - "movieIds": [] - })), - Some(json!({})), - None, - RadarrEvent::UpdateAllMovies, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let body = json!({ + "name": "RefreshMovie", + "movieIds": [] + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(RadarrEvent::UpdateAllMovies) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::UpdateAllMovies) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::UpdateAllMovies) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_update_and_scan_movie_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "name": "RefreshMovie", - "movieIds": [ 1 ] - })), - Some(json!({})), - None, - RadarrEvent::UpdateAndScan(1), - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let body = json!({ + "name": "RefreshMovie", + "movieIds": [ 1 ] + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(RadarrEvent::UpdateAndScan(1)) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::UpdateAndScan(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::UpdateAndScan(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[test] diff --git a/src/network/radarr_network/mod.rs b/src/network/radarr_network/mod.rs index 14e5511..72ff7d9 100644 --- a/src/network/radarr_network/mod.rs +++ b/src/network/radarr_network/mod.rs @@ -2,7 +2,7 @@ use anyhow::Result; use std::fmt::Debug; use log::info; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use crate::models::radarr_models::{ AddMovieBody, DeleteMovieParams, EditCollectionParams, EditMovieParams, IndexerSettings, @@ -22,12 +22,10 @@ mod root_folders; mod system; #[cfg(test)] -#[path = "radarr_network_tests.rs"] mod radarr_network_tests; #[cfg(test)] -#[path = "radarr_network_test_utils.rs"] -mod radarr_network_test_utils; +pub mod radarr_network_test_utils; #[derive(Debug, Eq, PartialEq, Clone)] pub enum RadarrEvent { diff --git a/src/network/radarr_network/radarr_network_test_utils.rs b/src/network/radarr_network/radarr_network_test_utils.rs index 54fb205..8cc37d6 100644 --- a/src/network/radarr_network/radarr_network_test_utils.rs +++ b/src/network/radarr_network/radarr_network_test_utils.rs @@ -1,16 +1,19 @@ #[cfg(test)] -pub(in crate::network::radarr_network) mod test_utils { +pub mod test_utils { use crate::models::radarr_models::{ AddMovieSearchResult, BlocklistItem, BlocklistItemMovie, Collection, CollectionMovie, Credit, CreditType, DownloadRecord, DownloadsResponse, IndexerSettings, MediaInfo, MinimumAvailability, - Movie, MovieCollection, MovieFile, MovieHistoryItem, RadarrRelease, Rating, RatingsList, + Movie, MovieCollection, MovieFile, MovieHistoryItem, RadarrRelease, RadarrTask, RadarrTaskName, + Rating, RatingsList, }; use crate::models::servarr_models::{ Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder, }; - use crate::models::HorizontallyScrollableText; + use crate::models::{HorizontallyScrollableText, ScrollableText}; + use bimap::BiMap; use chrono::DateTime; - use serde_json::{json, Number}; + use indoc::formatdoc; + use serde_json::{Number, Value, json}; pub const MOVIE_JSON: &str = r#"{ "id": 1, @@ -42,7 +45,7 @@ pub(in crate::network::radarr_network) mod test_utils { "value": 9.9 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } }, "movieFile": { @@ -86,10 +89,10 @@ pub(in crate::network::radarr_network) mod test_utils { "value": 9.9 }, "tmdb": { - "value": 9.9 + "value": 99 }, "rottenTomatoes": { - "value": 9.9 + "value": 99 } } } @@ -104,6 +107,25 @@ pub(in crate::network::radarr_network) mod test_utils { } } + pub fn log_line() -> &'static str { + "2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases" + } + + pub fn task() -> RadarrTask { + RadarrTask { + name: "Backup".to_string(), + task_name: RadarrTaskName::Backup, + interval: 60, + last_execution: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T21:29:16Z").unwrap()), + last_duration: "00:00:17".to_string(), + next_execution: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T22:29:16Z").unwrap()), + } + } + + pub fn tags_map() -> BiMap { + BiMap::from_iter([(1, "alex".to_owned())]) + } + pub fn genres() -> Vec { vec!["cool".to_owned(), "family".to_owned(), "fun".to_owned()] } @@ -114,11 +136,15 @@ pub(in crate::network::radarr_network) mod test_utils { } } + pub fn percentage_rating() -> Rating { + Rating { value: 99.into() } + } + pub fn ratings_list() -> RatingsList { RatingsList { imdb: Some(rating()), tmdb: Some(rating()), - rotten_tomatoes: Some(rating()), + rotten_tomatoes: Some(percentage_rating()), } } @@ -378,4 +404,100 @@ pub(in crate::network::radarr_network) mod test_utils { ..IndexerSettings::default() } } + + pub fn tag() -> Value { + json!({ + "id": 3, + "label": "testing" + }) + } + + pub fn quality_profile() -> Value { + json!({ + "id": 2222, + "name": "HD - 1080p" + }) + } + + pub fn quality_profile_map() -> BiMap { + let quality_profile = quality_profile(); + let id = quality_profile + .get("id") + .expect("A id must be set on a quality profile") + .as_i64() + .expect("'id' must be a string"); + let name = quality_profile + .get("name") + .expect("A name must be set on a quality profile") + .as_str() + .expect("'name' must be a string") + .to_owned(); + + BiMap::from_iter(vec![(id, name)]) + } + + pub fn updates() -> ScrollableText { + let line_break = "-".repeat(200); + ScrollableText::with_string(formatdoc!( + " + The latest version of Radarr is already installed + + 4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) + {line_break} + New: + * Cool new thing + Fixed: + * Some bugs killed + + + 3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) + {line_break} + New: + * Cool new thing (old) + * Other cool new thing (old) + + + 2.1.0 - 2023-04-15 02:02:53 UTC + {line_break} + Fixed: + * Killed bug 1 + * Fixed bug 2" + )) + } + + pub fn torrent_release() -> RadarrRelease { + RadarrRelease { + guid: "1234".to_string(), + protocol: "torrent".to_string(), + age: 12, + title: "Some movie release".into(), + indexer: "The Pirate Bay".to_string(), + indexer_id: 1, + size: 2468, + rejected: true, + rejections: Some(vec!["something interesting".into()]), + seeders: Some(25.into()), + leechers: Some(3.into()), + languages: Some(vec![language()]), + quality: quality_wrapper(), + } + } + + pub fn usenet_release() -> RadarrRelease { + RadarrRelease { + guid: "1234".to_string(), + protocol: "usenet".to_string(), + age: 22, + title: "Some Other movie release".into(), + indexer: "The Pirate Bay".to_string(), + indexer_id: 2, + size: 1512, + rejected: true, + rejections: Some(vec!["Bad stuff happens in the middle of nowhere".into()]), + seeders: None, + leechers: None, + languages: Some(vec![language()]), + quality: quality_wrapper(), + } + } } diff --git a/src/network/radarr_network/radarr_network_tests.rs b/src/network/radarr_network/radarr_network_tests.rs index a0cba2f..cfa10b0 100644 --- a/src/network/radarr_network/radarr_network_tests.rs +++ b/src/network/radarr_network/radarr_network_tests.rs @@ -1,21 +1,22 @@ #[cfg(test)] mod test { use super::super::*; + use crate::App; use crate::models::radarr_models::{ EditCollectionParams, EditMovieParams, IndexerSettings, RadarrTaskName, }; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_models::EditIndexerParams; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::App; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::{ + quality_profile, tag, + }; use bimap::BiMap; use pretty_assertions::{assert_eq, assert_str_eq}; - use reqwest::Client; use rstest::rstest; use serde_json::json; use std::sync::Arc; use tokio::sync::Mutex; - use tokio_util::sync::CancellationToken; #[rstest] fn test_resource_movie( @@ -161,146 +162,132 @@ mod test { #[tokio::test] async fn test_handle_get_radarr_healthcheck_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - None, - None, - RadarrEvent::HealthCheck, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .build_for(RadarrEvent::HealthCheck) + .await; + + let mut network = test_network(&app); let _ = network.handle_radarr_event(RadarrEvent::HealthCheck).await; - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_get_radarr_quality_profiles_event() { - let quality_profile_json = json!([{ - "id": 2222, - "name": "HD - 1080p" - }]); - let response: Vec = - serde_json::from_value(quality_profile_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(quality_profile_json), - None, - RadarrEvent::GetQualityProfiles, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let expected: Vec = vec![QualityProfile { + id: 2222, + name: "HD - 1080p".to_owned(), + }]; - if let RadarrSerdeable::QualityProfiles(quality_profiles) = network + let (mock, app, _server) = MockServarrApi::get() + .returns(json!([quality_profile()])) + .build_for(RadarrEvent::GetQualityProfiles) + .await; + + let mut network = test_network(&app); + + let result = network .handle_radarr_event(RadarrEvent::GetQualityProfiles) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.quality_profile_map, - BiMap::from_iter([(2222i64, "HD - 1080p".to_owned())]) - ); - assert_eq!(quality_profiles, response); - } + .await; + + mock.assert_async().await; + + let RadarrSerdeable::QualityProfiles(quality_profiles) = result.unwrap() else { + panic!("Expected QualityProfiles"); + }; + + assert_eq!(quality_profiles, expected); + assert_eq!( + app.lock().await.data.radarr_data.quality_profile_map, + BiMap::from_iter([(2222i64, "HD - 1080p".to_owned())]) + ); } #[tokio::test] async fn test_handle_get_radarr_tags_event() { - let tags_json = json!([{ - "id": 2222, - "label": "usenet" - }]); - let response: Vec = serde_json::from_value(tags_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(tags_json), - None, - RadarrEvent::GetTags, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let expected: Vec = vec![Tag { + id: 2222, + label: "usenet".to_owned(), + }]; - if let RadarrSerdeable::Tags(tags) = network - .handle_radarr_event(RadarrEvent::GetTags) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.tags_map, - BiMap::from_iter([(2222i64, "usenet".to_owned())]) - ); - assert_eq!(tags, response); - } + let (mock, app, _server) = MockServarrApi::get() + .returns(json!([{ + "id": 2222, + "label": "usenet" + }])) + .build_for(RadarrEvent::GetTags) + .await; + + let mut network = test_network(&app); + + let result = network.handle_radarr_event(RadarrEvent::GetTags).await; + + mock.assert_async().await; + + let RadarrSerdeable::Tags(tags) = result.unwrap() else { + panic!("Expected Tags"); + }; + + assert_eq!(tags, expected); + assert_eq!( + app.lock().await.data.radarr_data.tags_map, + BiMap::from_iter([(2222i64, "usenet".to_owned())]) + ); } #[tokio::test] async fn test_handle_add_radarr_tag() { - let tag_json = json!({ "id": 3, "label": "testing" }); - let response: Tag = serde_json::from_value(tag_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ "label": "testing" })), - Some(tag_json), - None, - RadarrEvent::AddTag(String::new()), - None, - None, - ) - .await; - app_arc.lock().await.data.radarr_data.tags_map = - BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let expected = Tag { + id: 3, + label: "testing".to_owned(), + }; - if let RadarrSerdeable::Tag(tag) = network + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "label": "testing" })) + .returns(tag()) + .build_for(RadarrEvent::AddTag(String::new())) + .await; + + app.lock().await.data.radarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); + + let mut network = test_network(&app); + + let result = network .handle_radarr_event(RadarrEvent::AddTag("testing".to_owned())) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.tags_map, - BiMap::from_iter([ - (1, "usenet".to_owned()), - (2, "test".to_owned()), - (3, "testing".to_owned()) - ]) - ); - assert_eq!(tag, response); - } + .await; + + mock.assert_async().await; + + let RadarrSerdeable::Tag(tag) = result.unwrap() else { + panic!("Expected Tag"); + }; + + assert_eq!(tag, expected); + assert_eq!( + app.lock().await.data.radarr_data.tags_map, + BiMap::from_iter([ + (1, "usenet".to_owned()), + (2, "test".to_owned()), + (3, "testing".to_owned()) + ]) + ); } #[tokio::test] async fn test_handle_delete_radarr_tag_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - RadarrEvent::DeleteTag(1), - Some("/1"), - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(RadarrEvent::DeleteTag(1)) + .await; - assert!(network - .handle_radarr_event(RadarrEvent::DeleteTag(1)) - .await - .is_ok()); + let mut network = test_network(&app); - async_server.assert_async().await; + let result = network.handle_radarr_event(RadarrEvent::DeleteTag(1)).await; + + mock.assert_async().await; + assert!(result.is_ok()); } #[tokio::test] @@ -315,7 +302,7 @@ mod test { (3, "hi".to_owned()), ]); } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); assert_eq!( network.extract_and_add_radarr_tag_ids_vec(tags).await, @@ -325,34 +312,29 @@ mod test { #[tokio::test] async fn test_extract_and_add_radarr_tag_ids_vec_add_missing_tags_first() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ "label": "TESTING" })), - Some(json!({ "id": 3, "label": "testing" })), - None, - RadarrEvent::GetTags, - None, - None, - ) - .await; + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "label": "TESTING" })) + .returns(json!({ "id": 3, "label": "testing" })) + .build_for(RadarrEvent::GetTags) + .await; let tags = "usenet, test, TESTING"; { - let mut app = app_arc.lock().await; - app.data.radarr_data.edit_movie_modal = Some(EditMovieModal { + let mut app_guard = app.lock().await; + app_guard.data.radarr_data.edit_movie_modal = Some(EditMovieModal { tags: tags.into(), ..EditMovieModal::default() }); - app.data.radarr_data.tags_map = + app_guard.data.radarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); let tag_ids_vec = network.extract_and_add_radarr_tag_ids_vec(tags).await; async_server.assert_async().await; assert_eq!(tag_ids_vec, vec![1, 2, 3]); assert_eq!( - app_arc.lock().await.data.radarr_data.tags_map, + app.lock().await.data.radarr_data.tags_map, BiMap::from_iter([ (1, "usenet".to_owned()), (2, "test".to_owned()), diff --git a/src/network/radarr_network/root_folders/radarr_root_folders_network_tests.rs b/src/network/radarr_network/root_folders/radarr_root_folders_network_tests.rs index abc806c..f323d45 100644 --- a/src/network/radarr_network/root_folders/radarr_root_folders_network_tests.rs +++ b/src/network/radarr_network/root_folders/radarr_root_folders_network_tests.rs @@ -2,62 +2,52 @@ mod tests { use crate::models::radarr_models::RadarrSerdeable; use crate::models::servarr_models::{AddRootFolderBody, RootFolder}; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::radarr_network::radarr_network_test_utils::test_utils::root_folder; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::radarr_network::RadarrEvent; - use crate::network::{Network, RequestMethod}; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::root_folder; use pretty_assertions::assert_eq; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_add_radarr_root_folder_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "path": "/nfs/test" - })), - Some(json!({})), - None, - RadarrEvent::AddRootFolder(AddRootFolderBody::default()), - None, - None, - ) - .await; + })) + .returns(json!({})) + .build_for(RadarrEvent::AddRootFolder(AddRootFolderBody::default())) + .await; let add_root_folder_body = AddRootFolderBody { path: "/nfs/test".to_owned(), }; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::AddRootFolder(add_root_folder_body)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::AddRootFolder(add_root_folder_body)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_delete_radarr_root_folder_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - RadarrEvent::DeleteRootFolder(1), - Some("/1"), - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(RadarrEvent::DeleteRootFolder(1)) + .await; + let mut network = test_network(&app); - assert!(network - .handle_radarr_event(RadarrEvent::DeleteRootFolder(1)) - .await - .is_ok()); + assert!( + network + .handle_radarr_event(RadarrEvent::DeleteRootFolder(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -69,29 +59,24 @@ mod tests { "freeSpace": 219902325555200u64, }]); let response: Vec = serde_json::from_value(root_folder_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(root_folder_json), - None, - RadarrEvent::GetRootFolders, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(root_folder_json) + .build_for(RadarrEvent::GetRootFolders) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::RootFolders(root_folders) = network + let RadarrSerdeable::RootFolders(root_folders) = network .handle_radarr_event(RadarrEvent::GetRootFolders) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.root_folders.items, - vec![root_folder()] - ); - assert_eq!(root_folders, response); - } + else { + panic!("Expected RootFolders") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.root_folders.items, + vec![root_folder()] + ); + assert_eq!(root_folders, response); } } diff --git a/src/network/radarr_network/system/mod.rs b/src/network/radarr_network/system/mod.rs index 1dde56e..6091a55 100644 --- a/src/network/radarr_network/system/mod.rs +++ b/src/network/radarr_network/system/mod.rs @@ -72,17 +72,29 @@ impl Network<'_, '_> { "{}|{}|{}|{}|{}", log.time, log.level.to_uppercase(), - log.logger.as_ref().unwrap(), - log.exception_type.as_ref().unwrap(), - log.exception.as_ref().unwrap() + log + .logger + .as_ref() + .expect("logger must exist when exception is present"), + log + .exception_type + .as_ref() + .expect("exception_type must exist when exception is present"), + log + .exception + .as_ref() + .expect("exception must exist in this branch") )) } else { HorizontallyScrollableText::from(format!( "{}|{}|{}|{}", log.time, log.level.to_uppercase(), - log.logger.as_ref().unwrap(), - log.message.as_ref().unwrap() + log.logger.as_ref().expect("logger must exist in log entry"), + log + .message + .as_ref() + .expect("message must exist when exception is not present") )) } }) @@ -173,9 +185,9 @@ impl Network<'_, '_> { .map(|update| { let install_status = if update.installed_on.is_some() { if update.installed { - "(Currently Installed)".to_owned() + " (Currently Installed)".to_owned() } else { - "(Previously Installed)".to_owned() + " (Previously Installed)".to_owned() } } else { String::new() @@ -189,7 +201,7 @@ impl Network<'_, '_> { }; let mut update_info = formatdoc!( - "{} - {} {install_status} + "{} - {}{install_status} {}", update.version, update.release_date, diff --git a/src/network/radarr_network/system/radarr_system_network_tests.rs b/src/network/radarr_network/system/radarr_system_network_tests.rs index e7b28d0..bc07454 100644 --- a/src/network/radarr_network/system/radarr_system_network_tests.rs +++ b/src/network/radarr_network/system/radarr_system_network_tests.rs @@ -1,26 +1,21 @@ #[cfg(test)] mod tests { + use crate::models::HorizontallyScrollableText; use crate::models::radarr_models::{RadarrSerdeable, RadarrTask, RadarrTaskName, SystemStatus}; use crate::models::servarr_models::{ DiskSpace, HostConfig, LogResponse, QueueEvent, SecurityConfig, Update, }; - use crate::models::{HorizontallyScrollableText, ScrollableText}; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::radarr_network::RadarrEvent; - use crate::network::{Network, RequestMethod}; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::updates; use chrono::DateTime; - use indoc::formatdoc; use pretty_assertions::{assert_eq, assert_str_eq}; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_get_radarr_diskspace_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([ + let (mock, app, _server) = MockServarrApi::get() + .returns(json!([ { "freeSpace": 1111, "totalSpace": 2222, @@ -29,14 +24,10 @@ mod tests { "freeSpace": 3333, "totalSpace": 4444 } - ])), - None, - RadarrEvent::GetDiskSpace, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + ])) + .build_for(RadarrEvent::GetDiskSpace) + .await; + let mut network = test_network(&app); let disk_space_vec = vec![ DiskSpace { free_space: 1111, @@ -48,18 +39,19 @@ mod tests { }, ]; - if let RadarrSerdeable::DiskSpaces(disk_space) = network + let RadarrSerdeable::DiskSpaces(disk_space) = network .handle_radarr_event(RadarrEvent::GetDiskSpace) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.disk_space_vec, - disk_space_vec - ); - assert_eq!(disk_space, disk_space_vec); - } + else { + panic!("Expected DiskSpaces") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.disk_space_vec, + disk_space_vec + ); + assert_eq!(disk_space, disk_space_vec); } #[tokio::test] @@ -76,26 +68,21 @@ mod tests { "sslCertPassword": "test" }); let response: HostConfig = serde_json::from_value(host_config_response.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(host_config_response), - None, - RadarrEvent::GetHostConfig, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(host_config_response) + .build_for(RadarrEvent::GetHostConfig) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::HostConfig(host_config) = network + let RadarrSerdeable::HostConfig(host_config) = network .handle_radarr_event(RadarrEvent::GetHostConfig) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(host_config, response); - } + else { + panic!("Expected HostConfig") + }; + mock.assert_async().await; + assert_eq!(host_config, response); } #[tokio::test] @@ -131,29 +118,24 @@ mod tests { ] }); let response: LogResponse = serde_json::from_value(logs_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(logs_response_json), - None, - RadarrEvent::GetLogs(500), - None, - Some("pageSize=500&sortDirection=descending&sortKey=time"), - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(logs_response_json) + .query("pageSize=500&sortDirection=descending&sortKey=time") + .build_for(RadarrEvent::GetLogs(500)) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::LogResponse(logs) = network + let RadarrSerdeable::LogResponse(logs) = network .handle_radarr_event(RadarrEvent::GetLogs(500)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.logs.items, - expected_logs - ); - assert!(app_arc + else { + panic!("Expected LogResponse") + }; + mock.assert_async().await; + assert_eq!(app.lock().await.data.radarr_data.logs.items, expected_logs); + assert!( + app .lock() .await .data @@ -161,9 +143,9 @@ mod tests { .logs .current_selection() .text - .contains("INFO")); - assert_eq!(logs, response); - } + .contains("INFO") + ); + assert_eq!(logs, response); } #[tokio::test] @@ -191,30 +173,25 @@ mod tests { trigger: "scheduled".to_owned(), }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(queued_events_json), - None, - RadarrEvent::GetQueuedEvents, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(queued_events_json) + .build_for(RadarrEvent::GetQueuedEvents) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::QueueEvents(events) = network + let RadarrSerdeable::QueueEvents(events) = network .handle_radarr_event(RadarrEvent::GetQueuedEvents) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.queued_events.items, - vec![expected_event] - ); - assert_eq!(events, response); - } + else { + panic!("Expected QueueEvents") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.queued_events.items, + vec![expected_event] + ); + assert_eq!(events, response); } #[tokio::test] @@ -229,62 +206,52 @@ mod tests { }); let response: SecurityConfig = serde_json::from_value(security_config_response.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(security_config_response), - None, - RadarrEvent::GetSecurityConfig, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(security_config_response) + .build_for(RadarrEvent::GetSecurityConfig) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::SecurityConfig(security_config) = network + let RadarrSerdeable::SecurityConfig(security_config) = network .handle_radarr_event(RadarrEvent::GetSecurityConfig) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(security_config, response); - } + else { + panic!("Expected SecurityConfig") + }; + mock.assert_async().await; + assert_eq!(security_config, response); } #[tokio::test] async fn test_handle_get_radarr_status_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::get() + .returns(json!({ "version": "v1", "startTime": "2023-02-25T20:16:43Z" - })), - None, - RadarrEvent::GetStatus, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .build_for(RadarrEvent::GetStatus) + .await; + let mut network = test_network(&app); let date_time = DateTime::from(DateTime::parse_from_rfc3339("2023-02-25T20:16:43Z").unwrap()); - if let RadarrSerdeable::SystemStatus(status) = network + let RadarrSerdeable::SystemStatus(status) = network .handle_radarr_event(RadarrEvent::GetStatus) .await .unwrap() - { - async_server.assert_async().await; - assert_str_eq!(app_arc.lock().await.data.radarr_data.version, "v1"); - assert_eq!(app_arc.lock().await.data.radarr_data.start_time, date_time); - assert_eq!( - status, - SystemStatus { - version: "v1".to_owned(), - start_time: date_time - } - ); - } + else { + panic!("Expected SystemStatus") + }; + async_server.assert_async().await; + assert_str_eq!(app.lock().await.data.radarr_data.version, "v1"); + assert_eq!(app.lock().await.data.radarr_data.start_time, date_time); + assert_eq!( + status, + SystemStatus { + version: "v1".to_owned(), + start_time: date_time + } + ); } #[tokio::test] @@ -330,56 +297,26 @@ mod tests { }, }]); let response: Vec = serde_json::from_value(updates_json.clone()).unwrap(); - let line_break = "-".repeat(200); - let expected_text = ScrollableText::with_string(formatdoc!( - " - The latest version of Radarr is already installed + let expected_text = updates(); + let (async_server, app, _server) = MockServarrApi::get() + .returns(updates_json) + .build_for(RadarrEvent::GetUpdates) + .await; + let mut network = test_network(&app); - 4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) - {line_break} - New: - * Cool new thing - Fixed: - * Some bugs killed - - - 3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) - {line_break} - New: - * Cool new thing (old) - * Other cool new thing (old) - - - 2.1.0 - 2023-04-15 02:02:53 UTC - {line_break} - Fixed: - * Killed bug 1 - * Fixed bug 2" - )); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(updates_json), - None, - RadarrEvent::GetUpdates, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); - - if let RadarrSerdeable::Updates(updates) = network + let RadarrSerdeable::Updates(updates) = network .handle_radarr_event(RadarrEvent::GetUpdates) .await .unwrap() - { - async_server.assert_async().await; - assert_str_eq!( - app_arc.lock().await.data.radarr_data.updates.get_text(), - expected_text.get_text() - ); - assert_eq!(updates, response); - } + else { + panic!("Expected Updates") + }; + async_server.assert_async().await; + assert_str_eq!( + app.lock().await.data.radarr_data.updates.get_text(), + expected_text.get_text() + ); + assert_eq!(updates, response); } #[tokio::test] @@ -420,58 +357,51 @@ mod tests { last_duration: "00:00:00.5111547".to_owned(), }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(tasks_json), - None, - RadarrEvent::GetTasks, - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(tasks_json) + .build_for(RadarrEvent::GetTasks) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::Tasks(tasks) = network + let RadarrSerdeable::Tasks(tasks) = network .handle_radarr_event(RadarrEvent::GetTasks) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.radarr_data.tasks.items, - expected_tasks - ); - assert_eq!(tasks, response); - } + else { + panic!("Expected Tasks") + }; + async_server.assert_async().await; + assert_eq!( + app.lock().await.data.radarr_data.tasks.items, + expected_tasks + ); + assert_eq!(tasks, response); } #[tokio::test] async fn test_handle_start_radarr_task_event() { let response = json!({ "test": "test"}); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "ApplicationCheckUpdate" - })), - Some(response.clone()), - None, - RadarrEvent::StartTask(RadarrTaskName::ApplicationCheckUpdate), - None, - None, - ) - .await; - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(response.clone()) + .build_for(RadarrEvent::StartTask( + RadarrTaskName::ApplicationCheckUpdate, + )) + .await; + let mut network = test_network(&app); - if let RadarrSerdeable::Value(value) = network + let RadarrSerdeable::Value(value) = network .handle_radarr_event(RadarrEvent::StartTask( RadarrTaskName::ApplicationCheckUpdate, )) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(value, response); - } + else { + panic!("Expected Value") + }; + async_server.assert_async().await; + assert_eq!(value, response); } } diff --git a/src/network/servarr_test_utils.rs b/src/network/servarr_test_utils.rs new file mode 100644 index 0000000..0f79be9 --- /dev/null +++ b/src/network/servarr_test_utils.rs @@ -0,0 +1,35 @@ +use crate::models::servarr_data::modals::IndexerTestResultModalItem; +use crate::models::servarr_models::{DiskSpace, QueueEvent}; +use chrono::DateTime; + +pub fn diskspace() -> DiskSpace { + DiskSpace { + free_space: 6500, + total_space: 8675309, + } +} + +pub fn indexer_test_result() -> IndexerTestResultModalItem { + IndexerTestResultModalItem { + name: "DrunkenSlug".to_owned(), + is_valid: false, + validation_failures: "Some failure".into(), + } +} + +pub fn queued_event() -> QueueEvent { + QueueEvent { + trigger: "manual".to_string(), + name: "Refresh Monitored Downloads".to_string(), + command_name: "Refresh Monitored Downloads".to_string(), + status: "completed".to_string(), + queued: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T21:25:16Z").unwrap()), + started: Some(DateTime::from( + DateTime::parse_from_rfc3339("2023-05-20T21:25:30Z").unwrap(), + )), + ended: Some(DateTime::from( + DateTime::parse_from_rfc3339("2023-05-20T21:28:33Z").unwrap(), + )), + duration: Some("00:03:03".to_owned()), + } +} diff --git a/src/network/sonarr_network/blocklist/mod.rs b/src/network/sonarr_network/blocklist/mod.rs index 648b853..d43f46e 100644 --- a/src/network/sonarr_network/blocklist/mod.rs +++ b/src/network/sonarr_network/blocklist/mod.rs @@ -1,11 +1,11 @@ +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::sonarr_models::{BlocklistItem, BlocklistResponse}; -use crate::models::Route; use crate::network::sonarr_network::SonarrEvent; use crate::network::{Network, RequestMethod}; use anyhow::Result; use log::info; -use serde_json::{json, Value}; +use serde_json::{Value, json}; #[cfg(test)] #[path = "sonarr_blocklist_network_tests.rs"] diff --git a/src/network/sonarr_network/blocklist/sonarr_blocklist_network_tests.rs b/src/network/sonarr_network/blocklist/sonarr_blocklist_network_tests.rs index 75ec0c8..a8d27d8 100644 --- a/src/network/sonarr_network/blocklist/sonarr_blocklist_network_tests.rs +++ b/src/network/sonarr_network/blocklist/sonarr_blocklist_network_tests.rs @@ -3,17 +3,14 @@ mod tests { use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::sonarr_models::{BlocklistItem, BlocklistResponse, Series, SonarrSerdeable}; use crate::models::stateful_table::SortOption; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::sonarr_network::SonarrEvent; use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ blocklist_item, series, }; - use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, RequestMethod}; use pretty_assertions::assert_eq; - use reqwest::Client; use rstest::rstest; - use serde_json::{json, Number}; - use tokio_util::sync::CancellationToken; + use serde_json::{Number, json}; #[tokio::test] async fn test_handle_clear_sonarr_blocklist_event() { @@ -32,62 +29,54 @@ mod tests { }, ]; let expected_request_json = json!({ "ids": [1, 2, 3]}); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - Some(expected_request_json), - None, - None, - SonarrEvent::ClearBlocklist, - None, - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::delete() + .with_request_body(expected_request_json) + .build_for(SonarrEvent::ClearBlocklist) + .await; + app .lock() .await .data .sonarr_data .blocklist .set_items(blocklist_items); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::ClearBlocklist) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::ClearBlocklist) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] async fn test_handle_delete_sonarr_blocklist_item_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteBlocklistItem(1), - Some("/1"), - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(SonarrEvent::DeleteBlocklistItem(1)) + .await; + app .lock() .await .data .sonarr_data .blocklist .set_items(vec![blocklist_item()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteBlocklistItem(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteBlocklistItem(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[rstest] @@ -107,6 +96,7 @@ mod tests { }, { "seriesId": 2001, + "seriesTitle": "Test Series", "episodeIds": [42018], "sourceTitle": "A Series", "languages": [{ "id": 1, "name": "English" }], @@ -135,17 +125,11 @@ mod tests { ..blocklist_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(blocklist_json), - None, - SonarrEvent::GetBlocklist, - None, - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(blocklist_json) + .build_for(SonarrEvent::GetBlocklist) + .await; + app .lock() .await .data @@ -156,7 +140,7 @@ mod tests { title: "Z Series".into(), ..series() }]); - app_arc.lock().await.data.sonarr_data.blocklist.sort_asc = true; + app.lock().await.data.sonarr_data.blocklist.sort_asc = true; if use_custom_sorting { let cmp_fn = |a: &BlocklistItem, b: &BlocklistItem| { a.source_title @@ -169,7 +153,7 @@ mod tests { name: "Source Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data @@ -177,22 +161,23 @@ mod tests { .blocklist .sorting(vec![blocklist_sort_option]); } - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::BlocklistResponse(blocklist) = network + let SonarrSerdeable::BlocklistResponse(blocklist) = network .handle_sonarr_event(SonarrEvent::GetBlocklist) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.blocklist.items, - expected_blocklist - ); - assert!(app_arc.lock().await.data.sonarr_data.blocklist.sort_asc); - assert_eq!(blocklist, response); - } + else { + panic!("Expected BlocklistResponse") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.blocklist.items, + expected_blocklist + ); + assert!(app.lock().await.data.sonarr_data.blocklist.sort_asc); + assert_eq!(blocklist, response); } #[tokio::test] @@ -222,18 +207,12 @@ mod tests { "id": 456 }]}); let response: BlocklistResponse = serde_json::from_value(blocklist_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(blocklist_json), - None, - SonarrEvent::GetBlocklist, - None, - None, - ) - .await; - app_arc.lock().await.data.sonarr_data.blocklist.sort_asc = true; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(blocklist_json) + .build_for(SonarrEvent::GetBlocklist) + .await; + app.lock().await.data.sonarr_data.blocklist.sort_asc = true; + app .lock() .await .push_navigation_stack(ActiveSonarrBlock::BlocklistSortPrompt.into()); @@ -246,25 +225,26 @@ mod tests { name: "Source Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data .sonarr_data .blocklist .sorting(vec![blocklist_sort_option]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::BlocklistResponse(blocklist) = network + let SonarrSerdeable::BlocklistResponse(blocklist) = network .handle_sonarr_event(SonarrEvent::GetBlocklist) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc.lock().await.data.sonarr_data.blocklist.is_empty()); - assert!(app_arc.lock().await.data.sonarr_data.blocklist.sort_asc); - assert_eq!(blocklist, response); - } + else { + panic!("Expected BlocklistResponse") + }; + mock.assert_async().await; + assert!(app.lock().await.data.sonarr_data.blocklist.is_empty()); + assert!(app.lock().await.data.sonarr_data.blocklist.sort_asc); + assert_eq!(blocklist, response); } } diff --git a/src/network/sonarr_network/downloads/sonarr_downloads_network_tests.rs b/src/network/sonarr_network/downloads/sonarr_downloads_network_tests.rs index 4500b45..3a74f39 100644 --- a/src/network/sonarr_network/downloads/sonarr_downloads_network_tests.rs +++ b/src/network/sonarr_network/downloads/sonarr_downloads_network_tests.rs @@ -1,45 +1,38 @@ #[cfg(test)] mod tests { use crate::models::sonarr_models::{DownloadsResponse, SonarrSerdeable}; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::sonarr_network::SonarrEvent; use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ download_record, downloads_response, }; - use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, RequestMethod}; use pretty_assertions::assert_eq; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_delete_sonarr_download_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteDownload(1), - Some("/1"), - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(SonarrEvent::DeleteDownload(1)) + .await; + app .lock() .await .data .sonarr_data .downloads .set_items(vec![download_record()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteDownload(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteDownload(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -59,55 +52,48 @@ mod tests { }); let response: DownloadsResponse = serde_json::from_value(downloads_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(downloads_response_json), - None, - SonarrEvent::GetDownloads(500), - None, - Some("pageSize=500"), - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(downloads_response_json) + .query("pageSize=500") + .build_for(SonarrEvent::GetDownloads(500)) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::DownloadsResponse(downloads) = network + let SonarrSerdeable::DownloadsResponse(downloads) = network .handle_sonarr_event(SonarrEvent::GetDownloads(500)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.downloads.items, - downloads_response().records - ); - assert_eq!(downloads, response); - } + else { + panic!("Expected DownloadsResponse") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.downloads.items, + downloads_response().records + ); + assert_eq!(downloads, response); } #[tokio::test] async fn test_handle_update_sonarr_downloads_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "RefreshMonitoredDownloads" - })), - Some(json!({})), - None, - SonarrEvent::UpdateDownloads, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::UpdateDownloads) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::UpdateDownloads) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::UpdateDownloads) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } } diff --git a/src/network/sonarr_network/history/mod.rs b/src/network/sonarr_network/history/mod.rs index 20e1fff..0fddf3c 100644 --- a/src/network/sonarr_network/history/mod.rs +++ b/src/network/sonarr_network/history/mod.rs @@ -1,6 +1,6 @@ +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::sonarr_models::SonarrHistoryWrapper; -use crate::models::Route; use crate::network::sonarr_network::SonarrEvent; use crate::network::{Network, RequestMethod}; use anyhow::Result; diff --git a/src/network/sonarr_network/history/sonarr_history_network_tests.rs b/src/network/sonarr_network/history/sonarr_history_network_tests.rs index aa5476f..7bb1dae 100644 --- a/src/network/sonarr_network/history/sonarr_history_network_tests.rs +++ b/src/network/sonarr_network/history/sonarr_history_network_tests.rs @@ -3,15 +3,12 @@ mod tests { use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::sonarr_models::{SonarrHistoryItem, SonarrHistoryWrapper, SonarrSerdeable}; use crate::models::stateful_table::SortOption; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::history_item; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, RequestMethod}; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::history_item; use pretty_assertions::assert_eq; - use reqwest::Client; use rstest::rstest; use serde_json::json; - use tokio_util::sync::CancellationToken; #[rstest] #[tokio::test] @@ -57,17 +54,12 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetHistory(500), - None, - Some("pageSize=500&sortDirection=descending&sortKey=date"), - ) - .await; - app_arc.lock().await.data.sonarr_data.history.sort_asc = true; + let (mock, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("pageSize=500&sortDirection=descending&sortKey=date") + .build_for(SonarrEvent::GetHistory(500)) + .await; + app.lock().await.data.sonarr_data.history.sort_asc = true; if use_custom_sorting { let cmp_fn = |a: &SonarrHistoryItem, b: &SonarrHistoryItem| { a.source_title @@ -81,7 +73,7 @@ mod tests { name: "Source Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data @@ -89,22 +81,23 @@ mod tests { .history .sorting(vec![history_sort_option]); } - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryWrapper(history) = network + let SonarrSerdeable::SonarrHistoryWrapper(history) = network .handle_sonarr_event(SonarrEvent::GetHistory(500)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.history.items, - expected_history_items - ); - assert!(app_arc.lock().await.data.sonarr_data.history.sort_asc); - assert_eq!(history, response); - } + else { + panic!("Expected SonarrHistoryWrapper") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.history.items, + expected_history_items + ); + assert!(app.lock().await.data.sonarr_data.history.sort_asc); + assert_eq!(history, response); } #[tokio::test] @@ -136,18 +129,13 @@ mod tests { } }]}); let response: SonarrHistoryWrapper = serde_json::from_value(history_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetHistory(500), - None, - Some("pageSize=500&sortDirection=descending&sortKey=date"), - ) - .await; - app_arc.lock().await.data.sonarr_data.history.sort_asc = true; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("pageSize=500&sortDirection=descending&sortKey=date") + .build_for(SonarrEvent::GetHistory(500)) + .await; + app.lock().await.data.sonarr_data.history.sort_asc = true; + app .lock() .await .push_navigation_stack(ActiveSonarrBlock::HistorySortPrompt.into()); @@ -161,50 +149,50 @@ mod tests { name: "Source Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data .sonarr_data .history .sorting(vec![history_sort_option]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryWrapper(history) = network + let SonarrSerdeable::SonarrHistoryWrapper(history) = network .handle_sonarr_event(SonarrEvent::GetHistory(500)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc.lock().await.data.sonarr_data.history.is_empty()); - assert!(app_arc.lock().await.data.sonarr_data.history.sort_asc); - assert_eq!(history, response); - } + else { + panic!("Expected SonarrHistoryWrapper") + }; + mock.assert_async().await; + assert!(app.lock().await.data.sonarr_data.history.is_empty()); + assert!(app.lock().await.data.sonarr_data.history.sort_asc); + assert_eq!(history, response); } #[tokio::test] async fn test_handle_mark_sonarr_history_item_as_failed_event() { let expected_history_item_id = 1; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - None, - Some(json!({})), - None, - SonarrEvent::MarkHistoryItemAsFailed(expected_history_item_id), - Some("/1"), - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); - - assert!(network - .handle_sonarr_event(SonarrEvent::MarkHistoryItemAsFailed( - expected_history_item_id + let (mock, app, _server) = MockServarrApi::post() + .returns(json!({})) + .path("/1") + .build_for(SonarrEvent::MarkHistoryItemAsFailed( + expected_history_item_id, )) - .await - .is_ok()); - async_server.assert_async().await; + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); + + assert!( + network + .handle_sonarr_event(SonarrEvent::MarkHistoryItemAsFailed( + expected_history_item_id + )) + .await + .is_ok() + ); + mock.assert_async().await; } } diff --git a/src/network/sonarr_network/indexers/mod.rs b/src/network/sonarr_network/indexers/mod.rs index ed19639..7200d47 100644 --- a/src/network/sonarr_network/indexers/mod.rs +++ b/src/network/sonarr_network/indexers/mod.rs @@ -4,9 +4,9 @@ use crate::models::sonarr_models::IndexerSettings; use crate::models::stateful_table::StatefulTable; use crate::network::sonarr_network::SonarrEvent; use crate::network::{Network, RequestMethod}; -use anyhow::Result; +use anyhow::{Context, Result}; use log::{debug, info}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; #[cfg(test)] #[path = "sonarr_indexers_network_tests.rs"] @@ -101,57 +101,57 @@ impl Network<'_, '_> { ) = { let priority = detailed_indexer_body["priority"] .as_i64() - .expect("Unable to deserialize 'priority'"); + .context("Failed to deserialize indexer 'priority' field")?; let seed_ratio_field_option = detailed_indexer_body["fields"] .as_array() - .unwrap() + .context("Failed to get indexer 'fields' array")? .iter() .find(|field| field["name"] == "seedCriteria.seedRatio"); let name = edit_indexer_params.name.unwrap_or( detailed_indexer_body["name"] .as_str() - .expect("Unable to deserialize 'name'") + .context("Failed to deserialize indexer 'name' field")? .to_owned(), ); let enable_rss = edit_indexer_params.enable_rss.unwrap_or( detailed_indexer_body["enableRss"] .as_bool() - .expect("Unable to deserialize 'enableRss'"), + .context("Failed to deserialize indexer 'enableRss' field")?, ); let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or( detailed_indexer_body["enableAutomaticSearch"] .as_bool() - .expect("Unable to deserialize 'enableAutomaticSearch"), + .context("Failed to deserialize indexer 'enableAutomaticSearch' field")?, ); let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or( detailed_indexer_body["enableInteractiveSearch"] .as_bool() - .expect("Unable to deserialize 'enableInteractiveSearch'"), + .context("Failed to deserialize indexer 'enableInteractiveSearch' field")?, ); let url = edit_indexer_params.url.unwrap_or( detailed_indexer_body["fields"] .as_array() - .expect("Unable to deserialize 'fields'") + .context("Failed to get indexer 'fields' array for baseUrl")? .iter() .find(|field| field["name"] == "baseUrl") - .expect("Field 'baseUrl' was not found in the 'fields' array") + .context("Field 'baseUrl' was not found in the indexer fields array")? .get("value") .unwrap_or(&json!("")) .as_str() - .expect("Unable to deserialize 'baseUrl value'") + .context("Failed to deserialize indexer 'baseUrl' value")? .to_owned(), ); let api_key = edit_indexer_params.api_key.unwrap_or( detailed_indexer_body["fields"] .as_array() - .expect("Unable to deserialize 'fields'") + .context("Failed to get indexer 'fields' array for apiKey")? .iter() .find(|field| field["name"] == "apiKey") - .expect("Field 'apiKey' was not found in the 'fields' array") + .context("Field 'apiKey' was not found in the indexer fields array")? .get("value") .unwrap_or(&json!("")) .as_str() - .expect("Unable to deserialize 'apiKey value'") + .context("Failed to deserialize indexer 'apiKey' value")? .to_owned(), ); let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| { @@ -160,7 +160,7 @@ impl Network<'_, '_> { .get("value") .unwrap_or(&json!("")) .as_str() - .expect("Unable to deserialize 'seedCriteria.seedRatio value'") + .unwrap_or("") .to_owned(); } @@ -172,10 +172,14 @@ impl Network<'_, '_> { edit_indexer_params.tags.unwrap_or( detailed_indexer_body["tags"] .as_array() - .expect("Unable to deserialize 'tags'") + .context("Failed to get indexer 'tags' array")? .iter() - .map(|item| item.as_i64().expect("Unable to deserialize tag ID")) - .collect(), + .map(|item| { + item + .as_i64() + .context("Failed to deserialize indexer tag ID") + }) + .collect::>>()?, ) }; let priority = edit_indexer_params.priority.unwrap_or(priority); @@ -193,47 +197,54 @@ impl Network<'_, '_> { ) }; - *detailed_indexer_body.get_mut("name").unwrap() = json!(name); - *detailed_indexer_body.get_mut("priority").unwrap() = json!(priority); - *detailed_indexer_body.get_mut("enableRss").unwrap() = json!(enable_rss); + *detailed_indexer_body + .get_mut("name") + .context("Failed to get mutable reference to indexer 'name' field")? = json!(name); + *detailed_indexer_body + .get_mut("priority") + .context("Failed to get mutable reference to indexer 'priority' field")? = json!(priority); + *detailed_indexer_body + .get_mut("enableRss") + .context("Failed to get mutable reference to indexer 'enableRss' field")? = json!(enable_rss); *detailed_indexer_body .get_mut("enableAutomaticSearch") - .unwrap() = json!(enable_automatic_search); + .context("Failed to get mutable reference to indexer 'enableAutomaticSearch' field")? = + json!(enable_automatic_search); *detailed_indexer_body .get_mut("enableInteractiveSearch") - .unwrap() = json!(enable_interactive_search); + .context("Failed to get mutable reference to indexer 'enableInteractiveSearch' field")? = + json!(enable_interactive_search); *detailed_indexer_body .get_mut("fields") - .unwrap() - .as_array_mut() - .unwrap() + .and_then(|f| f.as_array_mut()) + .context("Failed to get mutable reference to indexer 'fields' array")? .iter_mut() .find(|field| field["name"] == "baseUrl") - .unwrap() + .context("Failed to find 'baseUrl' field in indexer fields array")? .get_mut("value") - .unwrap() = json!(url); + .context("Failed to get mutable reference to 'baseUrl' value")? = json!(url); *detailed_indexer_body .get_mut("fields") - .unwrap() - .as_array_mut() - .unwrap() + .and_then(|f| f.as_array_mut()) + .context("Failed to get mutable reference to indexer 'fields' array for apiKey")? .iter_mut() .find(|field| field["name"] == "apiKey") - .unwrap() + .context("Failed to find 'apiKey' field in indexer fields array")? .get_mut("value") - .unwrap() = json!(api_key); - *detailed_indexer_body.get_mut("tags").unwrap() = json!(tags); + .context("Failed to get mutable reference to 'apiKey' value")? = json!(api_key); + *detailed_indexer_body + .get_mut("tags") + .context("Failed to get mutable reference to indexer 'tags' field")? = json!(tags); let seed_ratio_field_option = detailed_indexer_body .get_mut("fields") - .unwrap() - .as_array_mut() - .unwrap() + .and_then(|f| f.as_array_mut()) + .context("Failed to get mutable reference to indexer 'fields' array for seed ratio")? .iter_mut() .find(|field| field["name"] == "seedCriteria.seedRatio"); if let Some(seed_ratio_field) = seed_ratio_field_option { seed_ratio_field .as_object_mut() - .unwrap() + .context("Failed to get mutable reference to 'seedCriteria.seedRatio' object")? .insert("value".to_string(), json!(seed_ratio)); } @@ -330,12 +341,13 @@ impl Network<'_, '_> { self .handle_request::(request_props, |test_results, mut app| { if test_results.as_object().is_none() { - app.data.sonarr_data.indexer_test_errors = Some( - test_results.as_array().unwrap()[0] - .get("errorMessage") - .unwrap() - .to_string(), - ); + let error_message = test_results + .as_array() + .and_then(|arr| arr.first()) + .and_then(|item| item.get("errorMessage")) + .map(|msg| msg.to_string()) + .unwrap_or_else(|| "Unknown indexer test error".to_string()); + app.data.sonarr_data.indexer_test_errors = Some(error_message); } else { app.data.sonarr_data.indexer_test_errors = Some(String::new()); }; diff --git a/src/network/sonarr_network/indexers/sonarr_indexers_network_tests.rs b/src/network/sonarr_network/indexers/sonarr_indexers_network_tests.rs index 4a4ed73..3bd86bd 100644 --- a/src/network/sonarr_network/indexers/sonarr_indexers_network_tests.rs +++ b/src/network/sonarr_network/indexers/sonarr_indexers_network_tests.rs @@ -1,50 +1,44 @@ #[cfg(test)] mod tests { + use crate::models::HorizontallyScrollableText; use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_models::{EditIndexerParams, Indexer, IndexerTestResult}; use crate::models::sonarr_models::SonarrSerdeable; - use crate::models::HorizontallyScrollableText; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::sonarr_network::SonarrEvent; use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ indexer, indexer_settings, }; - use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, NetworkResource, RequestMethod}; use bimap::BiMap; use mockito::Matcher; use pretty_assertions::assert_eq; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_delete_sonarr_indexer_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteIndexer(1), - Some("/1"), - None, - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(SonarrEvent::DeleteIndexer(1)) + .await; + app .lock() .await .data .sonarr_data .indexers .set_items(vec![indexer()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteIndexer(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteIndexer(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -56,26 +50,22 @@ mod tests { "retention": 1, "rssSyncInterval": 60 }); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Put, - Some(indexer_settings_json), - None, - None, - SonarrEvent::EditAllIndexerSettings(indexer_settings()), - None, - None, - ) - .await; + let (mock, app, _server) = MockServarrApi::put() + .with_request_body(indexer_settings_json) + .build_for(SonarrEvent::EditAllIndexerSettings(indexer_settings())) + .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditAllIndexerSettings(indexer_settings())) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditAllIndexerSettings(indexer_settings())) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -139,17 +129,12 @@ mod tests { "tags": [1, 2], "id": 1 }); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; - let async_edit_server = server + let (mock_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; + let mock_edit_server = server .mock( "PUT", format!( @@ -163,23 +148,25 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.sonarr_data.tags_map = + app.lock().await.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details_server.assert_async().await; + mock_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_sonarr_indexer_event_does_not_overwrite_tags_vec_if_tag_input_string_is_none( - ) { + async fn test_handle_edit_sonarr_indexer_event_does_not_overwrite_tags_vec_if_tag_input_string_is_none() + { let expected_edit_indexer_params = EditIndexerParams { indexer_id: 1, name: Some("Test Update".to_owned()), @@ -239,17 +226,12 @@ mod tests { "tags": [1, 2], "id": 1 }); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; - let async_edit_server = server + let (mock_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; + let mock_edit_server = server .mock( "PUT", format!( @@ -263,21 +245,23 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details_server.assert_async().await; + mock_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_sonarr_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details( - ) { + async fn test_handle_edit_sonarr_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details() + { let expected_edit_indexer_params = EditIndexerParams { indexer_id: 1, name: Some("Test Update".to_owned()), @@ -330,17 +314,12 @@ mod tests { "id": 1 }); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; - let async_edit_server = server + let (mock_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; + let mock_edit_server = server .mock( "PUT", format!( @@ -354,23 +333,25 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.sonarr_data.tags_map = + app.lock().await.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details_server.assert_async().await; + mock_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_sonarr_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details( - ) { + async fn test_handle_edit_sonarr_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details() + { let expected_edit_indexer_params = EditIndexerParams { indexer_id: 1, name: Some("Test Update".to_owned()), @@ -430,17 +411,12 @@ mod tests { "id": 1 }); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; - let async_edit_server = server + let (mock_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; + let mock_edit_server = server .mock( "PUT", format!( @@ -454,18 +430,20 @@ mod tests { .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - app_arc.lock().await.data.sonarr_data.tags_map = + app.lock().await.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditIndexer(expected_edit_indexer_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details_server.assert_async().await; + mock_edit_server.assert_async().await; } #[tokio::test] @@ -497,17 +475,12 @@ mod tests { indexer_id: 1, ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json.clone()), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; - let async_edit_server = server + let (mock_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json.clone()) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; + let mock_edit_server = server .mock( "PUT", format!( @@ -521,16 +494,18 @@ mod tests { .match_body(Matcher::Json(indexer_details_json)) .create_async() .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); - async_details_server.assert_async().await; - async_edit_server.assert_async().await; + mock_details_server.assert_async().await; + mock_edit_server.assert_async().await; } #[tokio::test] @@ -587,16 +562,11 @@ mod tests { ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; let async_edit_server = server .mock( "PUT", @@ -611,13 +581,15 @@ mod tests { .match_body(Matcher::Json(expected_edit_indexer_body)) .create_async() .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditIndexer(edit_indexer_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -656,31 +628,26 @@ mod tests { "id": 1 }]); let response: Vec = serde_json::from_value(indexers_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexers_response_json), - None, - SonarrEvent::GetIndexers, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(indexers_response_json) + .build_for(SonarrEvent::GetIndexers) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Indexers(indexers) = network + let SonarrSerdeable::Indexers(indexers) = network .handle_sonarr_event(SonarrEvent::GetIndexers) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.indexers.items, - vec![indexer()] - ); - assert_eq!(indexers, response); - } + else { + panic!("Expected Indexers") + }; + async_server.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.indexers.items, + vec![indexer()] + ); + assert_eq!(indexers, response); } #[tokio::test] @@ -714,16 +681,11 @@ mod tests { "errorMessage": "test failure", "severity": "error" }]); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json.clone()), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json.clone()) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; let async_test_server = server .mock( "POST", @@ -735,29 +697,30 @@ mod tests { .with_body(response_json.to_string()) .create_async() .await; - app_arc + app .lock() .await .data .sonarr_data .indexers .set_items(vec![indexer()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Value(value) = network + let SonarrSerdeable::Value(value) = network .handle_sonarr_event(SonarrEvent::TestIndexer(1)) .await .unwrap() - { - async_details_server.assert_async().await; - async_test_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.indexer_test_errors, - Some("\"test failure\"".to_owned()) - ); - assert_eq!(value, response_json) - } + else { + panic!("Expected Value") + }; + async_details_server.assert_async().await; + async_test_server.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.indexer_test_errors, + Some("\"test failure\"".to_owned()) + ); + assert_eq!(value, response_json); } #[tokio::test] @@ -784,16 +747,11 @@ mod tests { "tags": [1], "id": 1 }); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json.clone()), - None, - SonarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(indexer_details_json.clone()) + .path("/1") + .build_for(SonarrEvent::GetIndexers) + .await; let async_test_server = server .mock( "POST", @@ -805,29 +763,30 @@ mod tests { .with_body("{}") .create_async() .await; - app_arc + app .lock() .await .data .sonarr_data .indexers .set_items(vec![indexer()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Value(value) = network + let SonarrSerdeable::Value(value) = network .handle_sonarr_event(SonarrEvent::TestIndexer(1)) .await .unwrap() - { - async_details_server.assert_async().await; - async_test_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.indexer_test_errors, - Some(String::new()) - ); - assert_eq!(value, json!({})); - } + else { + panic!("Expected Value") + }; + async_details_server.assert_async().await; + async_test_server.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.indexer_test_errors, + Some(String::new()) + ); + assert_eq!(value, json!({})); } #[tokio::test] @@ -879,52 +838,50 @@ mod tests { ] }]); let response: Vec = serde_json::from_value(response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - None, - Some(response_json), - Some(400), - SonarrEvent::TestAllIndexers, - None, - None, - ) - .await; - app_arc + let (async_server, app, _server) = MockServarrApi::post() + .returns(response_json) + .status(400) + .build_for(SonarrEvent::TestAllIndexers) + .await; + app .lock() .await .data .sonarr_data .indexers .set_items(indexers); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::IndexerTestResults(results) = network + let SonarrSerdeable::IndexerTestResults(results) = network .handle_sonarr_event(SonarrEvent::TestAllIndexers) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected IndexerTestResults") + }; + async_server.assert_async().await; + assert!( + app .lock() .await .data .sonarr_data .indexer_test_all_results - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .indexer_test_all_results - .as_ref() - .unwrap() - .items, - indexer_test_results_modal_items - ); - assert_eq!(results, response); - } + .is_some() + ); + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .indexer_test_all_results + .as_ref() + .unwrap() + .items, + indexer_test_results_modal_items + ); + assert_eq!(results, response); } } diff --git a/src/network/sonarr_network/library/episodes/sonarr_episodes_network_tests.rs b/src/network/sonarr_network/library/episodes/sonarr_episodes_network_tests.rs index 83a5d2a..4de541a 100644 --- a/src/network/sonarr_network/library/episodes/sonarr_episodes_network_tests.rs +++ b/src/network/sonarr_network/library/episodes/sonarr_episodes_network_tests.rs @@ -7,43 +7,37 @@ mod tests { SonarrHistoryWrapper, SonarrSerdeable, }; use crate::models::stateful_table::SortOption; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::sonarr_network::SonarrEvent; use crate::network::sonarr_network::library::episodes::get_episode_status; use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ - episode, episode_file, history_item, release, EPISODE_JSON, + EPISODE_JSON, episode, episode_file, history_item, torrent_release, }; - use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, NetworkResource, RequestMethod}; use indoc::formatdoc; use mockito::Matcher; use pretty_assertions::{assert_eq, assert_str_eq}; - use reqwest::Client; use rstest::rstest; - use serde_json::{json, Number}; + use serde_json::{Number, json}; use std::slice; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_delete_sonarr_episode_file_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteEpisodeFile(1), - Some("/1"), - None, - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::delete() + .path("/1") + .build_for(SonarrEvent::DeleteEpisodeFile(1)) + .await; app_arc.lock().await.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default()); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(1)) + .await + .is_ok() + ); async_server.assert_async().await; } @@ -76,16 +70,11 @@ mod tests { }; let expected_episodes = vec![episode_1.clone(), episode_2.clone(), episode_3.clone()]; let mut expected_sorted_episodes = vec![episode_1.clone(), episode_3.clone()]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([episode_1, episode_2, episode_3])), - None, - SonarrEvent::GetEpisodes(1), - None, - Some("seriesId=1"), - ) - .await; + let (mock, app, _server) = MockServarrApi::get() + .query("seriesId=1") + .returns(json!([episode_1, episode_2, episode_3])) + .build_for(SonarrEvent::GetEpisodes(1)) + .await; let mut season_details_modal = SeasonDetailsModal::default(); season_details_modal.episodes.sort_asc = true; if use_custom_sorting { @@ -99,8 +88,8 @@ mod tests { .episodes .sorting(vec![title_sort_option]); } - app_arc.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); - app_arc + app.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); + app .lock() .await .data @@ -110,7 +99,7 @@ mod tests { id: 1, ..Series::default() }]); - app_arc + app .lock() .await .data @@ -120,42 +109,44 @@ mod tests { season_number: 1, ..Season::default() }]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Episodes(episodes) = network + let result = network .handle_sonarr_event(SonarrEvent::GetEpisodes(1)) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .items, - expected_sorted_episodes - ); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .sort_asc - ); - assert_eq!(episodes, expected_episodes); - } + .await; + + mock.assert_async().await; + + let SonarrSerdeable::Episodes(episodes) = result.unwrap() else { + panic!("Expected Episodes variant") + }; + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episodes + .items, + expected_sorted_episodes + ); + assert!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episodes + .sort_asc + ); + assert_eq!(episodes, expected_episodes); } #[tokio::test] @@ -184,20 +175,15 @@ mod tests { ..episode() }; let expected_episodes = vec![episode_1.clone(), episode_2.clone(), episode_3.clone()]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([episode_1, episode_2, episode_3])), - None, - SonarrEvent::GetEpisodes(1), - None, - Some("seriesId=1"), - ) - .await; + let (mock, app, _server) = MockServarrApi::get() + .query("seriesId=1") + .returns(json!([episode_1, episode_2, episode_3])) + .build_for(SonarrEvent::GetEpisodes(1)) + .await; let mut season_details_modal = SeasonDetailsModal::default(); season_details_modal.episodes.sort_asc = true; - app_arc.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); - app_arc + app.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); + app .lock() .await .data @@ -207,56 +193,53 @@ mod tests { id: 1, ..Series::default() }]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Episodes(episodes) = network + let result = network .handle_sonarr_event(SonarrEvent::GetEpisodes(1)) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .items, - expected_episodes - ); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .sort_asc - ); - assert_eq!(episodes, expected_episodes); - } + .await; + + mock.assert_async().await; + + let SonarrSerdeable::Episodes(episodes) = result.unwrap() else { + panic!("Expected Episodes variant") + }; + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episodes + .items, + expected_episodes + ); + assert!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episodes + .sort_asc + ); + assert_eq!(episodes, expected_episodes); } #[tokio::test] async fn test_handle_get_episodes_event_empty_season_details_modal() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([episode()])), - None, - SonarrEvent::GetEpisodes(1), - None, - Some("seriesId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(json!([episode()])) + .query("seriesId=1") + .build_for(SonarrEvent::GetEpisodes(1)) + .await; app_arc .lock() .await @@ -268,29 +251,30 @@ mod tests { ..Series::default() }]); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Episodes(episodes) = network + let SonarrSerdeable::Episodes(episodes) = network .handle_sonarr_event(SonarrEvent::GetEpisodes(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .items, - vec![episode()] - ); - assert_eq!(episodes, vec![episode()]); - } + else { + panic!("Expected Episodes") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episodes + .items, + vec![episode()] + ); + assert_eq!(episodes, vec![episode()]); } #[tokio::test] @@ -336,16 +320,11 @@ mod tests { ..episode() }; let mut expected_episodes = vec![episode_2.clone(), episode_1.clone()]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(episodes_json), - None, - SonarrEvent::GetEpisodes(1), - None, - Some("seriesId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(episodes_json) + .query("seriesId=1") + .build_for(SonarrEvent::GetEpisodes(1)) + .await; app_arc .lock() .await @@ -373,15 +352,18 @@ mod tests { }]); app_arc.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Episodes(episodes) = network + let SonarrSerdeable::Episodes(episodes) = network .handle_sonarr_event(SonarrEvent::GetEpisodes(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected Episodes") + }; + async_server.assert_async().await; + assert!( + app_arc .lock() .await .data @@ -390,35 +372,30 @@ mod tests { .as_ref() .unwrap() .episodes - .is_empty()); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .sort_asc - ); - assert_eq!(episodes, expected_episodes); - } + .is_empty() + ); + assert!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episodes + .sort_asc + ); + assert_eq!(episodes, expected_episodes); } #[tokio::test] async fn test_handle_get_episode_files_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([episode_file()])), - None, - SonarrEvent::GetEpisodeFiles(1), - None, - Some("seriesId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(json!([episode_file()])) + .query("seriesId=1") + .build_for(SonarrEvent::GetEpisodeFiles(1)) + .await; app_arc.lock().await.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default()); app_arc @@ -432,43 +409,39 @@ mod tests { ..Series::default() }]); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::EpisodeFiles(episode_files) = network + let SonarrSerdeable::EpisodeFiles(episode_files) = network .handle_sonarr_event(SonarrEvent::GetEpisodeFiles(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_files - .items, - vec![episode_file()] - ); - assert_eq!(episode_files, vec![episode_file()]); - } + else { + panic!("Expected EpisodeFiles") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_files + .items, + vec![episode_file()] + ); + assert_eq!(episode_files, vec![episode_file()]); } #[tokio::test] async fn test_handle_get_episode_files_event_empty_season_details_modal() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([episode_file()])), - None, - SonarrEvent::GetEpisodeFiles(1), - None, - Some("seriesId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(json!([episode_file()])) + .query("seriesId=1") + .build_for(SonarrEvent::GetEpisodeFiles(1)) + .await; app_arc .lock() .await @@ -480,36 +453,39 @@ mod tests { ..Series::default() }]); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::EpisodeFiles(episode_files) = network + let SonarrSerdeable::EpisodeFiles(episode_files) = network .handle_sonarr_event(SonarrEvent::GetEpisodeFiles(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected EpisodeFiles") + }; + async_server.assert_async().await; + assert!( + app_arc .lock() .await .data .sonarr_data .season_details_modal - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_files - .items, - vec![episode_file()] - ); - assert_eq!(episode_files, vec![episode_file()]); - } + .is_some() + ); + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_files + .items, + vec![episode_file()] + ); + assert_eq!(episode_files, vec![episode_file()]); } #[tokio::test] @@ -555,16 +531,11 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetEpisodeHistory(1), - None, - Some("episodeId=1&pageSize=1000&sortDirection=descending&sortKey=date"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(history_json) + .query("episodeId=1&pageSize=1000&sortDirection=descending&sortKey=date") + .build_for(SonarrEvent::GetEpisodeHistory(1)) + .await; app_arc.lock().await.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default()); app_arc @@ -600,47 +571,48 @@ mod tests { .episode_history .sort_asc = true; app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::SonarrHistoryWrapper(history) = network + let SonarrSerdeable::SonarrHistoryWrapper(history) = network .handle_sonarr_event(SonarrEvent::GetEpisodeHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_history - .items, - expected_history_items - ); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_history - .sort_asc - ); - assert_eq!(history, response); - } + else { + panic!("Expected SonarrHistoryWrapper") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_history + .items, + expected_history_items + ); + assert!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_history + .sort_asc + ); + assert_eq!(history, response); } #[tokio::test] @@ -686,16 +658,11 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetEpisodeHistory(1), - None, - Some("episodeId=1&pageSize=1000&sortDirection=descending&sortKey=date"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(history_json) + .query("episodeId=1&pageSize=1000&sortDirection=descending&sortKey=date") + .build_for(SonarrEvent::GetEpisodeHistory(1)) + .await; app_arc.lock().await.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default()); app_arc @@ -709,47 +676,48 @@ mod tests { .episodes .set_items(vec![episode()]); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::SonarrHistoryWrapper(history) = network + let SonarrSerdeable::SonarrHistoryWrapper(history) = network .handle_sonarr_event(SonarrEvent::GetEpisodeHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_history - .items, - expected_history_items - ); - assert!( - !app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_history - .sort_asc - ); - assert_eq!(history, response); - } + else { + panic!("Expected SonarrHistoryWrapper") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_history + .items, + expected_history_items + ); + assert!( + !app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_history + .sort_asc + ); + assert_eq!(history, response); } #[tokio::test] @@ -795,73 +763,64 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetEpisodeHistory(1), - None, - Some("episodeId=1&pageSize=1000&sortDirection=descending&sortKey=date"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(history_json) + .query("episodeId=1&pageSize=1000&sortDirection=descending&sortKey=date") + .build_for(SonarrEvent::GetEpisodeHistory(1)) + .await; app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::SonarrHistoryWrapper(history) = network + let SonarrSerdeable::SonarrHistoryWrapper(history) = network .handle_sonarr_event(SonarrEvent::GetEpisodeHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_history - .items, - expected_history_items - ); - assert!( - !app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_history - .sort_asc - ); - assert_eq!(history, response); - } + else { + panic!("Expected SonarrHistoryWrapper") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_history + .items, + expected_history_items + ); + assert!( + !app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_history + .sort_asc + ); + assert_eq!(history, response); } #[tokio::test] async fn test_handle_get_episode_details_event() { let response: Episode = serde_json::from_str(EPISODE_JSON).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(EPISODE_JSON).unwrap()), - None, - SonarrEvent::GetEpisodeDetails(1), - Some("/1"), - None, - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(serde_json::from_str(EPISODE_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetEpisodeDetails(1)) + .await; let mut episode_details_modal = EpisodeDetailsModal::default(); episode_details_modal.episode_details_tabs.next(); let mut season_details_modal = SeasonDetailsModal::default(); @@ -873,15 +832,18 @@ mod tests { .await .push_navigation_stack(ActiveSonarrBlock::EpisodeDetails.into()); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Episode(episode) = network + let SonarrSerdeable::Episode(episode) = network .handle_sonarr_event(SonarrEvent::GetEpisodeDetails(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected Episode") + }; + async_server.assert_async().await; + assert!( + app_arc .lock() .await .data @@ -890,27 +852,12 @@ mod tests { .as_ref() .unwrap() .episode_details_modal - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_details_tabs - .get_active_route(), - ActiveSonarrBlock::EpisodeHistory.into() - ); - assert_eq!(episode, response); - - let app = app_arc.lock().await; - let episode_details_modal = app + .is_some() + ); + assert_eq!( + app_arc + .lock() + .await .data .sonarr_data .season_details_modal @@ -918,67 +865,77 @@ mod tests { .unwrap() .episode_details_modal .as_ref() - .unwrap(); - assert_str_eq!( - episode_details_modal.episode_details.get_text(), - formatdoc!( - "Title: Something cool - Season: 1 - Episode Number: 1 - Air Date: 2024-02-10 07:28:45 UTC - Status: Downloaded - Description: Okay so this one time at band camp..." - ) - ); - assert_str_eq!( - episode_details_modal.file_details, - formatdoc!( - "Relative Path: /season 1/episode 1.mkv - Absolute Path: /nfs/tv/series/season 1/episode 1.mkv - Size: 3.30 GB - Language: English - Date Added: 2024-02-10 07:28:45 UTC" - ) - ); - assert_str_eq!( - episode_details_modal.audio_details, - formatdoc!( - "Bitrate: 0 - Channels: 7.1 - Codec: AAC - Languages: eng - Stream Count: 1" - ) - ); - assert_str_eq!( - episode_details_modal.video_details, - formatdoc!( - "Bit Depth: 10 - Bitrate: 0 - Codec: x265 - FPS: 23.976 - Resolution: 1920x1080 - Scan Type: Progressive - Runtime: 23:51 - Subtitles: English" - ) - ); - } + .unwrap() + .episode_details_tabs + .get_active_route(), + ActiveSonarrBlock::EpisodeHistory.into() + ); + assert_eq!(episode, response); + + let app = app_arc.lock().await; + let episode_details_modal = app + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap(); + assert_str_eq!( + episode_details_modal.episode_details.get_text(), + formatdoc!( + "Title: Something cool + Season: 1 + Episode Number: 1 + Air Date: 2024-02-10 07:28:45 UTC + Status: Downloaded + Description: Okay so this one time at band camp..." + ) + ); + assert_str_eq!( + episode_details_modal.file_details, + formatdoc!( + "Relative Path: /season 1/episode 1.mkv + Absolute Path: /nfs/tv/series/season 1/episode 1.mkv + Size: 3.30 GB + Language: English + Date Added: 2024-02-10 07:28:45 UTC" + ) + ); + assert_str_eq!( + episode_details_modal.audio_details, + formatdoc!( + "Bitrate: 0 + Channels: 7.1 + Codec: AAC + Languages: eng + Stream Count: 1" + ) + ); + assert_str_eq!( + episode_details_modal.video_details, + formatdoc!( + "Bit Depth: 10 + Bitrate: 0 + Codec: x265 + FPS: 23.976 + Resolution: 1920x1080 + Scan Type: Progressive + Runtime: 23:51 + Subtitles: English" + ) + ); } #[tokio::test] async fn test_handle_get_episode_details_event_empty_episode_details_modal() { let response: Episode = serde_json::from_str(EPISODE_JSON).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(EPISODE_JSON).unwrap()), - None, - SonarrEvent::GetEpisodeDetails(1), - Some("/1"), - None, - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(serde_json::from_str(EPISODE_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetEpisodeDetails(1)) + .await; let mut season_details_modal = SeasonDetailsModal::default(); season_details_modal.episodes.set_items(vec![episode()]); app_arc.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); @@ -987,15 +944,18 @@ mod tests { .await .push_navigation_stack(ActiveSonarrBlock::EpisodeDetails.into()); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Episode(episode) = network + let SonarrSerdeable::Episode(episode) = network .handle_sonarr_event(SonarrEvent::GetEpisodeDetails(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected Episode") + }; + async_server.assert_async().await; + assert!( + app_arc .lock() .await .data @@ -1004,109 +964,100 @@ mod tests { .as_ref() .unwrap() .episode_details_modal - .is_some()); - assert_eq!(episode, response); + .is_some() + ); + assert_eq!(episode, response); - let app = app_arc.lock().await; - let episode_details_modal = app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap(); - assert_str_eq!( - episode_details_modal.episode_details.get_text(), - formatdoc!( - "Title: Something cool - Season: 1 - Episode Number: 1 - Air Date: 2024-02-10 07:28:45 UTC - Status: Downloaded - Description: Okay so this one time at band camp..." - ) - ); - assert_str_eq!( - episode_details_modal.file_details, - formatdoc!( - "Relative Path: /season 1/episode 1.mkv - Absolute Path: /nfs/tv/series/season 1/episode 1.mkv - Size: 3.30 GB - Language: English - Date Added: 2024-02-10 07:28:45 UTC" - ) - ); - assert_str_eq!( - episode_details_modal.audio_details, - formatdoc!( - "Bitrate: 0 - Channels: 7.1 - Codec: AAC - Languages: eng - Stream Count: 1" - ) - ); - assert_str_eq!( - episode_details_modal.video_details, - formatdoc!( - "Bit Depth: 10 - Bitrate: 0 - Codec: x265 - FPS: 23.976 - Resolution: 1920x1080 - Scan Type: Progressive - Runtime: 23:51 - Subtitles: English" - ) - ); - } + let app = app_arc.lock().await; + let episode_details_modal = app + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap(); + assert_str_eq!( + episode_details_modal.episode_details.get_text(), + formatdoc!( + "Title: Something cool + Season: 1 + Episode Number: 1 + Air Date: 2024-02-10 07:28:45 UTC + Status: Downloaded + Description: Okay so this one time at band camp..." + ) + ); + assert_str_eq!( + episode_details_modal.file_details, + formatdoc!( + "Relative Path: /season 1/episode 1.mkv + Absolute Path: /nfs/tv/series/season 1/episode 1.mkv + Size: 3.30 GB + Language: English + Date Added: 2024-02-10 07:28:45 UTC" + ) + ); + assert_str_eq!( + episode_details_modal.audio_details, + formatdoc!( + "Bitrate: 0 + Channels: 7.1 + Codec: AAC + Languages: eng + Stream Count: 1" + ) + ); + assert_str_eq!( + episode_details_modal.video_details, + formatdoc!( + "Bit Depth: 10 + Bitrate: 0 + Codec: x265 + FPS: 23.976 + Resolution: 1920x1080 + Scan Type: Progressive + Runtime: 23:51 + Subtitles: English" + ) + ); } #[tokio::test] async fn test_handle_get_episode_details_event_season_details_modal_not_required_in_cli_mode() { let response: Episode = serde_json::from_str(EPISODE_JSON).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(EPISODE_JSON).unwrap()), - None, - SonarrEvent::GetEpisodeDetails(1), - Some("/1"), - None, - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(serde_json::from_str(EPISODE_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetEpisodeDetails(1)) + .await; app_arc.lock().await.cli_mode = true; app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Episode(episode) = network + let SonarrSerdeable::Episode(episode) = network .handle_sonarr_event(SonarrEvent::GetEpisodeDetails(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(episode, response); - } + else { + panic!("Expected Episode") + }; + async_server.assert_async().await; + assert_eq!(episode, response); } #[tokio::test] #[should_panic(expected = "Season details modal is empty")] - async fn test_handle_get_episode_details_event_requires_season_details_modal_to_be_some_when_in_tui_mode( - ) { - let (_async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(EPISODE_JSON).unwrap()), - None, - SonarrEvent::GetEpisodeDetails(1), - Some("/1"), - None, - ) - .await; + async fn test_handle_get_episode_details_event_requires_season_details_modal_to_be_some_when_in_tui_mode() + { + let (_async_server, app_arc, _server) = MockServarrApi::get() + .returns(serde_json::from_str(EPISODE_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetEpisodeDetails(1)) + .await; app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); network .handle_sonarr_event(SonarrEvent::GetEpisodeDetails(1)) @@ -1131,16 +1082,11 @@ mod tests { "languages": [ { "id": 1, "name": "English" } ], "quality": { "quality": { "name": "Bluray-1080p" }} }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(release_json), - None, - SonarrEvent::GetEpisodeReleases(1), - None, - Some("episodeId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(release_json) + .query("episodeId=1") + .build_for(SonarrEvent::GetEpisodeReleases(1)) + .await; let mut season_details_modal = SeasonDetailsModal::default(); season_details_modal.episodes.set_items(vec![episode()]); app_arc.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); @@ -1154,32 +1100,33 @@ mod tests { .unwrap() .episode_details_modal = Some(EpisodeDetailsModal::default()); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Releases(releases_vec) = network + let SonarrSerdeable::Releases(releases_vec) = network .handle_sonarr_event(SonarrEvent::GetEpisodeReleases(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_releases - .items, - vec![release()] - ); - assert_eq!(releases_vec, vec![release()]); - } + else { + panic!("Expected Releases") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_releases + .items, + vec![torrent_release()] + ); + assert_eq!(releases_vec, vec![torrent_release()]); } #[tokio::test] @@ -1199,46 +1146,42 @@ mod tests { "languages": [ { "id": 1, "name": "English" } ], "quality": { "quality": { "name": "Bluray-1080p" }} }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(release_json), - None, - SonarrEvent::GetEpisodeReleases(1), - None, - Some("episodeId=1"), - ) - .await; + let (async_server, app_arc, _server) = MockServarrApi::get() + .returns(release_json) + .query("episodeId=1") + .build_for(SonarrEvent::GetEpisodeReleases(1)) + .await; let mut season_details_modal = SeasonDetailsModal::default(); season_details_modal.episodes.set_items(vec![episode()]); app_arc.lock().await.data.sonarr_data.season_details_modal = Some(season_details_modal); app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - if let SonarrSerdeable::Releases(releases_vec) = network + let SonarrSerdeable::Releases(releases_vec) = network .handle_sonarr_event(SonarrEvent::GetEpisodeReleases(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_releases - .items, - vec![release()] - ); - assert_eq!(releases_vec, vec![release()]); - } + else { + panic!("Expected Releases") + }; + async_server.assert_async().await; + assert_eq!( + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .episode_details_modal + .as_ref() + .unwrap() + .episode_releases + .items, + vec![torrent_release()] + ); + assert_eq!(releases_vec, vec![torrent_release()]); } #[tokio::test] @@ -1249,16 +1192,11 @@ mod tests { }; let body = Episode { id: 2, ..episode() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!(body)), - None, - SonarrEvent::GetEpisodeDetails(2), - Some("/2"), - None, - ) - .await; + let (async_details_server, app_arc, mut server) = MockServarrApi::get() + .returns(json!(body)) + .path("/2") + .build_for(SonarrEvent::GetEpisodeDetails(2)) + .await; let async_toggle_server = server .mock( "PUT", @@ -1274,12 +1212,14 @@ mod tests { .create_async() .await; app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); - assert!(network - .handle_sonarr_event(SonarrEvent::ToggleEpisodeMonitoring(2)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::ToggleEpisodeMonitoring(2)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_toggle_server.assert_async().await; @@ -1287,28 +1227,26 @@ mod tests { #[tokio::test] async fn test_handle_trigger_automatic_episode_search_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ - "name": "EpisodeSearch", - "episodeIds": [ 1 ] - })), - Some(json!({})), - None, - SonarrEvent::TriggerAutomaticEpisodeSearch(1), - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let body = json!({ + "name": "EpisodeSearch", + "episodeIds": [ 1 ] + }); + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(body) + .returns(json!({})) + .build_for(SonarrEvent::TriggerAutomaticEpisodeSearch(1)) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::TriggerAutomaticEpisodeSearch(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::TriggerAutomaticEpisodeSearch(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[test] diff --git a/src/network/sonarr_network/library/seasons/mod.rs b/src/network/sonarr_network/library/seasons/mod.rs index 5f0695f..7ed2912 100644 --- a/src/network/sonarr_network/library/seasons/mod.rs +++ b/src/network/sonarr_network/library/seasons/mod.rs @@ -4,7 +4,7 @@ use crate::network::sonarr_network::SonarrEvent; use crate::network::{Network, RequestMethod}; use anyhow::Result; use log::{debug, info, warn}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; #[cfg(test)] #[path = "sonarr_seasons_network_tests.rs"] diff --git a/src/network/sonarr_network/library/seasons/sonarr_seasons_network_tests.rs b/src/network/sonarr_network/library/seasons/sonarr_seasons_network_tests.rs index 23d8de6..80427cc 100644 --- a/src/network/sonarr_network/library/seasons/sonarr_seasons_network_tests.rs +++ b/src/network/sonarr_network/library/seasons/sonarr_seasons_network_tests.rs @@ -2,17 +2,15 @@ mod tests { use crate::models::servarr_data::sonarr::modals::SeasonDetailsModal; use crate::models::sonarr_models::{SonarrHistoryItem, SonarrRelease, SonarrSerdeable}; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ - history_item, release, season, series, SERIES_JSON, - }; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, NetworkResource, RequestMethod}; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ + SERIES_JSON, history_item, season, series, torrent_release, + }; use mockito::Matcher; use pretty_assertions::assert_eq; - use reqwest::Client; - use serde_json::{json, Value}; - use tokio_util::sync::CancellationToken; + use serde_json::{Value, json}; #[tokio::test] async fn test_handle_toggle_season_monitoring_event() { @@ -28,16 +26,11 @@ mod tests { .get_mut("monitored") .unwrap() = json!(false); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; let async_toggle_server = server .mock( "PUT", @@ -53,17 +46,19 @@ mod tests { .create_async() .await; { - let mut app = app_arc.lock().await; - app.data.sonarr_data.series.set_items(vec![series()]); - app.data.sonarr_data.seasons.set_items(vec![season()]); + let mut app_lock = app.lock().await; + app_lock.data.sonarr_data.series.set_items(vec![series()]); + app_lock.data.sonarr_data.seasons.set_items(vec![season()]); } - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::ToggleSeasonMonitoring((1, 1))) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::ToggleSeasonMonitoring((1, 1))) + .await + .is_ok() + ); async_details_server.assert_async().await; async_toggle_server.assert_async().await; @@ -106,68 +101,63 @@ mod tests { ]); let expected_filtered_sonarr_release = SonarrRelease { full_season: true, - ..release() + ..torrent_release() }; let expected_raw_sonarr_releases = vec![ SonarrRelease { full_season: true, - ..release() + ..torrent_release() }, SonarrRelease { guid: "4567".to_owned(), - ..release() + ..torrent_release() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(release_json), - None, - SonarrEvent::GetSeasonReleases((1, 1)), - None, - Some("seriesId=1&seasonNumber=1"), - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(release_json) + .query("seriesId=1&seasonNumber=1") + .build_for(SonarrEvent::GetSeasonReleases((1, 1))) + .await; + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc + app .lock() .await .data .sonarr_data .seasons .set_items(vec![season()]); - app_arc.lock().await.data.sonarr_data.season_details_modal = - Some(SeasonDetailsModal::default()); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Releases(releases_vec) = network + let SonarrSerdeable::Releases(releases_vec) = network .handle_sonarr_event(SonarrEvent::GetSeasonReleases((1, 1))) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_releases - .items, - vec![expected_filtered_sonarr_release] - ); - assert_eq!(releases_vec, expected_raw_sonarr_releases); - } + else { + panic!("Expected Releases") + }; + mock.assert_async().await; + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_releases + .items, + vec![expected_filtered_sonarr_release] + ); + assert_eq!(releases_vec, expected_raw_sonarr_releases); } #[tokio::test] @@ -207,43 +197,40 @@ mod tests { ]); let expected_sonarr_release = SonarrRelease { full_season: true, - ..release() + ..torrent_release() }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(release_json), - None, - SonarrEvent::GetSeasonReleases((1, 1)), - None, - Some("seriesId=1&seasonNumber=1"), - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(release_json) + .query("seriesId=1&seasonNumber=1") + .build_for(SonarrEvent::GetSeasonReleases((1, 1))) + .await; + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc + app .lock() .await .data .sonarr_data .seasons .set_items(vec![season()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::GetSeasonReleases((1, 1))) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::GetSeasonReleases((1, 1))) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; assert_eq!( - app_arc + app .lock() .await .data @@ -300,33 +287,27 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetSeasonHistory((1, 1)), - None, - Some("seriesId=1&seasonNumber=1"), - ) - .await; - app_arc.lock().await.data.sonarr_data.season_details_modal = - Some(SeasonDetailsModal::default()); - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("seriesId=1&seasonNumber=1") + .build_for(SonarrEvent::GetSeasonHistory((1, 1))) + .await; + app.lock().await.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default()); + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc + app .lock() .await .data .sonarr_data .seasons .set_items(vec![season()]); - app_arc + app .lock() .await .data @@ -336,42 +317,43 @@ mod tests { .unwrap() .season_history .sort_asc = true; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryItems(history) = network + let SonarrSerdeable::SonarrHistoryItems(history) = network .handle_sonarr_event(SonarrEvent::GetSeasonHistory((1, 1))) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .items, - expected_history_items - ); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .sort_asc - ); - assert_eq!(history, response); - } + else { + panic!("Expected SonarrHistoryItems") + }; + mock.assert_async().await; + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .items, + expected_history_items + ); + assert!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .sort_asc + ); + assert_eq!(history, response); } #[tokio::test] @@ -417,99 +399,94 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetSeasonHistory((1, 1)), - None, - Some("seriesId=1&seasonNumber=1"), - ) - .await; - app_arc + let (mock, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("seriesId=1&seasonNumber=1") + .build_for(SonarrEvent::GetSeasonHistory((1, 1))) + .await; + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc + app .lock() .await .data .sonarr_data .seasons .set_items(vec![season()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryItems(history) = network + let SonarrSerdeable::SonarrHistoryItems(history) = network .handle_sonarr_event(SonarrEvent::GetSeasonHistory((1, 1))) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected SonarrHistoryItems") + }; + mock.assert_async().await; + assert!( + app .lock() .await .data .sonarr_data .season_details_modal - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .items, - expected_history_items - ); - assert!( - !app_arc - .lock() - .await - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_history - .sort_asc - ); - assert_eq!(history, response); - } + .is_some() + ); + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .items, + expected_history_items + ); + assert!( + !app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .unwrap() + .season_history + .sort_asc + ); + assert_eq!(history, response); } #[tokio::test] async fn test_handle_trigger_automatic_season_search_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "SeasonSearch", "seriesId": 1, "seasonNumber": 1 - })), - Some(json!({})), - None, - SonarrEvent::TriggerAutomaticSeasonSearch((1, 1)), - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::TriggerAutomaticSeasonSearch((1, 1))) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::TriggerAutomaticSeasonSearch((1, 1))) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::TriggerAutomaticSeasonSearch((1, 1))) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } } diff --git a/src/network/sonarr_network/library/series/mod.rs b/src/network/sonarr_network/library/series/mod.rs index a9bbf7f..100a162 100644 --- a/src/network/sonarr_network/library/series/mod.rs +++ b/src/network/sonarr_network/library/series/mod.rs @@ -1,15 +1,15 @@ +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; use crate::models::sonarr_models::{ AddSeriesBody, AddSeriesSearchResult, DeleteSeriesParams, EditSeriesParams, Series, SonarrCommandBody, SonarrHistoryItem, }; use crate::models::stateful_table::StatefulTable; -use crate::models::Route; use crate::network::sonarr_network::SonarrEvent; use crate::network::{Network, RequestMethod}; use anyhow::Result; use log::{debug, info, warn}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use urlencoding::encode; #[cfg(test)] @@ -56,7 +56,9 @@ impl Network<'_, '_> { add_list_exclusion, } = delete_series_params; - info!("Deleting Sonarr series with ID: {id} with deleteFiles={delete_series_files} and addImportExclusion={add_list_exclusion}"); + info!( + "Deleting Sonarr series with ID: {id} with deleteFiles={delete_series_files} and addImportExclusion={add_list_exclusion}" + ); let request_props = self .request_props_from( @@ -305,29 +307,17 @@ impl Network<'_, '_> { self .handle_request::<(), Vec>(request_props, |mut history_vec, mut app| { - if app.data.sonarr_data.series_history.is_none() { - app.data.sonarr_data.series_history = Some(StatefulTable::default()); - } - - if !matches!( + let is_sorting = matches!( app.get_current_route(), Route::Sonarr(ActiveSonarrBlock::SeriesHistorySortPrompt, _) - ) { + ); + + let series_history = app.data.sonarr_data.series_history.get_or_insert_default(); + + if !is_sorting { history_vec.sort_by(|a, b| a.id.cmp(&b.id)); - app - .data - .sonarr_data - .series_history - .as_mut() - .unwrap() - .set_items(history_vec); - app - .data - .sonarr_data - .series_history - .as_mut() - .unwrap() - .apply_sorting_toggle(false); + series_history.set_items(history_vec); + series_history.apply_sorting_toggle(false); } }) .await diff --git a/src/network/sonarr_network/library/series/sonarr_series_network_tests.rs b/src/network/sonarr_network/library/series/sonarr_series_network_tests.rs index de74cfe..fabd110 100644 --- a/src/network/sonarr_network/library/series/sonarr_series_network_tests.rs +++ b/src/network/sonarr_network/library/series/sonarr_series_network_tests.rs @@ -6,19 +6,17 @@ mod tests { SonarrHistoryItem, SonarrSerdeable, }; use crate::models::stateful_table::{SortOption, StatefulTable}; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ - add_series_search_result, history_item, season, series, SERIES_JSON, - }; + use crate::network::NetworkResource; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, NetworkResource, RequestMethod}; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::{ + SERIES_JSON, add_series_search_result, history_item, season, series, + }; use bimap::BiMap; use mockito::Matcher; use pretty_assertions::assert_eq; - use reqwest::Client; use rstest::rstest; - use serde_json::{json, Value}; - use tokio_util::sync::CancellationToken; + use serde_json::{Value, json}; #[tokio::test] async fn test_handle_add_sonarr_series_event() { @@ -39,9 +37,8 @@ mod tests { search_for_missing_episodes: true, }, }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "tvdbId": 1234, "title": "Test", "monitored": true, @@ -56,30 +53,28 @@ mod tests { "searchForCutoffUnmetEpisodes": true, "searchForMissingEpisodes": true } - })), - Some(json!({})), - None, - SonarrEvent::AddSeries(expected_add_series_body.clone()), - None, - None, - ) - .await; - app_arc.lock().await.data.sonarr_data.tags_map = + })) + .returns(json!({})) + .build_for(SonarrEvent::AddSeries(expected_add_series_body.clone())) + .await; + app.lock().await.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::AddSeries(expected_add_series_body)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::AddSeries(expected_add_series_body)) + .await + .is_ok() + ); async_server.assert_async().await; } #[tokio::test] - async fn test_handle_add_sonarr_series_event_does_not_overwrite_tags_vec_when_tag_input_string_is_none( - ) { + async fn test_handle_add_sonarr_series_event_does_not_overwrite_tags_vec_when_tag_input_string_is_none() + { let expected_add_series_body = AddSeriesBody { tvdb_id: 1234, title: "Test".to_owned(), @@ -97,9 +92,8 @@ mod tests { search_for_missing_episodes: true, }, }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "tvdbId": 1234, "title": "Test", "monitored": true, @@ -114,21 +108,19 @@ mod tests { "searchForCutoffUnmetEpisodes": true, "searchForMissingEpisodes": true } - })), - Some(json!({})), - None, - SonarrEvent::AddSeries(expected_add_series_body.clone()), - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::AddSeries(expected_add_series_body.clone())) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::AddSeries(expected_add_series_body)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::AddSeries(expected_add_series_body)) + .await + .is_ok() + ); async_server.assert_async().await; } @@ -140,23 +132,20 @@ mod tests { delete_series_files: true, add_list_exclusion: true, }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteSeries(delete_series_params.clone()), - Some("/1"), - Some("deleteFiles=true&addImportExclusion=true"), - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::delete() + .path("/1") + .query("deleteFiles=true&addImportExclusion=true") + .build_for(SonarrEvent::DeleteSeries(delete_series_params.clone())) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteSeries(delete_series_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteSeries(delete_series_params)) + .await + .is_ok() + ); async_server.assert_async().await; } @@ -183,16 +172,11 @@ mod tests { ..EditSeriesParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; let async_edit_server = server .mock( "PUT", @@ -207,23 +191,25 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - app_arc.lock().await.data.sonarr_data.tags_map = + app.lock().await.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; } #[tokio::test] - async fn test_handle_edit_series_event_does_not_overwrite_tag_ids_vec_when_tag_input_string_is_none( - ) { + async fn test_handle_edit_series_event_does_not_overwrite_tag_ids_vec_when_tag_input_string_is_none() + { let mut expected_body: Value = serde_json::from_str(SERIES_JSON).unwrap(); *expected_body.get_mut("monitored").unwrap() = json!(false); *expected_body.get_mut("seasonFolder").unwrap() = json!(false); @@ -244,16 +230,11 @@ mod tests { ..EditSeriesParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; let async_edit_server = server .mock( "PUT", @@ -268,15 +249,17 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - app_arc.lock().await.data.sonarr_data.tags_map = + app.lock().await.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -289,16 +272,11 @@ mod tests { ..EditSeriesParams::default() }; let expected_body: Value = serde_json::from_str(SERIES_JSON).unwrap(); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; let async_edit_server = server .mock( "PUT", @@ -313,13 +291,15 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -330,16 +310,11 @@ mod tests { let mut expected_body: Value = serde_json::from_str(SERIES_JSON).unwrap(); *expected_body.get_mut("tags").unwrap() = json!([]); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; let edit_series_params = EditSeriesParams { series_id: 1, clear_tags: true, @@ -359,13 +334,15 @@ mod tests { .match_body(Matcher::Json(expected_body)) .create_async() .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::EditSeries(edit_series_params)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_edit_server.assert_async().await; @@ -376,16 +353,11 @@ mod tests { let mut expected_body: Value = serde_json::from_str(SERIES_JSON).unwrap(); *expected_body.get_mut("monitored").unwrap() = json!(false); - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; + let (async_details_server, app, mut server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; let async_toggle_server = server .mock( "PUT", @@ -401,17 +373,19 @@ mod tests { .create_async() .await; { - let mut app = app_arc.lock().await; + let mut app = app.lock().await; app.data.sonarr_data.series.set_items(vec![series()]); app.data.sonarr_data.seasons.set_items(vec![season()]); } - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::ToggleSeriesMonitoring(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::ToggleSeriesMonitoring(1)) + .await + .is_ok() + ); async_details_server.assert_async().await; async_toggle_server.assert_async().await; @@ -420,34 +394,30 @@ mod tests { #[tokio::test] async fn test_handle_get_series_details_event() { let expected_series: Series = serde_json::from_str(SERIES_JSON).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(serde_json::from_str(SERIES_JSON).unwrap()), - None, - SonarrEvent::GetSeriesDetails(1), - Some("/1"), - None, - ) - .await; - app_arc + let (async_server, app, _server) = MockServarrApi::get() + .returns(serde_json::from_str(SERIES_JSON).unwrap()) + .path("/1") + .build_for(SonarrEvent::GetSeriesDetails(1)) + .await; + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Series(series) = network + let SonarrSerdeable::Series(series) = network .handle_sonarr_event(SonarrEvent::GetSeriesDetails(1)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(series, expected_series); - } + else { + panic!("Expected Series") + }; + async_server.assert_async().await; + assert_eq!(series, expected_series); } #[rstest] @@ -496,16 +466,11 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetSeriesHistory(1), - None, - Some("seriesId=1"), - ) - .await; + let (async_server, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("seriesId=1") + .build_for(SonarrEvent::GetSeriesHistory(1)) + .await; let mut series_history_table = StatefulTable { sort_asc: true, ..StatefulTable::default() @@ -525,55 +490,50 @@ mod tests { }; series_history_table.sorting(vec![history_sort_option]); } - app_arc + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc.lock().await.data.sonarr_data.series_history = Some(series_history_table); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.data.sonarr_data.series_history = Some(series_history_table); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryItems(history_items) = network + let SonarrSerdeable::SonarrHistoryItems(history_items) = network .handle_sonarr_event(SonarrEvent::GetSeriesHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected SonarrHistoryItems") + }; + async_server.assert_async().await; + assert!(app.lock().await.data.sonarr_data.series_history.is_some()); + assert_eq!( + app .lock() .await .data .sonarr_data .series_history - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .items, - expected_history_items - ); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .sort_asc - ); - assert_eq!(history_items, response); - } + .as_ref() + .unwrap() + .items, + expected_history_items + ); + assert!( + app + .lock() + .await + .data + .sonarr_data + .series_history + .as_ref() + .unwrap() + .sort_asc + ); + assert_eq!(history_items, response); } #[tokio::test] @@ -619,64 +579,54 @@ mod tests { ..history_item() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetSeriesHistory(1), - None, - Some("seriesId=1"), - ) - .await; - app_arc + let (async_server, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("seriesId=1") + .build_for(SonarrEvent::GetSeriesHistory(1)) + .await; + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryItems(history_items) = network + let SonarrSerdeable::SonarrHistoryItems(history_items) = network .handle_sonarr_event(SonarrEvent::GetSeriesHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected SonarrHistoryItems") + }; + async_server.assert_async().await; + assert!(app.lock().await.data.sonarr_data.series_history.is_some()); + assert_eq!( + app .lock() .await .data .sonarr_data .series_history - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .items, - expected_history_items - ); - assert!( - !app_arc - .lock() - .await - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .sort_asc - ); - assert_eq!(history_items, response); - } + .as_ref() + .unwrap() + .items, + expected_history_items + ); + assert!( + !app + .lock() + .await + .data + .sonarr_data + .series_history + .as_ref() + .unwrap() + .sort_asc + ); + assert_eq!(history_items, response); } #[tokio::test] @@ -708,16 +658,11 @@ mod tests { } }]); let response: Vec = serde_json::from_value(history_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(history_json), - None, - SonarrEvent::GetSeriesHistory(1), - None, - Some("seriesId=1"), - ) - .await; + let (async_server, app, _server) = MockServarrApi::get() + .returns(history_json) + .query("seriesId=1") + .build_for(SonarrEvent::GetSeriesHistory(1)) + .await; let cmp_fn = |a: &SonarrHistoryItem, b: &SonarrHistoryItem| { a.source_title .text @@ -733,35 +678,32 @@ mod tests { ..StatefulTable::default() }; series_history_table.sorting(vec![history_sort_option]); - app_arc.lock().await.data.sonarr_data.series_history = Some(series_history_table); - app_arc + app.lock().await.data.sonarr_data.series_history = Some(series_history_table); + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc + app .lock() .await .push_navigation_stack(ActiveSonarrBlock::SeriesHistorySortPrompt.into()); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SonarrHistoryItems(history_items) = network + let SonarrSerdeable::SonarrHistoryItems(history_items) = network .handle_sonarr_event(SonarrEvent::GetSeriesHistory(1)) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .sonarr_data - .series_history - .is_some()); - assert!(app_arc + else { + panic!("Expected SonarrHistoryItems") + }; + async_server.assert_async().await; + assert!(app.lock().await.data.sonarr_data.series_history.is_some()); + assert!( + app .lock() .await .data @@ -769,20 +711,20 @@ mod tests { .series_history .as_ref() .unwrap() - .is_empty()); - assert!( - app_arc - .lock() - .await - .data - .sonarr_data - .series_history - .as_ref() - .unwrap() - .sort_asc - ); - assert_eq!(history_items, response); - } + .is_empty() + ); + assert!( + app + .lock() + .await + .data + .sonarr_data + .series_history + .as_ref() + .unwrap() + .sort_asc + ); + assert_eq!(history_items, response); } #[rstest] @@ -818,17 +760,11 @@ mod tests { ..series() }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([series_1, series_2])), - None, - SonarrEvent::ListSeries, - None, - None, - ) - .await; - app_arc.lock().await.data.sonarr_data.series.sort_asc = true; + let (async_server, app, _server) = MockServarrApi::get() + .returns(json!([series_1, series_2])) + .build_for(SonarrEvent::ListSeries) + .await; + app.lock().await.data.sonarr_data.series.sort_asc = true; if use_custom_sorting { let cmp_fn = |a: &Series, b: &Series| { a.title @@ -841,7 +777,7 @@ mod tests { name: "Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data @@ -849,22 +785,23 @@ mod tests { .series .sorting(vec![title_sort_option]); } - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SeriesVec(series) = network + let SonarrSerdeable::SeriesVec(series) = network .handle_sonarr_event(SonarrEvent::ListSeries) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.series.items, - expected_sorted_series - ); - assert!(app_arc.lock().await.data.sonarr_data.series.sort_asc); - assert_eq!(series, expected_series); - } + else { + panic!("Expected SeriesVec") + }; + async_server.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.series.items, + expected_sorted_series + ); + assert!(app.lock().await.data.sonarr_data.series.sort_asc); + assert_eq!(series, expected_series); } #[tokio::test] @@ -875,21 +812,15 @@ mod tests { *series_1.get_mut("title").unwrap() = json!("z test"); *series_2.get_mut("id").unwrap() = json!(2); *series_2.get_mut("title").unwrap() = json!("A test"); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([series_1, series_2])), - None, - SonarrEvent::ListSeries, - None, - None, - ) - .await; - app_arc + let (async_server, app, _server) = MockServarrApi::get() + .returns(json!([series_1, series_2])) + .build_for(SonarrEvent::ListSeries) + .await; + app .lock() .await .push_navigation_stack(ActiveSonarrBlock::SeriesSortPrompt.into()); - app_arc.lock().await.data.sonarr_data.series.sort_asc = true; + app.lock().await.data.sonarr_data.series.sort_asc = true; let cmp_fn = |a: &Series, b: &Series| { a.title .text @@ -900,31 +831,26 @@ mod tests { name: "Title", cmp_fn: Some(cmp_fn), }; - app_arc + app .lock() .await .data .sonarr_data .series .sorting(vec![title_sort_option]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::ListSeries) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::ListSeries) + .await + .is_ok() + ); async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .sonarr_data - .series - .items - .is_empty()); - assert!(app_arc.lock().await.data.sonarr_data.series.sort_asc); + assert!(app.lock().await.data.sonarr_data.series.items.is_empty()); + assert!(app.lock().await.data.sonarr_data.series.sort_asc); } #[tokio::test] @@ -942,164 +868,152 @@ mod tests { "ratings": { "votes": 406744, "value": 8.4 }, "statistics": { "seasonCount": 3 } }]); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(add_series_search_result_json), - None, - SonarrEvent::SearchNewSeries("test term".into()), - None, - Some("term=test%20term"), - ) - .await; - app_arc.lock().await.data.sonarr_data.add_series_search = Some("test term".into()); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(add_series_search_result_json) + .query("term=test%20term") + .build_for(SonarrEvent::SearchNewSeries("test term".into())) + .await; + app.lock().await.data.sonarr_data.add_series_search = Some("test term".into()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::AddSeriesSearchResults(add_series_search_results) = network + let SonarrSerdeable::AddSeriesSearchResults(add_series_search_results) = network .handle_sonarr_event(SonarrEvent::SearchNewSeries("test term".into())) .await .unwrap() - { - async_server.assert_async().await; - assert!(app_arc + else { + panic!("Expected AddSeriesSearchResults") + }; + async_server.assert_async().await; + assert!( + app .lock() .await .data .sonarr_data .add_searched_series - .is_some()); - assert_eq!( - app_arc - .lock() - .await - .data - .sonarr_data - .add_searched_series - .as_ref() - .unwrap() - .items, - vec![add_series_search_result()] - ); - assert_eq!(add_series_search_results, vec![add_series_search_result()]); - } + .is_some() + ); + assert_eq!( + app + .lock() + .await + .data + .sonarr_data + .add_searched_series + .as_ref() + .unwrap() + .items, + vec![add_series_search_result()] + ); + assert_eq!(add_series_search_results, vec![add_series_search_result()]); } #[tokio::test] async fn test_handle_search_new_series_event_no_results() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([])), - None, - SonarrEvent::SearchNewSeries("test term".into()), - None, - Some("term=test%20term"), - ) - .await; - app_arc.lock().await.data.sonarr_data.add_series_search = Some("test term".into()); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::get() + .returns(json!([])) + .query("term=test%20term") + .build_for(SonarrEvent::SearchNewSeries("test term".into())) + .await; + app.lock().await.data.sonarr_data.add_series_search = Some("test term".into()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::SearchNewSeries("test term".into())) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::SearchNewSeries("test term".into())) + .await + .is_ok() + ); async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .sonarr_data - .add_searched_series - .is_none()); + assert!( + app + .lock() + .await + .data + .sonarr_data + .add_searched_series + .is_none() + ); assert_eq!( - app_arc.lock().await.get_current_route(), + app.lock().await.get_current_route(), ActiveSonarrBlock::AddSeriesEmptySearchResults.into() ); } #[tokio::test] async fn test_handle_trigger_automatic_series_search_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "SeriesSearch", "seriesId": 1 - })), - Some(json!({})), - None, - SonarrEvent::TriggerAutomaticSeriesSearch(1), - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::TriggerAutomaticSeriesSearch(1)) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::TriggerAutomaticSeriesSearch(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::TriggerAutomaticSeriesSearch(1)) + .await + .is_ok() + ); async_server.assert_async().await; } #[tokio::test] async fn test_handle_update_all_series_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "RefreshSeries", - })), - Some(json!({})), - None, - SonarrEvent::UpdateAllSeries, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::UpdateAllSeries) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::UpdateAllSeries) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::UpdateAllSeries) + .await + .is_ok() + ); async_server.assert_async().await; } #[tokio::test] async fn test_handle_update_and_scan_series_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (async_server, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "RefreshSeries", "seriesId": 1, - })), - Some(json!({})), - None, - SonarrEvent::UpdateAndScanSeries(1), - None, - None, - ) - .await; - app_arc + })) + .returns(json!({})) + .build_for(SonarrEvent::UpdateAndScanSeries(1)) + .await; + app .lock() .await .data .sonarr_data .series .set_items(vec![series()]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::UpdateAndScanSeries(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::UpdateAndScanSeries(1)) + .await + .is_ok() + ); async_server.assert_async().await; } diff --git a/src/network/sonarr_network/library/sonarr_library_network_tests.rs b/src/network/sonarr_network/library/sonarr_library_network_tests.rs index 7e036a3..0323dd2 100644 --- a/src/network/sonarr_network/library/sonarr_library_network_tests.rs +++ b/src/network/sonarr_network/library/sonarr_library_network_tests.rs @@ -1,12 +1,9 @@ #[cfg(test)] mod tests { use crate::models::sonarr_models::SonarrReleaseDownloadBody; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, RequestMethod}; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_download_sonarr_release_event_uses_provided_params() { @@ -16,28 +13,25 @@ mod tests { series_id: Some(1), ..SonarrReleaseDownloadBody::default() }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "guid": "1234", "indexerId": 2, "seriesId": 1, - })), - Some(json!({})), - None, - SonarrEvent::DownloadRelease(params.clone()), - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::DownloadRelease(params.clone())) + .await; - assert!(network + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); + + let result = network .handle_sonarr_event(SonarrEvent::DownloadRelease(params)) - .await - .is_ok()); + .await; - async_server.assert_async().await; + mock.assert_async().await; + assert!(result.is_ok()); } } diff --git a/src/network/sonarr_network/mod.rs b/src/network/sonarr_network/mod.rs index f97fce5..b0f314c 100644 --- a/src/network/sonarr_network/mod.rs +++ b/src/network/sonarr_network/mod.rs @@ -1,6 +1,6 @@ use anyhow::Result; use log::info; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use super::{Network, NetworkEvent, NetworkResource}; use crate::{ @@ -19,7 +19,7 @@ mod sonarr_network_tests; #[cfg(test)] #[path = "sonarr_network_test_utils.rs"] -mod sonarr_network_test_utils; +pub mod sonarr_network_test_utils; mod blocklist; mod downloads; diff --git a/src/network/sonarr_network/root_folders/sonarr_root_folders_network_tests.rs b/src/network/sonarr_network/root_folders/sonarr_root_folders_network_tests.rs index b2a79e3..cd77d8e 100644 --- a/src/network/sonarr_network/root_folders/sonarr_root_folders_network_tests.rs +++ b/src/network/sonarr_network/root_folders/sonarr_root_folders_network_tests.rs @@ -2,71 +2,57 @@ mod tests { use crate::models::servarr_models::{AddRootFolderBody, RootFolder}; use crate::models::sonarr_models::SonarrSerdeable; - use crate::network::network_tests::test_utils::mock_servarr_api; - use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::root_folder; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, RequestMethod}; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::root_folder; use pretty_assertions::assert_eq; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_add_sonarr_root_folder_event() { let expected_add_root_folder_body = AddRootFolderBody { path: "/nfs/test".to_owned(), }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "path": "/nfs/test" - })), - Some(json!({})), - None, - SonarrEvent::AddRootFolder(expected_add_root_folder_body.clone()), - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .returns(json!({})) + .build_for(SonarrEvent::AddRootFolder( + expected_add_root_folder_body.clone(), + )) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::AddRootFolder(expected_add_root_folder_body)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::AddRootFolder(expected_add_root_folder_body)) + .await + .is_ok() + ); - async_server.assert_async().await; - assert!(app_arc - .lock() - .await - .data - .sonarr_data - .edit_root_folder - .is_none()); + mock.assert_async().await; + assert!(app.lock().await.data.sonarr_data.edit_root_folder.is_none()); } #[tokio::test] async fn test_handle_delete_sonarr_root_folder_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteRootFolder(1), - Some("/1"), - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(SonarrEvent::DeleteRootFolder(1)) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteRootFolder(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteRootFolder(1)) + .await + .is_ok() + ); - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -78,30 +64,25 @@ mod tests { "freeSpace": 219902325555200u64, }]); let response: Vec = serde_json::from_value(root_folder_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(root_folder_json), - None, - SonarrEvent::GetRootFolders, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(root_folder_json) + .build_for(SonarrEvent::GetRootFolders) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::RootFolders(root_folders) = network + let SonarrSerdeable::RootFolders(root_folders) = network .handle_sonarr_event(SonarrEvent::GetRootFolders) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.root_folders.items, - vec![root_folder()] - ); - assert_eq!(root_folders, response); - } + else { + panic!("Expected RootFolders") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.root_folders.items, + vec![root_folder()] + ); + assert_eq!(root_folders, response); } } diff --git a/src/network/sonarr_network/sonarr_network_test_utils.rs b/src/network/sonarr_network/sonarr_network_test_utils.rs index 0230262..e3fc28c 100644 --- a/src/network/sonarr_network/sonarr_network_test_utils.rs +++ b/src/network/sonarr_network/sonarr_network_test_utils.rs @@ -1,5 +1,5 @@ #[cfg(test)] -pub(in crate::network::sonarr_network) mod test_utils { +pub mod test_utils { use crate::models::servarr_models::{ Indexer, IndexerField, Language, Quality, QualityWrapper, RootFolder, }; @@ -7,11 +7,14 @@ pub(in crate::network::sonarr_network) mod test_utils { AddSeriesSearchResult, AddSeriesSearchResultStatistics, BlocklistItem, DownloadRecord, DownloadStatus, DownloadsResponse, Episode, EpisodeFile, IndexerSettings, MediaInfo, Rating, Season, SeasonStatistics, Series, SeriesStatistics, SeriesStatus, SeriesType, - SonarrHistoryData, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease, + SonarrHistoryData, SonarrHistoryEventType, SonarrHistoryItem, SonarrRelease, SonarrTask, + SonarrTaskName, }; - use crate::models::HorizontallyScrollableText; + use crate::models::{HorizontallyScrollableText, ScrollableText}; + use bimap::BiMap; use chrono::DateTime; - use serde_json::{json, Number}; + use indoc::formatdoc; + use serde_json::{Number, Value, json}; pub const SERIES_JSON: &str = r#"{ "title": "Test", @@ -22,6 +25,7 @@ pub(in crate::network::sonarr_network) mod test_utils { "seasons": [ { "seasonNumber": 1, + "title": "Season title", "monitored": true, "statistics": { "previousAiring": "2022-10-24T01:00:00Z", @@ -120,7 +124,7 @@ pub(in crate::network::sonarr_network) mod test_utils { BlocklistItem { id: 1, series_id: 1, - series_title: None, + series_title: Some("Test Series".to_owned()), episode_ids: vec![Number::from(1)], source_title: "Test Source Title".to_owned(), languages: vec![Some(language())], @@ -299,7 +303,7 @@ pub(in crate::network::sonarr_network) mod test_utils { pub fn season() -> Season { Season { - title: None, + title: Some("Season title".to_owned()), season_number: 1, monitored: true, statistics: Some(season_statistics()), @@ -364,7 +368,7 @@ pub(in crate::network::sonarr_network) mod test_utils { ] } - pub fn release() -> SonarrRelease { + pub fn torrent_release() -> SonarrRelease { SonarrRelease { guid: "1234".to_owned(), protocol: "torrent".to_owned(), @@ -383,6 +387,25 @@ pub(in crate::network::sonarr_network) mod test_utils { } } + pub fn usenet_release() -> SonarrRelease { + SonarrRelease { + guid: "1234".to_owned(), + protocol: "usenet".to_owned(), + age: 1, + title: HorizontallyScrollableText::from("Test Release"), + indexer: "DrunkenSlug".to_owned(), + indexer_id: 1, + size: 1234, + rejected: true, + rejections: Some(rejections()), + seeders: None, + leechers: None, + languages: Some(vec![Some(language())]), + quality: quality_wrapper(), + full_season: false, + } + } + pub fn root_folder() -> RootFolder { RootFolder { id: 1, @@ -392,4 +415,68 @@ pub(in crate::network::sonarr_network) mod test_utils { unmapped_folders: None, } } + + pub fn tag() -> Value { + json!({ + "id": 3, + "label": "testing" + }) + } + + pub fn log_line() -> &'static str { + "2025-12-16 16:40:59 UTC|INFO|ImportListSyncService|No list items to process" + } + + pub fn language_profiles_map() -> BiMap { + let Language { id, name } = language(); + + BiMap::from_iter(vec![(id, name)]) + } + + pub fn quality_profile_map() -> BiMap { + BiMap::from_iter(vec![(6, quality().name)]) + } + + pub fn tags_map() -> BiMap { + BiMap::from_iter(vec![(1, "alex".to_owned())]) + } + + pub fn task() -> SonarrTask { + SonarrTask { + name: "Backup".to_owned(), + task_name: SonarrTaskName::Backup, + interval: 60, + last_execution: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T21:29:16Z").unwrap()), + next_execution: DateTime::from(DateTime::parse_from_rfc3339("2023-05-20T22:29:16Z").unwrap()), + } + } + + pub fn updates() -> ScrollableText { + let line_break = "-".repeat(200); + ScrollableText::with_string(formatdoc!( + " + The latest version of Sonarr is already installed + + 4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) + {line_break} + New: + * Cool new thing + Fixed: + * Some bugs killed + + + 3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) + {line_break} + New: + * Cool new thing (old) + * Other cool new thing (old) + + + 2.1.0 - 2023-04-15 02:02:53 UTC + {line_break} + Fixed: + * Killed bug 1 + * Fixed bug 2" + )) + } } diff --git a/src/network/sonarr_network/sonarr_network_tests.rs b/src/network/sonarr_network/sonarr_network_tests.rs index 23e5d26..87aa4ce 100644 --- a/src/network/sonarr_network/sonarr_network_tests.rs +++ b/src/network/sonarr_network/sonarr_network_tests.rs @@ -9,18 +9,15 @@ mod test { AddSeriesBody, EditSeriesParams, IndexerSettings, SonarrTaskName, }; use crate::models::sonarr_models::{DeleteSeriesParams, SonarrSerdeable}; - use crate::network::{ - network_tests::test_utils::mock_servarr_api, sonarr_network::SonarrEvent, Network, - NetworkEvent, NetworkResource, RequestMethod, - }; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::tag; + use crate::network::{NetworkEvent, NetworkResource, sonarr_network::SonarrEvent}; use bimap::BiMap; use pretty_assertions::{assert_eq, assert_str_eq}; - use reqwest::Client; use rstest::rstest; use serde_json::json; use std::sync::Arc; use tokio::sync::Mutex; - use tokio_util::sync::CancellationToken; #[rstest] fn test_resource_all_indexer_settings( @@ -191,82 +188,74 @@ mod test { #[tokio::test] async fn test_handle_add_sonarr_tag() { - let tag_json = json!({ "id": 3, "label": "testing" }); - let response: Tag = serde_json::from_value(tag_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ "label": "testing" })), - Some(tag_json), - None, - SonarrEvent::AddTag(String::new()), - None, - None, - ) - .await; - app_arc.lock().await.data.sonarr_data.tags_map = - BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let expected = Tag { + id: 3, + label: "testing".to_owned(), + }; - if let SonarrSerdeable::Tag(tag) = network + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "label": "testing" })) + .returns(tag()) + .build_for(SonarrEvent::AddTag(String::new())) + .await; + + app.lock().await.data.sonarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); + app.lock().await.server_tabs.next(); + + let mut network = test_network(&app); + + let result = network .handle_sonarr_event(SonarrEvent::AddTag("testing".to_owned())) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.tags_map, - BiMap::from_iter([ - (1, "usenet".to_owned()), - (2, "test".to_owned()), - (3, "testing".to_owned()) - ]) - ); - assert_eq!(tag, response); - } + .await; + + mock.assert_async().await; + + let SonarrSerdeable::Tag(tag) = result.unwrap() else { + panic!("Expected Tag"); + }; + + assert_eq!(tag, expected); + assert_eq!( + app.lock().await.data.sonarr_data.tags_map, + BiMap::from_iter([ + (1, "usenet".to_owned()), + (2, "test".to_owned()), + (3, "testing".to_owned()) + ]) + ); } #[tokio::test] async fn test_handle_delete_sonarr_tag_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Delete, - None, - None, - None, - SonarrEvent::DeleteTag(1), - Some("/1"), - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (async_server, app, _server) = MockServarrApi::delete() + .path("/1") + .build_for(SonarrEvent::DeleteTag(1)) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - assert!(network - .handle_sonarr_event(SonarrEvent::DeleteTag(1)) - .await - .is_ok()); + assert!( + network + .handle_sonarr_event(SonarrEvent::DeleteTag(1)) + .await + .is_ok() + ); async_server.assert_async().await; } #[tokio::test] async fn test_handle_get_sonarr_healthcheck_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - None, - None, - SonarrEvent::HealthCheck, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .build_for(SonarrEvent::HealthCheck) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); let _ = network.handle_sonarr_event(SonarrEvent::HealthCheck).await; - async_server.assert_async().await; + mock.assert_async().await; } #[tokio::test] @@ -276,31 +265,28 @@ mod test { "name": "English" }]); let response: Vec = serde_json::from_value(language_profiles_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(language_profiles_json), - None, - SonarrEvent::GetLanguageProfiles, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(language_profiles_json) + .build_for(SonarrEvent::GetLanguageProfiles) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::LanguageProfiles(language_profiles) = network + let result = network .handle_sonarr_event(SonarrEvent::GetLanguageProfiles) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.language_profiles_map, - BiMap::from_iter([(2222i64, "English".to_owned())]) - ); - assert_eq!(language_profiles, response); - } + .await; + + mock.assert_async().await; + + let SonarrSerdeable::LanguageProfiles(language_profiles) = result.unwrap() else { + panic!("Expected LanguageProfiles") + }; + + assert_eq!( + app.lock().await.data.sonarr_data.language_profiles_map, + BiMap::from_iter([(2222i64, "English".to_owned())]) + ); + assert_eq!(language_profiles, response); } #[tokio::test] @@ -311,31 +297,28 @@ mod test { }]); let response: Vec = serde_json::from_value(quality_profile_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(quality_profile_json), - None, - SonarrEvent::GetQualityProfiles, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(quality_profile_json) + .build_for(SonarrEvent::GetQualityProfiles) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::QualityProfiles(quality_profiles) = network + let result = network .handle_sonarr_event(SonarrEvent::GetQualityProfiles) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.quality_profile_map, - BiMap::from_iter([(2222i64, "HD - 1080p".to_owned())]) - ); - assert_eq!(quality_profiles, response); - } + .await; + + mock.assert_async().await; + + let SonarrSerdeable::QualityProfiles(quality_profiles) = result.unwrap() else { + panic!("Expected QualityProfiles") + }; + + assert_eq!( + app.lock().await.data.sonarr_data.quality_profile_map, + BiMap::from_iter([(2222i64, "HD - 1080p".to_owned())]) + ); + assert_eq!(quality_profiles, response); } #[tokio::test] @@ -345,31 +328,27 @@ mod test { "label": "usenet" }]); let response: Vec = serde_json::from_value(tags_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(tags_json), - None, - SonarrEvent::GetTags, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(tags_json) + .build_for(SonarrEvent::GetTags) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Tags(tags) = network - .handle_sonarr_event(SonarrEvent::GetTags) - .await - .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.tags_map, - BiMap::from_iter([(2222i64, "usenet".to_owned())]) - ); - assert_eq!(tags, response); - } + let result = network.handle_sonarr_event(SonarrEvent::GetTags).await; + + mock.assert_async().await; + + let SonarrSerdeable::Tags(tags) = result.unwrap() else { + panic!("Expected Tags") + }; + + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.tags_map, + BiMap::from_iter([(2222i64, "usenet".to_owned())]) + ); + assert_eq!(tags, response); } #[tokio::test] @@ -385,7 +364,7 @@ mod test { ]); } app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let mut network = test_network(&app_arc); assert_eq!( network.extract_and_add_sonarr_tag_ids_vec(tags).await, @@ -395,35 +374,30 @@ mod test { #[tokio::test] async fn test_extract_and_add_sonarr_tag_ids_vec_add_missing_tags_first() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ "label": "TESTING" })), - Some(json!({ "id": 3, "label": "testing" })), - None, - SonarrEvent::GetTags, - None, - None, - ) - .await; + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "label": "TESTING" })) + .returns(json!({ "id": 3, "label": "testing" })) + .build_for(SonarrEvent::GetTags) + .await; let tags = "usenet, test, TESTING"; { - let mut app = app_arc.lock().await; - app.data.sonarr_data.add_series_modal = Some(AddSeriesModal { + let mut app_guard = app.lock().await; + app_guard.data.sonarr_data.add_series_modal = Some(AddSeriesModal { tags: tags.into(), ..AddSeriesModal::default() }); - app.data.sonarr_data.tags_map = + app_guard.data.sonarr_data.tags_map = BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]); } - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); let tag_ids_vec = network.extract_and_add_sonarr_tag_ids_vec(tags).await; - async_server.assert_async().await; + mock.assert_async().await; assert_eq!(tag_ids_vec, vec![1, 2, 3]); assert_eq!( - app_arc.lock().await.data.sonarr_data.tags_map, + app.lock().await.data.sonarr_data.tags_map, BiMap::from_iter([ (1, "usenet".to_owned()), (2, "test".to_owned()), diff --git a/src/network/sonarr_network/system/mod.rs b/src/network/sonarr_network/system/mod.rs index 63798f2..d2c1ed6 100644 --- a/src/network/sonarr_network/system/mod.rs +++ b/src/network/sonarr_network/system/mod.rs @@ -55,17 +55,29 @@ impl Network<'_, '_> { "{}|{}|{}|{}|{}", log.time, log.level.to_uppercase(), - log.logger.as_ref().unwrap(), - log.exception_type.as_ref().unwrap(), - log.exception.as_ref().unwrap() + log + .logger + .as_ref() + .expect("logger must exist when exception is present"), + log + .exception_type + .as_ref() + .expect("exception_type must exist when exception is present"), + log + .exception + .as_ref() + .expect("exception must exist in this branch") )) } else { HorizontallyScrollableText::from(format!( "{}|{}|{}|{}", log.time, log.level.to_uppercase(), - log.logger.as_ref().unwrap(), - log.message.as_ref().unwrap() + log.logger.as_ref().expect("logger must exist in log entry"), + log + .message + .as_ref() + .expect("message must exist when exception is not present") )) } }) @@ -190,9 +202,9 @@ impl Network<'_, '_> { .map(|update| { let install_status = if update.installed_on.is_some() { if update.installed { - "(Currently Installed)".to_owned() + " (Currently Installed)".to_owned() } else { - "(Previously Installed)".to_owned() + " (Previously Installed)".to_owned() } } else { String::new() @@ -206,7 +218,7 @@ impl Network<'_, '_> { }; let mut update_info = formatdoc!( - "{} - {} {install_status} + "{} - {}{install_status} {}", update.version, update.release_date, diff --git a/src/network/sonarr_network/system/sonarr_system_network_tests.rs b/src/network/sonarr_network/system/sonarr_system_network_tests.rs index 4ee3f37..b254176 100644 --- a/src/network/sonarr_network/system/sonarr_system_network_tests.rs +++ b/src/network/sonarr_network/system/sonarr_system_network_tests.rs @@ -1,19 +1,16 @@ #[cfg(test)] mod tests { + use crate::models::HorizontallyScrollableText; use crate::models::servarr_models::{ DiskSpace, HostConfig, LogResponse, QueueEvent, SecurityConfig, Update, }; use crate::models::sonarr_models::{SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus}; - use crate::models::{HorizontallyScrollableText, ScrollableText}; - use crate::network::network_tests::test_utils::mock_servarr_api; + use crate::network::network_tests::test_utils::{MockServarrApi, test_network}; use crate::network::sonarr_network::SonarrEvent; - use crate::network::{Network, RequestMethod}; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::updates; use chrono::DateTime; - use indoc::formatdoc; use pretty_assertions::{assert_eq, assert_str_eq}; - use reqwest::Client; use serde_json::json; - use tokio_util::sync::CancellationToken; #[tokio::test] async fn test_handle_get_sonarr_host_config_event() { @@ -29,27 +26,22 @@ mod tests { "sslCertPassword": "test" }); let response: HostConfig = serde_json::from_value(host_config_response.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(host_config_response), - None, - SonarrEvent::GetHostConfig, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(host_config_response) + .build_for(SonarrEvent::GetHostConfig) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::HostConfig(host_config) = network + let SonarrSerdeable::HostConfig(host_config) = network .handle_sonarr_event(SonarrEvent::GetHostConfig) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(host_config, response); - } + else { + panic!("Expected HostConfig") + }; + mock.assert_async().await; + assert_eq!(host_config, response); } #[tokio::test] @@ -85,30 +77,25 @@ mod tests { ] }); let response: LogResponse = serde_json::from_value(logs_response_json.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(logs_response_json), - None, - SonarrEvent::GetLogs(500), - None, - Some("pageSize=500&sortDirection=descending&sortKey=time"), - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(logs_response_json) + .query("pageSize=500&sortDirection=descending&sortKey=time") + .build_for(SonarrEvent::GetLogs(500)) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::LogResponse(logs) = network + let SonarrSerdeable::LogResponse(logs) = network .handle_sonarr_event(SonarrEvent::GetLogs(500)) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.logs.items, - expected_logs - ); - assert!(app_arc + else { + panic!("Expected LogResponse") + }; + mock.assert_async().await; + assert_eq!(app.lock().await.data.sonarr_data.logs.items, expected_logs); + assert!( + app .lock() .await .data @@ -116,17 +103,15 @@ mod tests { .logs .current_selection() .text - .contains("INFO")); - assert_eq!(logs, response); - } + .contains("INFO") + ); + assert_eq!(logs, response); } #[tokio::test] async fn test_handle_get_sonarr_diskspace_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!([ + let (mock, app, _server) = MockServarrApi::get() + .returns(json!([ { "freeSpace": 1111, "totalSpace": 2222, @@ -135,15 +120,11 @@ mod tests { "freeSpace": 3333, "totalSpace": 4444 } - ])), - None, - SonarrEvent::GetDiskSpace, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + ])) + .build_for(SonarrEvent::GetDiskSpace) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); let disk_space_vec = vec![ DiskSpace { free_space: 1111, @@ -155,18 +136,19 @@ mod tests { }, ]; - if let SonarrSerdeable::DiskSpaces(disk_space) = network + let SonarrSerdeable::DiskSpaces(disk_space) = network .handle_sonarr_event(SonarrEvent::GetDiskSpace) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.disk_space_vec, - disk_space_vec - ); - assert_eq!(disk_space, disk_space_vec); - } + else { + panic!("Expected DiskSpaces") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.disk_space_vec, + disk_space_vec + ); + assert_eq!(disk_space, disk_space_vec); } #[tokio::test] @@ -194,31 +176,26 @@ mod tests { trigger: "scheduled".to_owned(), }; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(queued_events_json), - None, - SonarrEvent::GetQueuedEvents, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(queued_events_json) + .build_for(SonarrEvent::GetQueuedEvents) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::QueueEvents(events) = network + let SonarrSerdeable::QueueEvents(events) = network .handle_sonarr_event(SonarrEvent::GetQueuedEvents) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.queued_events.items, - vec![expected_event] - ); - assert_eq!(events, response); - } + else { + panic!("Expected QueueEvents") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.queued_events.items, + vec![expected_event] + ); + assert_eq!(events, response); } #[tokio::test] @@ -233,64 +210,54 @@ mod tests { }); let response: SecurityConfig = serde_json::from_value(security_config_response.clone()).unwrap(); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(security_config_response), - None, - SonarrEvent::GetSecurityConfig, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(security_config_response) + .build_for(SonarrEvent::GetSecurityConfig) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::SecurityConfig(security_config) = network + let SonarrSerdeable::SecurityConfig(security_config) = network .handle_sonarr_event(SonarrEvent::GetSecurityConfig) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(security_config, response); - } + else { + panic!("Expected SecurityConfig") + }; + mock.assert_async().await; + assert_eq!(security_config, response); } #[tokio::test] async fn test_handle_get_status_event() { - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(json!({ + let (mock, app, _server) = MockServarrApi::get() + .returns(json!({ "version": "v1", "startTime": "2023-02-25T20:16:43Z" - })), - None, - SonarrEvent::GetStatus, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + })) + .build_for(SonarrEvent::GetStatus) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); let date_time = DateTime::from(DateTime::parse_from_rfc3339("2023-02-25T20:16:43Z").unwrap()); - if let SonarrSerdeable::SystemStatus(status) = network + let SonarrSerdeable::SystemStatus(status) = network .handle_sonarr_event(SonarrEvent::GetStatus) .await .unwrap() - { - async_server.assert_async().await; - assert_str_eq!(app_arc.lock().await.data.sonarr_data.version, "v1"); - assert_eq!(app_arc.lock().await.data.sonarr_data.start_time, date_time); - assert_eq!( - status, - SystemStatus { - version: "v1".to_owned(), - start_time: date_time - } - ); - } + else { + panic!("Expected SystemStatus") + }; + mock.assert_async().await; + assert_str_eq!(app.lock().await.data.sonarr_data.version, "v1"); + assert_eq!(app.lock().await.data.sonarr_data.start_time, date_time); + assert_eq!( + status, + SystemStatus { + version: "v1".to_owned(), + start_time: date_time + } + ); } #[tokio::test] @@ -327,31 +294,26 @@ mod tests { next_execution: timestamp, }, ]; - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(tasks_json), - None, - SonarrEvent::GetTasks, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + let (mock, app, _server) = MockServarrApi::get() + .returns(tasks_json) + .build_for(SonarrEvent::GetTasks) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Tasks(tasks) = network + let SonarrSerdeable::Tasks(tasks) = network .handle_sonarr_event(SonarrEvent::GetTasks) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!( - app_arc.lock().await.data.sonarr_data.tasks.items, - expected_tasks - ); - assert_eq!(tasks, response); - } + else { + panic!("Expected Tasks") + }; + mock.assert_async().await; + assert_eq!( + app.lock().await.data.sonarr_data.tasks.items, + expected_tasks + ); + assert_eq!(tasks, response); } #[tokio::test] @@ -397,75 +359,49 @@ mod tests { }, }]); let response: Vec = serde_json::from_value(updates_json.clone()).unwrap(); - let line_break = "-".repeat(200); - let expected_text = ScrollableText::with_string(formatdoc!( - " - The latest version of Sonarr is already installed + let expected_text = updates(); + let (mock, app, _server) = MockServarrApi::get() + .returns(updates_json) + .build_for(SonarrEvent::GetUpdates) + .await; + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - 4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) - {line_break} - New: - * Cool new thing - Fixed: - * Some bugs killed - - - 3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) - {line_break} - New: - * Cool new thing (old) - * Other cool new thing (old) - - - 2.1.0 - 2023-04-15 02:02:53 UTC - {line_break} - Fixed: - * Killed bug 1 - * Fixed bug 2" - )); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(updates_json), - None, - SonarrEvent::GetUpdates, - None, - None, - ) - .await; - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); - - if let SonarrSerdeable::Updates(updates) = network + let SonarrSerdeable::Updates(updates) = network .handle_sonarr_event(SonarrEvent::GetUpdates) .await .unwrap() - { - async_server.assert_async().await; - assert_str_eq!( - app_arc.lock().await.data.sonarr_data.updates.get_text(), - expected_text.get_text() - ); - assert_eq!(updates, response); - } + else { + panic!("Expected Updates") + }; + mock.assert_async().await; + let actual_text = app.lock().await.data.sonarr_data.updates.get_text(); + let expected = expected_text.get_text(); + + // Trim trailing whitespace from each line for comparison + let actual_trimmed: Vec<&str> = actual_text.lines().map(|l| l.trim_end()).collect(); + let expected_trimmed: Vec<&str> = expected.lines().map(|l| l.trim_end()).collect(); + + assert_eq!( + actual_trimmed, expected_trimmed, + "Updates text mismatch (after trimming trailing whitespace)" + ); + assert_eq!(updates, response); } #[tokio::test] async fn test_handle_start_sonarr_task_event() { let response = json!({ "test": "test"}); - let (async_server, app_arc, _server) = mock_servarr_api( - RequestMethod::Post, - Some(json!({ + let (mock, app, _server) = MockServarrApi::post() + .with_request_body(json!({ "name": "ApplicationUpdateCheck" - })), - Some(response.clone()), - None, - SonarrEvent::StartTask(SonarrTaskName::ApplicationUpdateCheck), - None, - None, - ) - .await; - app_arc + })) + .returns(response.clone()) + .build_for(SonarrEvent::StartTask( + SonarrTaskName::ApplicationUpdateCheck, + )) + .await; + app .lock() .await .data @@ -475,18 +411,19 @@ mod tests { task_name: SonarrTaskName::default(), ..SonarrTask::default() }]); - app_arc.lock().await.server_tabs.next(); - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + app.lock().await.server_tabs.next(); + let mut network = test_network(&app); - if let SonarrSerdeable::Value(value) = network + let SonarrSerdeable::Value(value) = network .handle_sonarr_event(SonarrEvent::StartTask( SonarrTaskName::ApplicationUpdateCheck, )) .await .unwrap() - { - async_server.assert_async().await; - assert_eq!(value, response); - } + else { + panic!("Expected Value") + }; + mock.assert_async().await; + assert_eq!(value, response); } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 7068648..58f88dc 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,6 +1,7 @@ use std::cell::Cell; use std::sync::atomic::Ordering; +use ratatui::Frame; use ratatui::layout::{Constraint, Flex, Layout, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::{Line, Text}; @@ -8,7 +9,6 @@ use ratatui::widgets::Paragraph; use ratatui::widgets::Tabs; use ratatui::widgets::Wrap; use ratatui::widgets::{Clear, Row}; -use ratatui::Frame; use sonarr_ui::SonarrUi; use utils::layout_block; @@ -31,6 +31,12 @@ mod radarr_ui; mod sonarr_ui; mod styles; pub mod theme; +#[cfg(test)] +mod ui_property_tests; +#[cfg(test)] +pub mod ui_test_utils; +#[cfg(test)] +mod ui_tests; mod utils; mod widgets; diff --git a/src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs b/src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs index 7609341..553a4a5 100644 --- a/src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +++ b/src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs @@ -1,10 +1,13 @@ #[cfg(test)] mod tests { - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS}; - use crate::ui::radarr_ui::blocklist::BlocklistUi; - use crate::ui::DrawUi; use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS}; + use crate::ui::DrawUi; + use crate::ui::radarr_ui::blocklist::BlocklistUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; + #[test] fn test_blocklist_ui_accepts() { ActiveRadarrBlock::iter().for_each(|active_radarr_block| { @@ -15,4 +18,56 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_blocklist_ui_renders_blocklist_tab_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + BlocklistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_blocklist_ui_renders_empty_blocklist() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + BlocklistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_blocklist_ui_renders_blocklist_tab( + #[values( + ActiveRadarrBlock::Blocklist, + ActiveRadarrBlock::BlocklistSortPrompt, + ActiveRadarrBlock::DeleteBlocklistItemPrompt, + ActiveRadarrBlock::BlocklistClearAllItemsPrompt + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + BlocklistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + } } diff --git a/src/ui/radarr_ui/blocklist/mod.rs b/src/ui/radarr_ui/blocklist/mod.rs index 260cfbd..f4afeeb 100644 --- a/src/ui/radarr_ui/blocklist/mod.rs +++ b/src/ui/radarr_ui/blocklist/mod.rs @@ -1,19 +1,19 @@ use crate::app::App; +use crate::models::Route; use crate::models::radarr_models::BlocklistItem; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS}; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{get_width_from_percentage, layout_block_top_border}; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; +use ratatui::Frame; use ratatui::layout::{Alignment, Constraint, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::{Line, Text}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; #[cfg(test)] #[path = "blocklist_ui_tests.rs"] @@ -23,11 +23,10 @@ pub(super) struct BlocklistUi; impl DrawUi for BlocklistUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return BLOCKLIST_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + BLOCKLIST_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { diff --git a/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__Blocklist.snap b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__Blocklist.snap new file mode 100644 index 0000000..1d3898a --- /dev/null +++ b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__Blocklist.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Movie Title ▼ Source Title Languages Quality Formats Date +=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC diff --git a/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__BlocklistClearAllItemsPrompt.snap b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__BlocklistClearAllItemsPrompt.snap new file mode 100644 index 0000000..22d813f --- /dev/null +++ b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__BlocklistClearAllItemsPrompt.snap @@ -0,0 +1,34 @@ +--- +source: src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Movie Title ▼ Source Title Languages Quality Formats Date +=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + ╭────── Clear Blocklist ──────╮ + │ Do you want to clear your │ + │ blocklist? │ + │ │ + │ │ + │ │ + │╭──────────────╮╭─────────────╮│ + ││ Yes ││ No ││ + │╰──────────────╯╰─────────────╯│ + ╰───────────────────────────────╯ diff --git a/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__BlocklistSortPrompt.snap b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__BlocklistSortPrompt.snap new file mode 100644 index 0000000..d0ab7ed --- /dev/null +++ b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__BlocklistSortPrompt.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Movie Title Source Title Languages Quality Formats Date +=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC + + + + + + + + + + + ╭───────────────────────────────╮ + │Something │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────╯ diff --git a/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__DeleteBlocklistItemPrompt.snap b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__DeleteBlocklistItemPrompt.snap new file mode 100644 index 0000000..c90b41f --- /dev/null +++ b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__DeleteBlocklistItemPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Movie Title ▼ Source Title Languages Quality Formats Date +=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + ╭────────────── Remove Item from Blocklist ───────────────╮ + │ Do you want to remove this item from your blocklist: │ + │ z movie? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_blocklist_tab_loading.snap b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_blocklist_tab_loading.snap new file mode 100644 index 0000000..0672cee --- /dev/null +++ b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_blocklist_tab_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_empty_blocklist.snap b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_empty_blocklist.snap new file mode 100644 index 0000000..1bfa784 --- /dev/null +++ b/src/ui/radarr_ui/blocklist/snapshots/managarr__ui__radarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_empty_blocklist.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/radarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/radarr_ui/collections/collection_details_ui.rs b/src/ui/radarr_ui/collections/collection_details_ui.rs index 67b9436..f794e43 100644 --- a/src/ui/radarr_ui/collections/collection_details_ui.rs +++ b/src/ui/radarr_ui/collections/collection_details_ui.rs @@ -1,15 +1,15 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Flex, Layout, Rect}; use ratatui::style::Stylize; use ratatui::text::{Line, Text}; use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::radarr_models::CollectionMovie; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, }; -use crate::models::Route; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{ borderless_block, get_width_from_percentage, layout_block_top_border_with_title, title_block, @@ -17,7 +17,7 @@ use crate::ui::utils::{ }; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; use crate::utils::convert_runtime; #[cfg(test)] @@ -100,7 +100,7 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) .unwrap_or_default() .value .as_f64() - .unwrap(); + .unwrap_or_default(); let rotten_tomatoes_rating = movie .ratings .rotten_tomatoes @@ -108,7 +108,7 @@ pub fn draw_collection_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) .unwrap_or_default() .value .as_u64() - .unwrap(); + .unwrap_or_default(); let imdb_rating = if imdb_rating == 0.0 { String::new() } else { diff --git a/src/ui/radarr_ui/collections/collection_details_ui_tests.rs b/src/ui/radarr_ui/collections/collection_details_ui_tests.rs index 871c688..9a78c2f 100644 --- a/src/ui/radarr_ui/collections/collection_details_ui_tests.rs +++ b/src/ui/radarr_ui/collections/collection_details_ui_tests.rs @@ -2,11 +2,13 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, }; - use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_collection_details_ui_accepts() { @@ -33,4 +35,41 @@ mod tests { .into() )); } + + mod snapshot_tests { + use super::*; + use crate::models::stateful_table::StatefulTable; + use rstest::rstest; + + #[rstest] + fn test_collection_details_ui_renders_collection_details( + #[values( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::ViewMovieOverview + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + CollectionDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + + #[test] + fn test_collection_details_ui_renders_collection_details_empty() { + let mut app = App::test_default_fully_populated(); + app.data.radarr_data.collection_movies = StatefulTable::default(); + app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + CollectionDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/collections/collections_ui_tests.rs b/src/ui/radarr_ui/collections/collections_ui_tests.rs index 1f66677..10fff87 100644 --- a/src/ui/radarr_ui/collections/collections_ui_tests.rs +++ b/src/ui/radarr_ui/collections/collections_ui_tests.rs @@ -2,11 +2,15 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, COLLECTIONS_BLOCKS, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, + ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, COLLECTIONS_BLOCKS, EDIT_COLLECTION_BLOCKS, }; - use crate::ui::radarr_ui::collections::CollectionsUi; + use crate::models::stateful_table::StatefulTable; use crate::ui::DrawUi; + use crate::ui::radarr_ui::collections::CollectionsUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_collections_ui_accepts() { @@ -23,4 +27,131 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::EDIT_COLLECTION_SELECTION_BLOCKS; + use rstest::rstest; + + #[rstest] + #[case(true, false, false)] + #[case(false, true, false)] + #[case(false, false, true)] + fn test_radarr_ui_renders_collections_tab_loading( + #[case] is_loading: bool, + #[case] empty_movies: bool, + #[case] empty_profile_map: bool, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::Collections.into()); + app.is_loading = is_loading; + if empty_movies { + app.data.radarr_data.movies = StatefulTable::default(); + } + + if empty_profile_map { + app.data.radarr_data.quality_profile_map = Default::default(); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + CollectionsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!( + "is_loading_{is_loading}_empty_movies_{empty_movies}_empty_profile_{empty_profile_map}" + ), + output + ); + } + + #[rstest] + fn test_radarr_ui_renders_collections_tab( + #[values( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::CollectionsSortPrompt, + ActiveRadarrBlock::FilterCollections, + ActiveRadarrBlock::FilterCollectionsError, + ActiveRadarrBlock::SearchCollection, + ActiveRadarrBlock::SearchCollectionError, + ActiveRadarrBlock::UpdateAllCollectionsPrompt + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + CollectionsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("collections_tab_{active_radarr_block}"), output); + } + + #[test] + fn test_radarr_ui_renders_collections_tab_empty() { + let mut app = App::test_default_fully_populated(); + app.data.radarr_data.collections = StatefulTable::default(); + app.push_navigation_stack(ActiveRadarrBlock::Collections.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + CollectionsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionPrompt + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionConfirmPrompt + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionRootFolderPathInput + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionSelectMinimumAvailability + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionSelectQualityProfile + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionToggleSearchOnAdd + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionToggleMonitored + )] + fn test_edit_collection_ui_renders_edit_collection_modal( + #[case] context_block: ActiveRadarrBlock, + #[case] active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack((active_radarr_block, Some(context_block)).into()); + app.data.radarr_data.selected_block = + BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + CollectionsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!( + "edit_collection_modal_{}_{}", + active_radarr_block.to_string(), + context_block.to_string() + ), + output + ); + } + } } diff --git a/src/ui/radarr_ui/collections/edit_collection_ui.rs b/src/ui/radarr_ui/collections/edit_collection_ui.rs index 407eb23..38ef03c 100644 --- a/src/ui/radarr_ui/collections/edit_collection_ui.rs +++ b/src/ui/radarr_ui/collections/edit_collection_ui.rs @@ -1,14 +1,14 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::widgets::ListItem; -use ratatui::Frame; use std::sync::atomic::Ordering; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::radarr::modals::EditCollectionModal; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, COLLECTION_DETAILS_BLOCKS, EDIT_COLLECTION_BLOCKS, }; -use crate::models::Route; use crate::render_selectable_input_box; use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; use crate::ui::styles::ManagarrStyle; @@ -18,7 +18,7 @@ use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; #[cfg(test)] #[path = "edit_collection_ui_tests.rs"] @@ -42,10 +42,10 @@ impl DrawUi for EditCollectionUi { fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() { - if let Some(context) = context_option { - if COLLECTION_DETAILS_BLOCKS.contains(&context) { - draw_popup(f, app, CollectionDetailsUi::draw, Size::Large); - } + if let Some(context) = context_option + && COLLECTION_DETAILS_BLOCKS.contains(&context) + { + draw_popup(f, app, CollectionDetailsUi::draw, Size::Large); } draw_popup( @@ -100,19 +100,27 @@ fn draw_edit_collection_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_> let selected_minimum_availability = minimum_availability_list.current_selection(); let selected_quality_profile = quality_profile_list.current_selection(); - let [paragraph_area, monitored_area, min_availability_area, quality_profile_area, root_folder_area, search_on_add_area, _, buttons_area] = - Layout::vertical([ - Constraint::Length(6), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Fill(1), - Constraint::Length(3), - ]) - .margin(1) - .areas(area); + let [ + paragraph_area, + monitored_area, + min_availability_area, + quality_profile_area, + root_folder_area, + search_on_add_area, + _, + buttons_area, + ] = Layout::vertical([ + Constraint::Length(6), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) + .margin(1) + .areas(area); let [save_area, cancel_area] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .areas(buttons_area); diff --git a/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs b/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs index 6e37d4b..d4f94f5 100644 --- a/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +++ b/src/ui/radarr_ui/collections/edit_collection_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS, + ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS, EDIT_COLLECTION_SELECTION_BLOCKS, }; - use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_edit_collection_ui_accepts() { @@ -26,4 +29,89 @@ mod tests { .into() )); } + + mod snapshot_tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionPrompt + )] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionConfirmPrompt + )] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionRootFolderPathInput + )] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionSelectMinimumAvailability + )] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionSelectQualityProfile + )] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionToggleSearchOnAdd + )] + #[case( + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::EditCollectionToggleMonitored + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionPrompt + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionConfirmPrompt + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionRootFolderPathInput + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionSelectMinimumAvailability + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionSelectQualityProfile + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionToggleSearchOnAdd + )] + #[case( + ActiveRadarrBlock::CollectionDetails, + ActiveRadarrBlock::EditCollectionToggleMonitored + )] + fn test_edit_collection_ui_renders_edit_collection_modal( + #[case] active_radarr_block: ActiveRadarrBlock, + #[case] context_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack((active_radarr_block, Some(context_block)).into()); + app.data.radarr_data.selected_block = + BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditCollectionUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!( + "{}_{}", + active_radarr_block.to_string(), + context_block.to_string() + ), + output + ); + } + } } diff --git a/src/ui/radarr_ui/collections/mod.rs b/src/ui/radarr_ui/collections/mod.rs index 3ab7f97..8cb7539 100644 --- a/src/ui/radarr_ui/collections/mod.rs +++ b/src/ui/radarr_ui/collections/mod.rs @@ -1,11 +1,12 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::radarr_models::Collection; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, COLLECTIONS_BLOCKS}; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::radarr_ui::collections::collection_details_ui::CollectionDetailsUi; use crate::ui::radarr_ui::collections::edit_collection_ui::EditCollectionUi; use crate::ui::styles::ManagarrStyle; @@ -13,7 +14,6 @@ use crate::ui::utils::{get_width_from_percentage, layout_block_top_border}; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; mod collection_details_ui; #[cfg(test)] @@ -25,13 +25,12 @@ pub(super) struct CollectionsUi; impl DrawUi for CollectionsUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return CollectionDetailsUi::accepts(route) - || EditCollectionUi::accepts(route) - || COLLECTIONS_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + CollectionDetailsUi::accepts(route) + || EditCollectionUi::accepts(route) + || COLLECTIONS_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { @@ -39,8 +38,8 @@ impl DrawUi for CollectionsUi { draw_collections(f, app, area); match route { - _ if CollectionDetailsUi::accepts(route) => CollectionDetailsUi::draw(f, app, area), _ if EditCollectionUi::accepts(route) => EditCollectionUi::draw(f, app, area), + _ if CollectionDetailsUi::accepts(route) => CollectionDetailsUi::draw(f, app, area), Route::Radarr(ActiveRadarrBlock::UpdateAllCollectionsPrompt, _) => { let confirmation_prompt = ConfirmationPrompt::new() .title("Update All Collections") diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__CollectionDetails.snap new file mode 100644 index 0000000..f5e36f1 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collection_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Availability: Released │ + │Monitored: Yes │ + │Search on Add: Yes │ + │ │ + │ │ + │ │ + │ Movies ────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ ✔ Title Year Runtime IMDB Rating Rotten Tomatoes Rating Genres │ + │=> ✔ Test 2023 2h 0m 9.9 99% cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__ViewMovieOverview.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__ViewMovieOverview.snap new file mode 100644 index 0000000..f129468 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__ViewMovieOverview.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collection_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Availability: Released │ + │Monitored: Yes │ + │Search on Add: Yes │ + │ │ + │ │ + │ ╭ Overview ────────────────────────────────────────────────────╮ │ + │ Movies ───────────────────│Collection blah blah blah │───────────────────────────│ + │ ✔ Title │ │ │ + │=> ✔ Test │ │family, fun │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__collection_details_ui_renders_collection_details_empty.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__collection_details_ui_renders_collection_details_empty.snap new file mode 100644 index 0000000..5d926d8 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collection_details_ui__collection_details_ui_tests__tests__snapshot_tests__collection_details_ui_renders_collection_details_empty.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collection_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Availability: Released │ + │Monitored: Yes │ + │Search on Add: Yes │ + │ │ + │ │ + │ │ + │ Movies ────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_Collections.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_Collections.snap new file mode 100644 index 0000000..b63c8c7 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_Collections.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_CollectionsSortPrompt.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_CollectionsSortPrompt.snap new file mode 100644 index 0000000..8d270f1 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_CollectionsSortPrompt.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + + + + + + + + ╭───────────────────────────────╮ + │Something │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_FilterCollections.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_FilterCollections.snap new file mode 100644 index 0000000..32bec1f --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_FilterCollections.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + + + + + + + + + + + + + + + + ╭───────────────── Filter ──────────────────╮ + │Something │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_FilterCollectionsError.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_FilterCollectionsError.snap new file mode 100644 index 0000000..86a684b --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_FilterCollectionsError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │The given filter produced empty results│ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_SearchCollection.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_SearchCollection.snap new file mode 100644 index 0000000..b023d51 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_SearchCollection.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + + + + + + + + + + + + + + + + ╭───────────────── Search ──────────────────╮ + │Something │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_SearchCollectionError.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_SearchCollectionError.snap new file mode 100644 index 0000000..eef3209 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_SearchCollectionError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ No items found matching search │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_UpdateAllCollectionsPrompt.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_UpdateAllCollectionsPrompt.snap new file mode 100644 index 0000000..0a60964 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__collections_tab_UpdateAllCollectionsPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + + + + + + + + + + + ╭──────────────── Update All Collections ─────────────────╮ + │ Do you want to update all of your collections? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionConfirmPrompt_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionConfirmPrompt_CollectionDetails.snap new file mode 100644 index 0000000..47b203b --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionConfirmPrompt_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Search on Add: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionPrompt_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionPrompt_CollectionDetails.snap new file mode 100644 index 0000000..47b203b --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionPrompt_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Search on Add: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionRootFolderPathInput_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionRootFolderPathInput_CollectionDetails.snap new file mode 100644 index 0000000..47b203b --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionRootFolderPathInput_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Search on Add: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionSelectMinimumAvailability_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionSelectMinimumAvailability_CollectionDetails.snap new file mode 100644 index 0000000..5cf8254 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionSelectMinimumAvailability_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ ╭───────────────────────────────╮ │ │ + │ │ │Announced │ │ │ + │ │ │In Cinemas │───────────────────────────╮ │ │ + │ │ Minimum│Released │ ▼ │ │ │ + │ │ │TBA │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionSelectQualityProfile_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionSelectQualityProfile_CollectionDetails.snap new file mode 100644 index 0000000..ee34413 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionSelectQualityProfile_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ ╭───────────────────────────────╮ │ │ + │ │ │HD - 1080p │ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionToggleMonitored_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionToggleMonitored_CollectionDetails.snap new file mode 100644 index 0000000..47b203b --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionToggleMonitored_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Search on Add: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionToggleSearchOnAdd_CollectionDetails.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionToggleSearchOnAdd_CollectionDetails.snap new file mode 100644 index 0000000..47b203b --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__edit_collection_modal_EditCollectionToggleSearchOnAdd_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭───╮ │ │ + │=> ✔ Test │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Search on Add: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_false_empty_movies_false_empty_profile_true.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_false_empty_movies_false_empty_profile_true.snap new file mode 100644 index 0000000..998f70c --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_false_empty_movies_false_empty_profile_true.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_false_empty_movies_true_empty_profile_false.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_false_empty_movies_true_empty_profile_false.snap new file mode 100644 index 0000000..998f70c --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_false_empty_movies_true_empty_profile_false.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_true_empty_movies_false_empty_profile_false.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_true_empty_movies_false_empty_profile_false.snap new file mode 100644 index 0000000..998f70c --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__is_loading_true_empty_movies_false_empty_profile_false.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__radarr_ui_renders_collections_tab_empty.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__radarr_ui_renders_collections_tab_empty.snap new file mode 100644 index 0000000..cf90617 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__collections_ui_tests__tests__snapshot_tests__radarr_ui_renders_collections_tab_empty.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/radarr_ui/collections/collections_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionConfirmPrompt.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionConfirmPrompt.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionConfirmPrompt.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionPrompt.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionPrompt.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionPrompt.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionRootFolderPathInput.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionRootFolderPathInput.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionRootFolderPathInput.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionSelectMinimumAvailability.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionSelectMinimumAvailability.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionSelectMinimumAvailability.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionSelectQualityProfile.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionSelectQualityProfile.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionSelectQualityProfile.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionToggleMonitored.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionToggleMonitored.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionToggleMonitored.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionToggleSearchOnAdd.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionToggleSearchOnAdd.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__CollectionDetails_EditCollectionToggleSearchOnAdd.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionConfirmPrompt.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionConfirmPrompt.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionConfirmPrompt.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionPrompt.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionPrompt.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionPrompt.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionRootFolderPathInput.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionRootFolderPathInput.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionRootFolderPathInput.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionSelectMinimumAvailability.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionSelectMinimumAvailability.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionSelectMinimumAvailability.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionSelectQualityProfile.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionSelectQualityProfile.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionSelectQualityProfile.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionToggleMonitored.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionToggleMonitored.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionToggleMonitored.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionToggleSearchOnAdd.snap b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionToggleSearchOnAdd.snap new file mode 100644 index 0000000..6ddcb02 --- /dev/null +++ b/src/ui/radarr_ui/collections/snapshots/managarr__ui__radarr_ui__collections__edit_collection_ui__edit_collection_ui_tests__tests__snapshot_tests__Collections_EditCollectionToggleSearchOnAdd.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/collections/edit_collection_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭─────────────────────────────────── Edit - Test Collection ────────────────────────────────────╮ + │ Collection blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Root Folder: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭───╮ │ + │ Search on Add: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/downloads/downloads_ui_tests.rs b/src/ui/radarr_ui/downloads/downloads_ui_tests.rs index c6b6bc0..8e27e63 100644 --- a/src/ui/radarr_ui/downloads/downloads_ui_tests.rs +++ b/src/ui/radarr_ui/downloads/downloads_ui_tests.rs @@ -2,9 +2,11 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; - use crate::ui::radarr_ui::downloads::DownloadsUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::downloads::DownloadsUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_downloads_ui_accepts() { @@ -16,4 +18,53 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use rstest::rstest; + + #[test] + fn test_radarr_ui_renders_downloads_tab_loading() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::Downloads.into()); + app.is_loading = true; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DownloadsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_radarr_ui_renders_downloads_tab( + #[values( + ActiveRadarrBlock::Downloads, + ActiveRadarrBlock::DeleteDownloadPrompt, + ActiveRadarrBlock::UpdateDownloadsPrompt + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DownloadsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + + #[test] + fn test_radarr_ui_renders_downloads_tab_empty() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::Downloads.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DownloadsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/downloads/mod.rs b/src/ui/radarr_ui/downloads/mod.rs index 3766d1b..30db8c2 100644 --- a/src/ui/radarr_ui/downloads/mod.rs +++ b/src/ui/radarr_ui/downloads/mod.rs @@ -1,17 +1,17 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; use crate::models::radarr_models::DownloadRecord; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS}; use crate::models::{HorizontallyScrollableText, Route}; +use crate::ui::DrawUi; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{get_width_from_percentage, layout_block_top_border}; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; use crate::utils::convert_to_gb; #[cfg(test)] @@ -22,11 +22,10 @@ pub(super) struct DownloadsUi; impl DrawUi for DownloadsUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return DOWNLOADS_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + DOWNLOADS_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { diff --git a/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__DeleteDownloadPrompt.snap b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__DeleteDownloadPrompt.snap new file mode 100644 index 0000000..6296a15 --- /dev/null +++ b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__DeleteDownloadPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Percent Complete Size Output Path Indexer Download Client +=> Test Download Title 50% 3.30 GB /nfs/movies/Test kickass torrents transmission + + + + + + + + + + + + + + ╭──────────────────── Cancel Download ────────────────────╮ + │ Do you really want to delete this download: │ + │ Test Download Title? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__Downloads.snap b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__Downloads.snap new file mode 100644 index 0000000..e459f73 --- /dev/null +++ b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__Downloads.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/radarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Percent Complete Size Output Path Indexer Download Client +=> Test Download Title 50% 3.30 GB /nfs/movies/Test kickass torrents transmission diff --git a/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__UpdateDownloadsPrompt.snap b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__UpdateDownloadsPrompt.snap new file mode 100644 index 0000000..11084ba --- /dev/null +++ b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__UpdateDownloadsPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Percent Complete Size Output Path Indexer Download Client +=> Test Download Title 50% 3.30 GB /nfs/movies/Test kickass torrents transmission + + + + + + + + + + + + + + ╭─────────────────── Update Downloads ────────────────────╮ + │ Do you want to update your downloads? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__radarr_ui_renders_downloads_tab_empty.snap b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__radarr_ui_renders_downloads_tab_empty.snap new file mode 100644 index 0000000..98a5dca --- /dev/null +++ b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__radarr_ui_renders_downloads_tab_empty.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/radarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__radarr_ui_renders_downloads_tab_loading.snap b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__radarr_ui_renders_downloads_tab_loading.snap new file mode 100644 index 0000000..a84c6d5 --- /dev/null +++ b/src/ui/radarr_ui/downloads/snapshots/managarr__ui__radarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__radarr_ui_renders_downloads_tab_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/indexers/edit_indexer_ui.rs b/src/ui/radarr_ui/indexers/edit_indexer_ui.rs index 85fc58a..cd7f52a 100644 --- a/src/ui/radarr_ui/indexers/edit_indexer_ui.rs +++ b/src/ui/radarr_ui/indexers/edit_indexer_ui.rs @@ -1,8 +1,8 @@ use std::sync::atomic::Ordering; use crate::app::App; -use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::Route; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; use crate::render_selectable_input_box; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::title_block_centered; @@ -11,9 +11,9 @@ use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; -use ratatui::layout::{Constraint, Flex, Layout, Rect}; +use crate::ui::{DrawUi, draw_popup}; use ratatui::Frame; +use ratatui::layout::{Constraint, Flex, Layout, Rect}; #[cfg(test)] #[path = "edit_indexer_ui_tests.rs"] @@ -55,15 +55,20 @@ fn draw_edit_indexer_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { Layout::horizontal([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)]) .margin(1) .areas(settings_area); - let [name_area, rss_area, auto_search_area, interactive_search_area, priority_area] = - Layout::vertical([ - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - ]) - .areas(left_side_area); + let [ + name_area, + rss_area, + auto_search_area, + interactive_search_area, + priority_area, + ] = Layout::vertical([ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + ]) + .areas(left_side_area); let [url_area, api_key_area, seed_ratio_area, tags_area] = Layout::vertical([ Constraint::Length(3), Constraint::Length(3), diff --git a/src/ui/radarr_ui/indexers/edit_indexer_ui_tests.rs b/src/ui/radarr_ui/indexers/edit_indexer_ui_tests.rs index 09b1c97..cec9ae6 100644 --- a/src/ui/radarr_ui/indexers/edit_indexer_ui_tests.rs +++ b/src/ui/radarr_ui/indexers/edit_indexer_ui_tests.rs @@ -1,10 +1,17 @@ #[cfg(test)] mod tests { - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; - use crate::ui::radarr_ui::indexers::edit_indexer_ui::EditIndexerUi; - use crate::ui::DrawUi; use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, + }; + use crate::models::servarr_models::Indexer; + use crate::ui::DrawUi; + use crate::ui::radarr_ui::indexers::edit_indexer_ui::EditIndexerUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; + #[test] fn test_edit_indexer_ui_accepts() { ActiveRadarrBlock::iter().for_each(|active_radarr_block| { @@ -15,4 +22,42 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_NZB_SELECTION_BLOCKS; + use crate::network::radarr_network::radarr_network_test_utils::test_utils::indexer; + + #[test] + fn test_edit_indexer_ui_renders_edit_indexer_modal_torrent() { + let mut app = App::test_default_fully_populated(); + app.data.radarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_TORRENT_SELECTION_BLOCKS); + app.push_navigation_stack(ActiveRadarrBlock::EditIndexerPrompt.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditIndexerUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_edit_indexer_ui_renders_edit_indexer_modal_usenet() { + let mut app = App::test_default_fully_populated(); + app.data.radarr_data.indexers.set_items(vec![Indexer { + protocol: "usenet".to_owned(), + ..indexer() + }]); + app.data.radarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_NZB_SELECTION_BLOCKS); + app.push_navigation_stack(ActiveRadarrBlock::EditIndexerPrompt.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditIndexerUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/indexers/indexer_settings_ui.rs b/src/ui/radarr_ui/indexers/indexer_settings_ui.rs index 1aa709c..677f17f 100644 --- a/src/ui/radarr_ui/indexers/indexer_settings_ui.rs +++ b/src/ui/radarr_ui/indexers/indexer_settings_ui.rs @@ -1,13 +1,13 @@ use std::sync::atomic::Ordering; -use ratatui::layout::{Constraint, Flex, Layout, Rect}; use ratatui::Frame; +use ratatui::layout::{Constraint, Flex, Layout, Rect}; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, }; -use crate::models::Route; use crate::render_selectable_input_box; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::title_block_centered; @@ -16,7 +16,7 @@ use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; #[cfg(test)] #[path = "indexer_settings_ui_tests.rs"] @@ -26,11 +26,10 @@ pub(super) struct IndexerSettingsUi; impl DrawUi for IndexerSettingsUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return INDEXER_SETTINGS_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + INDEXER_SETTINGS_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { @@ -62,21 +61,30 @@ fn draw_edit_indexer_settings_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Layout::horizontal([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)]) .margin(1) .areas(settings_area); - let [min_age_area, retention_area, max_size_area, prefer_flags_area] = Layout::vertical([ + let [ + min_age_area, + retention_area, + max_size_area, + prefer_flags_area, + ] = Layout::vertical([ Constraint::Length(3), Constraint::Length(3), Constraint::Length(3), Constraint::Length(3), ]) .areas(left_side_area); - let [availability_delay_area, rss_sync_interval_area, whitelisted_sub_tags_area, allow_hardcoded_subs_area] = - Layout::vertical([ - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - ]) - .areas(right_side_area); + let [ + availability_delay_area, + rss_sync_interval_area, + whitelisted_sub_tags_area, + allow_hardcoded_subs_area, + ] = Layout::vertical([ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + ]) + .areas(right_side_area); if let Route::Radarr(active_radarr_block, _) = app.get_current_route() { let min_age = indexer_settings.minimum_age.to_string(); diff --git a/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs b/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs index bef1814..f260225 100644 --- a/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs +++ b/src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::BlockSelectionState; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, + ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, }; - use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_indexer_settings_ui_accepts() { @@ -18,4 +21,22 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + + #[test] + fn test_indexer_settings_ui_renders_indexer_settings() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::IndexerSettingsMinimumAgeInput.into()); + app.data.radarr_data.selected_block = + BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexerSettingsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/indexers/indexers_ui_tests.rs b/src/ui/radarr_ui/indexers/indexers_ui_tests.rs index 4bf9eec..19193d3 100644 --- a/src/ui/radarr_ui/indexers/indexers_ui_tests.rs +++ b/src/ui/radarr_ui/indexers/indexers_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, EDIT_INDEXER_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, + ActiveRadarrBlock, EDIT_INDEXER_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXERS_BLOCKS, }; - use crate::ui::radarr_ui::indexers::IndexersUi; + use crate::models::stateful_table::StatefulTable; use crate::ui::DrawUi; + use crate::ui::radarr_ui::indexers::IndexersUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_indexers_ui_accepts() { @@ -24,4 +27,98 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + + #[test] + fn test_indexers_ui_renders_indexers_tab_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::Indexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_indexers_tab_empty_indexers() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::Indexers.into()); + app.data.radarr_data.indexers = StatefulTable::default(); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_indexers_tab() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::Indexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_test_indexer_loading() { + let mut app = App::test_default_fully_populated(); + app.data.radarr_data.indexer_test_errors = None; + app.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_test_indexer_success() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_test_indexer_error() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into()); + + app.data.radarr_data.indexer_test_errors = + Some("Connection timeout: Unable to reach indexer".to_owned()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_delete_indexer_prompt() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/indexers/mod.rs b/src/ui/radarr_ui/indexers/mod.rs index d1864a6..bc63c90 100644 --- a/src/ui/radarr_ui/indexers/mod.rs +++ b/src/ui/radarr_ui/indexers/mod.rs @@ -1,13 +1,14 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::Text; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, INDEXERS_BLOCKS}; use crate::models::servarr_models::Indexer; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::radarr_ui::indexers::edit_indexer_ui::EditIndexerUi; use crate::ui::radarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; use crate::ui::radarr_ui::indexers::test_all_indexers_ui::TestAllIndexersUi; @@ -18,7 +19,6 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; mod edit_indexer_ui; mod indexer_settings_ui; diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_indexer_modal_torrent.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_indexer_modal_torrent.snap new file mode 100644 index 0000000..b0b91ef --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_indexer_modal_torrent.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/radarr_ui/indexers/edit_indexer_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Name: │DrunkenSlug │ URL: │http://127.0.0.1:9696/1/ │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable RSS: │ ✔ │ API Key: │someApiKey │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Automatic Search: │ ✔ │ Seed Ratio: │ratio │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Interactive Search: │ ✔ │ Tags: │25 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭─────────────────────────╮ │ + │ Indexer Priority ▴▾: │1 │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_indexer_modal_usenet.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_indexer_modal_usenet.snap new file mode 100644 index 0000000..19ff9dc --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_indexer_modal_usenet.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/radarr_ui/indexers/edit_indexer_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Name: │DrunkenSlug │ URL: │http://127.0.0.1:9696/1/ │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable RSS: │ ✔ │ API Key: │someApiKey │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Automatic Search: │ ✔ │ Tags: │25 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Interactive Search: │ ✔ │ Indexer Priority ▴▾: │1 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexer_settings_ui__indexer_settings_ui_tests__tests__snapshot_tests__indexer_settings_ui_renders_indexer_settings.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexer_settings_ui__indexer_settings_ui_tests__tests__snapshot_tests__indexer_settings_ui_renders_indexer_settings.snap new file mode 100644 index 0000000..99424f6 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexer_settings_ui__indexer_settings_ui_tests__tests__snapshot_tests__indexer_settings_ui_renders_indexer_settings.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/radarr_ui/indexers/indexer_settings_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + ╭─────────────────────────────────────── Configure All Indexer Settings ────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Minimum Age (minutes) ▴▾: │12 │ Availability Delay (days) │0 │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Retention (days) ▴▾: │30 │ RSS Sync Interval (minutes│60 │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Maximum Size (MB) ▴▾: │1234 │ Whitelisted Subtitle Tags:│eng │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭───╮ │ + │ Prefer Indexer Flags: │ ✔ │ Allow Hardcoded Subs: │ ✔ │ │ + │ ╰───╯ ╰───╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_delete_indexer_prompt.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_delete_indexer_prompt.snap new file mode 100644 index 0000000..55337d7 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_delete_indexer_prompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer ▼ RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + ╭──────────────────── Delete Indexer ─────────────────────╮ + │ Do you really want to delete this indexer: │ + │ Test Indexer? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab.snap new file mode 100644 index 0000000..73ea7b5 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer ▼ RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab_empty_indexers.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab_empty_indexers.snap new file mode 100644 index 0000000..5581166 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab_empty_indexers.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab_loading.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab_loading.snap new file mode 100644 index 0000000..3ee5788 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_indexers_tab_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_error.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_error.snap new file mode 100644 index 0000000..de58ca2 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_error.snap @@ -0,0 +1,35 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer ▼ RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ Connection timeout: Unable to reach │ + │ indexer │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_loading.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_loading.snap new file mode 100644 index 0000000..ef6e02b --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_loading.snap @@ -0,0 +1,35 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer ▼ RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + + + + ╭ Testing Indexer ────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_success.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_success.snap new file mode 100644 index 0000000..ff3a0bd --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_indexer_success.snap @@ -0,0 +1,35 @@ +--- +source: src/ui/radarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer ▼ RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ error │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders_loading_state.snap b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders_loading_state.snap new file mode 100644 index 0000000..6048c73 --- /dev/null +++ b/src/ui/radarr_ui/indexers/snapshots/managarr__ui__radarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders_loading_state.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/indexers/test_all_indexers_ui_tests.rs +expression: output +--- + + + + + + + ╭ Test All Indexers ─────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs b/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs index 00b8b5d..c4ec021 100644 --- a/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs +++ b/src/ui/radarr_ui/indexers/test_all_indexers_ui.rs @@ -1,15 +1,15 @@ use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; -use crate::models::Route; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{get_width_from_percentage, title_block}; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; #[cfg(test)] #[path = "test_all_indexers_ui_tests.rs"] @@ -19,11 +19,10 @@ pub(super) struct TestAllIndexersUi; impl DrawUi for TestAllIndexersUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return active_radarr_block == ActiveRadarrBlock::TestAllIndexers; - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + active_radarr_block == ActiveRadarrBlock::TestAllIndexers } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { diff --git a/src/ui/radarr_ui/indexers/test_all_indexers_ui_tests.rs b/src/ui/radarr_ui/indexers/test_all_indexers_ui_tests.rs index 66ffea8..0c0c80e 100644 --- a/src/ui/radarr_ui/indexers/test_all_indexers_ui_tests.rs +++ b/src/ui/radarr_ui/indexers/test_all_indexers_ui_tests.rs @@ -2,9 +2,11 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; - use crate::ui::radarr_ui::indexers::test_all_indexers_ui::TestAllIndexersUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::indexers::test_all_indexers_ui::TestAllIndexersUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_test_all_indexers_ui_accepts() { @@ -16,4 +18,23 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + use super::*; + + #[test] + fn test_test_all_indexers_ui_renders_loading_state() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + TestAllIndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/library/add_movie_ui.rs b/src/ui/radarr_ui/library/add_movie_ui.rs index b28663d..65f27e4 100644 --- a/src/ui/radarr_ui/library/add_movie_ui.rs +++ b/src/ui/radarr_ui/library/add_movie_ui.rs @@ -1,13 +1,13 @@ use std::sync::atomic::Ordering; +use ratatui::Frame; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::widgets::{Cell, ListItem, Row}; -use ratatui::Frame; +use crate::models::Route; use crate::models::radarr_models::AddMovieSearchResult; use crate::models::servarr_data::radarr::modals::AddMovieModal; -use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; -use crate::models::Route; +use crate::models::servarr_data::radarr::radarr_data::{ADD_MOVIE_BLOCKS, ActiveRadarrBlock}; use crate::ui::radarr_ui::collections::CollectionsUi; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{ @@ -19,9 +19,9 @@ use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; use crate::utils::convert_runtime; -use crate::{render_selectable_input_box, App}; +use crate::{App, render_selectable_input_box}; #[cfg(test)] #[path = "add_movie_ui_tests.rs"] @@ -31,11 +31,10 @@ pub(super) struct AddMovieUi; impl DrawUi for AddMovieUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return ADD_MOVIE_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + ADD_MOVIE_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { @@ -81,13 +80,19 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { Layout::vertical([Constraint::Length(3), Constraint::Fill(0)]) .margin(1) .areas(area); - let block_content = &app.data.radarr_data.add_movie_search.as_ref().unwrap().text; + let block_content = &app + .data + .radarr_data + .add_movie_search + .as_ref() + .expect("add_movie_search must be populated") + .text; let offset = app .data .radarr_data .add_movie_search .as_ref() - .unwrap() + .expect("add_movie_search must be populated") .offset .load(Ordering::SeqCst); let search_results_row_mapping = |movie: &AddMovieSearchResult| { @@ -99,7 +104,7 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .unwrap_or_default() .value .as_f64() - .unwrap(); + .unwrap_or_default(); let rotten_tomatoes_rating = movie .ratings .rotten_tomatoes @@ -107,7 +112,7 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .unwrap_or_default() .value .as_u64() - .unwrap(); + .unwrap_or_default(); let imdb_rating = if imdb_rating == 0.0 { String::new() } else { @@ -261,7 +266,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .radarr_data .add_searched_movies .as_ref() - .unwrap() + .expect("add_searched_movies must be populated") .current_selection() .title .text, @@ -270,7 +275,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .radarr_data .add_searched_movies .as_ref() - .unwrap() + .expect("add_searched_movies must be populated") .current_selection() .overview .clone(), @@ -288,7 +293,12 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { root_folder_list, tags, .. - } = app.data.radarr_data.add_movie_modal.as_ref().unwrap(); + } = app + .data + .radarr_data + .add_movie_modal + .as_ref() + .expect("add_movie_modal must exist in this context"); let selected_monitor = monitor_list.current_selection(); let selected_minimum_availability = minimum_availability_list.current_selection(); @@ -297,19 +307,27 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { f.render_widget(title_block_centered(&title), area); - let [paragraph_area, root_folder_area, monitor_area, min_availability_area, quality_profile_area, tags_area, _, buttons_area] = - Layout::vertical([ - Constraint::Length(6), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Fill(1), - Constraint::Length(3), - ]) - .margin(1) - .areas(area); + let [ + paragraph_area, + root_folder_area, + monitor_area, + min_availability_area, + quality_profile_area, + tags_area, + _, + buttons_area, + ] = Layout::vertical([ + Constraint::Length(6), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) + .margin(1) + .areas(area); let prompt_paragraph = layout_paragraph_borderless(&prompt); f.render_widget(prompt_paragraph, paragraph_area); @@ -371,7 +389,7 @@ fn draw_add_movie_select_monitor_popup(f: &mut Frame<'_>, app: &mut App<'_>) { .radarr_data .add_movie_modal .as_mut() - .unwrap() + .expect("add_movie_modal must exist in this context") .monitor_list, |monitor| ListItem::new(monitor.to_display_str().to_owned()), ); @@ -387,7 +405,7 @@ fn draw_add_movie_select_minimum_availability_popup(f: &mut Frame<'_>, app: &mut .radarr_data .add_movie_modal .as_mut() - .unwrap() + .expect("add_movie_modal must exist in this context") .minimum_availability_list, |minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()), ); @@ -403,7 +421,7 @@ fn draw_add_movie_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App< .radarr_data .add_movie_modal .as_mut() - .unwrap() + .expect("add_movie_modal must exist in this context") .quality_profile_list, |quality_profile| ListItem::new(quality_profile.clone()), ); @@ -419,7 +437,7 @@ fn draw_add_movie_select_root_folder_popup(f: &mut Frame<'_>, app: &mut App<'_>) .radarr_data .add_movie_modal .as_mut() - .unwrap() + .expect("add_movie_modal must exist in this context") .root_folder_list, |root_folder| ListItem::new(root_folder.path.to_owned()), ); diff --git a/src/ui/radarr_ui/library/add_movie_ui_tests.rs b/src/ui/radarr_ui/library/add_movie_ui_tests.rs index ff24d30..749bd2e 100644 --- a/src/ui/radarr_ui/library/add_movie_ui_tests.rs +++ b/src/ui/radarr_ui/library/add_movie_ui_tests.rs @@ -2,9 +2,11 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ADD_MOVIE_BLOCKS}; - use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi; + use crate::app::App; + use crate::models::servarr_data::radarr::radarr_data::{ADD_MOVIE_BLOCKS, ActiveRadarrBlock}; use crate::ui::DrawUi; + use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_add_movie_ui_accepts() { @@ -16,4 +18,85 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::ADD_MOVIE_SELECTION_BLOCKS; + use rstest::rstest; + + #[test] + fn test_add_movie_ui_renders_loading_for_search() { + let mut app = App::test_default_fully_populated(); + app.data.radarr_data.add_searched_movies = None; + app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AddMovieUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + #[case(ActiveRadarrBlock::AddMovieSearchInput, None)] + #[case(ActiveRadarrBlock::AddMovieSearchResults, None)] + #[case(ActiveRadarrBlock::AddMovieEmptySearchResults, None)] + #[case(ActiveRadarrBlock::AddMoviePrompt, None)] + #[case(ActiveRadarrBlock::AddMovieSelectMinimumAvailability, None)] + #[case(ActiveRadarrBlock::AddMovieSelectMonitor, None)] + #[case(ActiveRadarrBlock::AddMovieSelectQualityProfile, None)] + #[case(ActiveRadarrBlock::AddMovieSelectRootFolder, None)] + #[case(ActiveRadarrBlock::AddMovieAlreadyInLibrary, None)] + #[case(ActiveRadarrBlock::AddMovieTagsInput, None)] + #[case( + ActiveRadarrBlock::AddMoviePrompt, + Some(ActiveRadarrBlock::CollectionDetails) + )] + #[case( + ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + Some(ActiveRadarrBlock::CollectionDetails) + )] + #[case( + ActiveRadarrBlock::AddMovieSelectMonitor, + Some(ActiveRadarrBlock::CollectionDetails) + )] + #[case( + ActiveRadarrBlock::AddMovieSelectQualityProfile, + Some(ActiveRadarrBlock::CollectionDetails) + )] + #[case( + ActiveRadarrBlock::AddMovieSelectRootFolder, + Some(ActiveRadarrBlock::CollectionDetails) + )] + #[case( + ActiveRadarrBlock::AddMovieTagsInput, + Some(ActiveRadarrBlock::CollectionDetails) + )] + fn test_add_movie_ui_renders( + #[case] active_radarr_block: ActiveRadarrBlock, + #[case] context: Option, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack((active_radarr_block, context).into()); + app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AddMovieUi::draw(f, app, f.area()); + }); + + if let Some(context) = context { + insta::assert_snapshot!( + format!( + "{}_{}", + active_radarr_block.to_string(), + context.to_string() + ), + output + ); + } else { + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + } + } } diff --git a/src/ui/radarr_ui/library/delete_movie_ui.rs b/src/ui/radarr_ui/library/delete_movie_ui.rs index 9a338da..d750477 100644 --- a/src/ui/radarr_ui/library/delete_movie_ui.rs +++ b/src/ui/radarr_ui/library/delete_movie_ui.rs @@ -1,13 +1,13 @@ -use ratatui::layout::Rect; use ratatui::Frame; +use ratatui::layout::Rect; use crate::app::App; -use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; use crate::models::Route; +use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; +use crate::ui::DrawUi; use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; #[cfg(test)] #[path = "delete_movie_ui_tests.rs"] @@ -17,11 +17,10 @@ pub(super) struct DeleteMovieUi; impl DrawUi for DeleteMovieUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return DELETE_MOVIE_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + DELETE_MOVIE_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { diff --git a/src/ui/radarr_ui/library/delete_movie_ui_tests.rs b/src/ui/radarr_ui/library/delete_movie_ui_tests.rs index 625ce88..bd2ea87 100644 --- a/src/ui/radarr_ui/library/delete_movie_ui_tests.rs +++ b/src/ui/radarr_ui/library/delete_movie_ui_tests.rs @@ -2,9 +2,14 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS}; - use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, DELETE_MOVIE_BLOCKS, DELETE_MOVIE_SELECTION_BLOCKS, + }; use crate::ui::DrawUi; + use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_delete_movie_ui_accepts() { @@ -16,4 +21,21 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + + #[test] + fn test_delete_movie_ui_renders_delete_movie_prompt() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into()); + app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DeleteMovieUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/library/edit_movie_ui.rs b/src/ui/radarr_ui/library/edit_movie_ui.rs index bc2a8c6..f944e81 100644 --- a/src/ui/radarr_ui/library/edit_movie_ui.rs +++ b/src/ui/radarr_ui/library/edit_movie_ui.rs @@ -1,16 +1,16 @@ use std::sync::atomic::Ordering; +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::prelude::Layout; use ratatui::widgets::ListItem; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::radarr::modals::EditMovieModal; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, EDIT_MOVIE_BLOCKS, MOVIE_DETAILS_BLOCKS, }; -use crate::models::Route; use crate::render_selectable_input_box; use crate::ui::radarr_ui::library::movie_details_ui::MovieDetailsUi; @@ -21,7 +21,7 @@ use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; #[cfg(test)] #[path = "edit_movie_ui_tests.rs"] @@ -31,19 +31,18 @@ pub(super) struct EditMovieUi; impl DrawUi for EditMovieUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return EDIT_MOVIE_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + EDIT_MOVIE_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { if let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() { - if let Some(context) = context_option { - if MOVIE_DETAILS_BLOCKS.contains(&context) { - draw_popup(f, app, MovieDetailsUi::draw, Size::Large); - } + if let Some(context) = context_option + && MOVIE_DETAILS_BLOCKS.contains(&context) + { + draw_popup(f, app, MovieDetailsUi::draw, Size::Large); } draw_popup(f, app, draw_edit_movie_confirmation_prompt, Size::Medium); @@ -88,23 +87,36 @@ fn draw_edit_movie_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, are monitored, path, tags, - } = app.data.radarr_data.edit_movie_modal.as_ref().unwrap(); + } = app + .data + .radarr_data + .edit_movie_modal + .as_ref() + .expect("edit_movie_modal must exist in this context"); let selected_minimum_availability = minimum_availability_list.current_selection(); let selected_quality_profile = quality_profile_list.current_selection(); - let [paragraph_area, monitored_area, min_availability_area, quality_profile_area, path_area, tags_area, _, buttons_area] = - Layout::vertical([ - Constraint::Length(6), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Fill(1), - Constraint::Length(3), - ]) - .margin(1) - .areas(area); + let [ + paragraph_area, + monitored_area, + min_availability_area, + quality_profile_area, + path_area, + tags_area, + _, + buttons_area, + ] = Layout::vertical([ + Constraint::Length(6), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) + .margin(1) + .areas(area); let [save_area, cancel_area] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .areas(buttons_area); @@ -168,7 +180,7 @@ fn draw_edit_movie_select_minimum_availability_popup(f: &mut Frame<'_>, app: &mu .radarr_data .edit_movie_modal .as_mut() - .unwrap() + .expect("edit_movie_modal must exist in this context") .minimum_availability_list, |minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()), ); @@ -184,7 +196,7 @@ fn draw_edit_movie_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App .radarr_data .edit_movie_modal .as_mut() - .unwrap() + .expect("edit_movie_modal must exist in this context") .quality_profile_list, |quality_profile| ListItem::new(quality_profile.clone()), ); diff --git a/src/ui/radarr_ui/library/edit_movie_ui_tests.rs b/src/ui/radarr_ui/library/edit_movie_ui_tests.rs index ccaf1ac..8d9993f 100644 --- a/src/ui/radarr_ui/library/edit_movie_ui_tests.rs +++ b/src/ui/radarr_ui/library/edit_movie_ui_tests.rs @@ -2,9 +2,14 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS}; - use crate::ui::radarr_ui::library::edit_movie_ui::EditMovieUi; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::{ + ActiveRadarrBlock, EDIT_MOVIE_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, + }; use crate::ui::DrawUi; + use crate::ui::radarr_ui::library::edit_movie_ui::EditMovieUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_edit_movie_ui_accepts() { @@ -16,4 +21,63 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case(ActiveRadarrBlock::EditMoviePrompt, None, 0)] + #[case( + ActiveRadarrBlock::EditMoviePrompt, + Some(ActiveRadarrBlock::MovieDetails), + 0 + )] + #[case( + ActiveRadarrBlock::EditMoviePrompt, + Some(ActiveRadarrBlock::MovieHistory), + 1 + )] + #[case( + ActiveRadarrBlock::EditMoviePrompt, + Some(ActiveRadarrBlock::FileInfo), + 2 + )] + #[case(ActiveRadarrBlock::EditMoviePrompt, Some(ActiveRadarrBlock::Cast), 3)] + #[case(ActiveRadarrBlock::EditMoviePrompt, Some(ActiveRadarrBlock::Crew), 4)] + #[case( + ActiveRadarrBlock::EditMoviePrompt, + Some(ActiveRadarrBlock::ManualSearch), + 5 + )] + fn test_edit_movie_ui_renders_edit_movie_modal( + #[case] active_radarr_block: ActiveRadarrBlock, + #[case] context: Option, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack((active_radarr_block, context).into()); + if context.is_some() { + app.data.radarr_data.movie_info_tabs.set_index(index); + } + app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditMovieUi::draw(f, app, f.area()); + }); + + if let Some(context) = context { + insta::assert_snapshot!( + format!( + "{}_{}", + active_radarr_block.to_string(), + context.to_string() + ), + output + ); + } else { + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + } + } } diff --git a/src/ui/radarr_ui/library/library_ui_tests.rs b/src/ui/radarr_ui/library/library_ui_tests.rs index 357def9..629c955 100644 --- a/src/ui/radarr_ui/library/library_ui_tests.rs +++ b/src/ui/radarr_ui/library/library_ui_tests.rs @@ -2,12 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ - ActiveRadarrBlock, ADD_MOVIE_BLOCKS, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS, + ADD_MOVIE_BLOCKS, ActiveRadarrBlock, DELETE_MOVIE_BLOCKS, EDIT_MOVIE_BLOCKS, LIBRARY_BLOCKS, MOVIE_DETAILS_BLOCKS, }; - use crate::ui::radarr_ui::library::LibraryUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::library::LibraryUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_library_ui_accepts() { @@ -26,4 +28,101 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::radarr::radarr_data::{ + ADD_MOVIE_SELECTION_BLOCKS, EDIT_MOVIE_SELECTION_BLOCKS, + }; + use rstest::rstest; + + #[test] + fn test_library_ui_renders_library_tab_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_library_tab_empty_movies() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_library_ui_renders_library_tab( + #[values( + ActiveRadarrBlock::Movies, + ActiveRadarrBlock::MoviesSortPrompt, + ActiveRadarrBlock::SearchMovie, + ActiveRadarrBlock::SearchMovieError, + ActiveRadarrBlock::FilterMovies, + ActiveRadarrBlock::FilterMoviesError, + ActiveRadarrBlock::UpdateAllMoviesPrompt + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("library_tab_{active_radarr_block}"), output); + } + + #[rstest] + fn test_library_movie_ui_renders_add_movie_ui( + #[values( + ActiveRadarrBlock::AddMovieSearchInput, + ActiveRadarrBlock::AddMovieSearchResults, + ActiveRadarrBlock::AddMovieEmptySearchResults, + ActiveRadarrBlock::AddMoviePrompt, + ActiveRadarrBlock::AddMovieSelectMinimumAvailability, + ActiveRadarrBlock::AddMovieSelectMonitor, + ActiveRadarrBlock::AddMovieSelectQualityProfile, + ActiveRadarrBlock::AddMovieSelectRootFolder, + ActiveRadarrBlock::AddMovieAlreadyInLibrary, + ActiveRadarrBlock::AddMovieTagsInput + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("add_movie_ui_{active_radarr_block}"), output); + } + + #[test] + fn test_edit_movie_ui_renders_edit_movie_modal() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into()); + app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/library/mod.rs b/src/ui/radarr_ui/library/mod.rs index ddf8697..7260837 100644 --- a/src/ui/radarr_ui/library/mod.rs +++ b/src/ui/radarr_ui/library/mod.rs @@ -1,11 +1,12 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::radarr_models::Movie; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, LIBRARY_BLOCKS}; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::radarr_ui::decorate_with_row_style; use crate::ui::radarr_ui::library::add_movie_ui::AddMovieUi; use crate::ui::radarr_ui::library::delete_movie_ui::DeleteMovieUi; @@ -15,7 +16,6 @@ use crate::ui::utils::{get_width_from_percentage, layout_block_top_border}; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; use crate::utils::{convert_runtime, convert_to_gb}; mod add_movie_ui; @@ -99,24 +99,17 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { let certification = movie.certification.clone().unwrap_or_default(); let quality_profile = quality_profile_map .get_by_left(&movie.quality_profile_id) - .unwrap() + .expect("Quality profile ID must exist in quality_profile_map") .to_owned(); - let empty_tag = String::new(); - let tags = if !movie.tags.is_empty() { - movie - .tags - .iter() - .map(|tag_id| { - tags_map - .get_by_left(&tag_id.as_i64().unwrap()) - .unwrap_or(&empty_tag) - .clone() - }) - .collect::>() - .join(", ") - } else { - String::new() - }; + let tags = movie + .tags + .iter() + .filter_map(|tag_id| { + let id = tag_id.as_i64()?; + tags_map.get_by_left(&id).cloned() + }) + .collect::>() + .join(", "); decorate_with_row_style( downloads_vec, diff --git a/src/ui/radarr_ui/library/movie_details_ui.rs b/src/ui/radarr_ui/library/movie_details_ui.rs index 38ef583..bdc2566 100644 --- a/src/ui/radarr_ui/library/movie_details_ui.rs +++ b/src/ui/radarr_ui/library/movie_details_ui.rs @@ -1,17 +1,17 @@ use std::iter; +use ratatui::Frame; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::{Line, Span, Text}; use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; -use ratatui::Frame; use serde_json::Number; use crate::app::App; +use crate::models::Route; use crate::models::radarr_models::{Credit, MovieHistoryItem, RadarrRelease}; use crate::models::servarr_data::radarr::modals::MovieDetailsModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; -use crate::models::Route; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{ borderless_block, decorate_peer_style, get_width_from_percentage, layout_block_bottom_border, @@ -21,7 +21,7 @@ use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::{draw_popup, draw_tabs, DrawUi}; +use crate::ui::{DrawUi, draw_popup, draw_tabs}; use crate::utils::convert_to_gb; #[cfg(test)] @@ -32,11 +32,10 @@ pub(super) struct MovieDetailsUi; impl DrawUi for MovieDetailsUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { @@ -117,16 +116,22 @@ fn draw_file_info(f: &mut Frame<'_>, app: &App<'_>, area: Rect) { let file_info = movie_details_modal.file_details.to_owned(); let audio_details = movie_details_modal.audio_details.to_owned(); let video_details = movie_details_modal.video_details.to_owned(); - let [file_details_title_area, file_details_area, audio_details_title_area, audio_details_area, video_details_title_area, video_details_area] = - Layout::vertical([ - Constraint::Length(2), - Constraint::Length(5), - Constraint::Length(1), - Constraint::Length(6), - Constraint::Length(1), - Constraint::Length(7), - ]) - .areas(area); + let [ + file_details_title_area, + file_details_area, + audio_details_title_area, + audio_details_area, + video_details_title_area, + video_details_area, + ] = Layout::vertical([ + Constraint::Length(2), + Constraint::Length(5), + Constraint::Length(1), + Constraint::Length(6), + Constraint::Length(1), + Constraint::Length(7), + ]) + .areas(area); let file_details_title_paragraph = Paragraph::new("File Details".bold()).block(layout_block_top_border()); @@ -404,12 +409,12 @@ fn draw_movie_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .clone() .unwrap_or(Number::from(0u64)) .as_u64() - .unwrap(); + .unwrap_or_default(); let leechers = leechers .clone() .unwrap_or(Number::from(0u64)) .as_u64() - .unwrap(); + .unwrap_or_default(); decorate_peer_style( seeders, @@ -467,7 +472,7 @@ fn draw_manual_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_>) { .radarr_data .movie_details_modal .as_ref() - .unwrap() + .expect("movie_details_modal must exist in this context") .movie_releases .current_selection(); let title = if current_selection.rejected { diff --git a/src/ui/radarr_ui/library/movie_details_ui_tests.rs b/src/ui/radarr_ui/library/movie_details_ui_tests.rs index 9d99d6f..46e8417 100644 --- a/src/ui/radarr_ui/library/movie_details_ui_tests.rs +++ b/src/ui/radarr_ui/library/movie_details_ui_tests.rs @@ -5,12 +5,14 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS}; + use crate::ui::DrawUi; use crate::ui::radarr_ui::library::movie_details_ui::{ - style_from_download_status, MovieDetailsUi, + MovieDetailsUi, style_from_download_status, }; use crate::ui::styles::ManagarrStyle; - use crate::ui::DrawUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_movie_details_ui_accepts() { @@ -42,4 +44,129 @@ mod tests { expected_style ); } + + mod snapshot_tests { + use super::*; + + #[rstest] + #[case(ActiveRadarrBlock::MovieDetails, None, 0)] + #[case( + ActiveRadarrBlock::MovieDetails, + Some(ActiveRadarrBlock::AutomaticallySearchMoviePrompt), + 0 + )] + #[case( + ActiveRadarrBlock::MovieDetails, + Some(ActiveRadarrBlock::UpdateAndScanPrompt), + 0 + )] + #[case(ActiveRadarrBlock::MovieHistory, None, 1)] + #[case( + ActiveRadarrBlock::MovieHistory, + Some(ActiveRadarrBlock::AutomaticallySearchMoviePrompt), + 1 + )] + #[case( + ActiveRadarrBlock::MovieHistory, + Some(ActiveRadarrBlock::UpdateAndScanPrompt), + 1 + )] + #[case(ActiveRadarrBlock::FileInfo, None, 2)] + #[case( + ActiveRadarrBlock::FileInfo, + Some(ActiveRadarrBlock::AutomaticallySearchMoviePrompt), + 2 + )] + #[case( + ActiveRadarrBlock::FileInfo, + Some(ActiveRadarrBlock::UpdateAndScanPrompt), + 2 + )] + #[case(ActiveRadarrBlock::Cast, None, 3)] + #[case( + ActiveRadarrBlock::Cast, + Some(ActiveRadarrBlock::AutomaticallySearchMoviePrompt), + 3 + )] + #[case( + ActiveRadarrBlock::Cast, + Some(ActiveRadarrBlock::UpdateAndScanPrompt), + 3 + )] + #[case(ActiveRadarrBlock::Crew, None, 4)] + #[case( + ActiveRadarrBlock::Crew, + Some(ActiveRadarrBlock::AutomaticallySearchMoviePrompt), + 4 + )] + #[case( + ActiveRadarrBlock::Crew, + Some(ActiveRadarrBlock::UpdateAndScanPrompt), + 4 + )] + #[case(ActiveRadarrBlock::ManualSearch, None, 5)] + #[case( + ActiveRadarrBlock::ManualSearch, + Some(ActiveRadarrBlock::AutomaticallySearchMoviePrompt), + 5 + )] + #[case( + ActiveRadarrBlock::ManualSearch, + Some(ActiveRadarrBlock::UpdateAndScanPrompt), + 5 + )] + #[case(ActiveRadarrBlock::ManualSearchSortPrompt, None, 5)] + #[case(ActiveRadarrBlock::ManualSearchConfirmPrompt, None, 5)] + fn test_movie_details_ui_renders_movie_details_tab( + #[case] active_radarr_block: ActiveRadarrBlock, + #[case] context: Option, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack((active_radarr_block, context).into()); + app.data.radarr_data.movie_info_tabs.set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + MovieDetailsUi::draw(f, app, f.area()); + }); + + if let Some(context) = context { + insta::assert_snapshot!( + format!("movie_details_render_{active_radarr_block}_{context}"), + output + ); + } else { + insta::assert_snapshot!( + format!("movie_details_render_{active_radarr_block}"), + output + ); + } + } + + #[rstest] + fn test_movie_details_ui_renders_movie_details_tabs_loading( + #[values( + ActiveRadarrBlock::MovieDetails, + ActiveRadarrBlock::MovieHistory, + ActiveRadarrBlock::FileInfo, + ActiveRadarrBlock::Cast, + ActiveRadarrBlock::Crew, + ActiveRadarrBlock::ManualSearch + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + MovieDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("movie_details_loading_{active_radarr_block}"), + output + ); + } + } } diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieAlreadyInLibrary.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieAlreadyInLibrary.snap new file mode 100644 index 0000000..b6af07b --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieAlreadyInLibrary.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ✔ Title Year Runtime IMDB Rotten Tomatoes Genres │ + │=> ✔ Test 2023 2h 0m 9.9 99% cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Error ───────────────╮ │ + │ │ This film is already in your library │ │ + │ │ │ │ + │ ╰───────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieEmptySearchResults.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieEmptySearchResults.snap new file mode 100644 index 0000000..4a28d65 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieEmptySearchResults.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Error ───────────────╮ │ + │ │ No movies found matching your query! │ │ + │ │ │ │ + │ ╰───────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMoviePrompt.snap new file mode 100644 index 0000000..f83fa58 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMoviePrompt.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Monitor: │Movie only ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMoviePrompt_CollectionDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMoviePrompt_CollectionDetails.snap new file mode 100644 index 0000000..ae1d243 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMoviePrompt_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭────────────────────────────────────────────╮ │ │ + │=> ✔ Test │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Monitor: │Movie only ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSearchInput.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSearchInput.snap new file mode 100644 index 0000000..8428963 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSearchInput.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSearchResults.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSearchResults.snap new file mode 100644 index 0000000..7671ced --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSearchResults.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ✔ Title Year Runtime IMDB Rotten Tomatoes Genres │ + │=> ✔ Test 2023 2h 0m 9.9 99% cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMinimumAvailability.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMinimumAvailability.snap new file mode 100644 index 0000000..595503e --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMinimumAvailability.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │Announced │───────────────────────────╯ │ │ + │ │ │In Cinemas │───────────────────────────╮ │ │ + │ │ │Released │ ▼ │ │ │ + │ │ │TBA │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMinimumAvailability_CollectionDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMinimumAvailability_CollectionDetails.snap new file mode 100644 index 0000000..dfb9281 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMinimumAvailability_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭────────────────────────────────────────────╮ │ │ + │=> ✔ Test │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │Announced │───────────────────────────╯ │ │ + │ │ │In Cinemas │───────────────────────────╮ │ │ + │ │ │Released │ ▼ │ │ │ + │ │ │TBA │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMonitor.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMonitor.snap new file mode 100644 index 0000000..c04622f --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMonitor.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │Movie only │───────────────────────────╯ │ │ + │ │ │Movie and Collection │───────────────────────────╮ │ │ + │ │ │None │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMonitor_CollectionDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMonitor_CollectionDetails.snap new file mode 100644 index 0000000..50f15fe --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectMonitor_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭────────────────────────────────────────────╮ │ │ + │=> ✔ Test │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │Movie only │───────────────────────────╯ │ │ + │ │ │Movie and Collection │───────────────────────────╮ │ │ + │ │ │None │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectQualityProfile.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectQualityProfile.snap new file mode 100644 index 0000000..0080f13 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectQualityProfile.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │HD - 1080p │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectQualityProfile_CollectionDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectQualityProfile_CollectionDetails.snap new file mode 100644 index 0000000..4c3ee66 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectQualityProfile_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭────────────────────────────────────────────╮ │ │ + │=> ✔ Test │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │HD - 1080p │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectRootFolder.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectRootFolder.snap new file mode 100644 index 0000000..b77bab8 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectRootFolder.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │/nfs │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectRootFolder_CollectionDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectRootFolder_CollectionDetails.snap new file mode 100644 index 0000000..23dfbaa --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieSelectRootFolder_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭────────────────────────────────────────────╮ │ │ + │=> ✔ Test │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │/nfs │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieTagsInput.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieTagsInput.snap new file mode 100644 index 0000000..f83fa58 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieTagsInput.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Monitor: │Movie only ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieTagsInput_CollectionDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieTagsInput_CollectionDetails.snap new file mode 100644 index 0000000..ae1d243 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__AddMovieTagsInput_CollectionDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored +=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 + + + + ╭ Test Collection ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Overview: Collection blah blah blah │ + │Root Folder Path: /nfs/movies │ + │Quality Profile: HD - 1080p │ + │Minimum Avai╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮ │ + │Monitored: Y│ Collection blah blah blah │ │ + │Search on Ad│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ Movies ──│ │───────────│ + │ ✔ Title │ ╭────────────────────────────────────────────╮ │ │ + │=> ✔ Test │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Monitor: │Movie only ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__add_movie_ui_renders_loading_for_search.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__add_movie_ui_renders_loading_for_search.snap new file mode 100644 index 0000000..6320160 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__add_movie_ui__add_movie_ui_tests__tests__snapshot_tests__add_movie_ui_renders_loading_for_search.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/add_movie_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__delete_movie_ui__delete_movie_ui_tests__tests__snapshot_tests__delete_movie_ui_renders_delete_movie_prompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__delete_movie_ui__delete_movie_ui_tests__tests__snapshot_tests__delete_movie_ui_renders_delete_movie_prompt.snap new file mode 100644 index 0000000..3ba597b --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__delete_movie_ui__delete_movie_ui_tests__tests__snapshot_tests__delete_movie_ui_renders_delete_movie_prompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/library/delete_movie_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + + + + ╭───────────────────── Delete Movie ──────────────────────╮ + │ Do you really want to delete: │ + │ Test? │ + │ │ + │ │ + │ ╭───╮ │ + │ Delete Movie File: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Add List Exclusion: │ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt.snap new file mode 100644 index 0000000..8874f88 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Path: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_Cast.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_Cast.snap new file mode 100644 index 0000000..06800a3 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_Cast.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Cast Member Character │ + │=> Madison C╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮ │ + │ │ Blah blah blah │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭───╮ │ │ + │ │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Path: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_Crew.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_Crew.snap new file mode 100644 index 0000000..0c332b8 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_Crew.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Crew Member Job Department │ + │=> Alex Clar╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮ │ + │ │ Blah blah blah │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭───╮ │ │ + │ │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Path: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_FileInfo.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_FileInfo.snap new file mode 100644 index 0000000..ce57b14 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_FileInfo.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │File Details │ + │Some file in╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮ │ + │ │ Blah blah blah │ │ + │ │ │ │ + │ │ │ │ + │────────────│ │───────────│ + │Audio Detail│ │ │ + │Some audio i│ │ │ + │ │ ╭───╮ │ │ + │ │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │────────────│ Minimum Availability: │Announced ▼ │ │───────────│ + │Video Detail│ ╰────────────────────────────────────────────╯ │ │ + │Some video i│ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Path: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_ManualSearch.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_ManualSearch.snap new file mode 100644 index 0000000..af0e450 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_ManualSearch.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent ╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮D - 1080p │ + │ usenet │ Blah blah blah │D - 1080p │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭───╮ │ │ + │ │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Path: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_MovieDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_MovieDetails.snap new file mode 100644 index 0000000..435e0a1 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_MovieDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Some information: │ + │ ╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮ │ + │ │ Blah blah blah │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭───╮ │ │ + │ │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Path: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_MovieHistory.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_MovieHistory.snap new file mode 100644 index 0000000..2c38e79 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__edit_movie_ui__edit_movie_ui_tests__tests__snapshot_tests__EditMoviePrompt_MovieHistory.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/edit_movie_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Languages Quality Date │ + │=> Test ╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮37:56 UTC │ + │ │ Blah blah blah │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭───╮ │ │ + │ │ Monitored: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Path: │/nfs/movies │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Save ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieAlreadyInLibrary.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieAlreadyInLibrary.snap new file mode 100644 index 0000000..8bd5d6f --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieAlreadyInLibrary.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ✔ Title Year Runtime IMDB Rotten Tomatoes Genres │ + │=> ✔ Test 2023 2h 0m 9.9 99% cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Error ───────────────╮ │ + │ │ This film is already in your library │ │ + │ │ │ │ + │ ╰───────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieEmptySearchResults.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieEmptySearchResults.snap new file mode 100644 index 0000000..ac375b8 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieEmptySearchResults.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Error ───────────────╮ │ + │ │ No movies found matching your query! │ │ + │ │ │ │ + │ ╰───────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMoviePrompt.snap new file mode 100644 index 0000000..208d025 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMoviePrompt.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Monitor: │Movie only ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSearchInput.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSearchInput.snap new file mode 100644 index 0000000..2229ca0 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSearchInput.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSearchResults.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSearchResults.snap new file mode 100644 index 0000000..c2e106c --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSearchResults.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ✔ Title Year Runtime IMDB Rotten Tomatoes Genres │ + │=> ✔ Test 2023 2h 0m 9.9 99% cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectMinimumAvailability.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectMinimumAvailability.snap new file mode 100644 index 0000000..b472953 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectMinimumAvailability.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │Announced │───────────────────────────╯ │ │ + │ │ │In Cinemas │───────────────────────────╮ │ │ + │ │ │Released │ ▼ │ │ │ + │ │ │TBA │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectMonitor.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectMonitor.snap new file mode 100644 index 0000000..5a454f3 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectMonitor.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │Movie only │───────────────────────────╯ │ │ + │ │ │Movie and Collection │───────────────────────────╮ │ │ + │ │ │None │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectQualityProfile.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectQualityProfile.snap new file mode 100644 index 0000000..c4963ff --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectQualityProfile.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │HD - 1080p │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectRootFolder.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectRootFolder.snap new file mode 100644 index 0000000..5bacaa4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieSelectRootFolder.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ ╭───────────────────────────────╮ ▼ │ │ │ + │ │ │/nfs │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Minimum│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ Qu│ │ ▼ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ │ │───────────────────────────╮ │ │ + │ │ │ │ │ │ │ + │ │ │ │───────────────────────────╯ │ │ + │ │ ╰───────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieTagsInput.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieTagsInput.snap new file mode 100644 index 0000000..208d025 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__add_movie_ui_AddMovieTagsInput.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + ╭───────────────────────────────────────────────────── Add Movie ──────────────────────────────────────────────────────╮ + │test │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭───────────╭────────────────────────────────────── Add Movie - Test ───────────────────────────────────────╮──────────╮ + │ ✔ Title│ New movie blah blah blah │ │ + │=> ✔ Test │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Monitor: │Movie only ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Minimum Availability: │Announced ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │HD - 1080p ▼ │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ ╭────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + │ │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ │ + │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__edit_movie_ui_renders_edit_movie_modal.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__edit_movie_ui_renders_edit_movie_modal.snap new file mode 100644 index 0000000..d2e591e --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__edit_movie_ui_renders_edit_movie_modal.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + ╭───────────────────────────────────────── Edit - Test ─────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Minimum Availability: │Announced ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Quality Profile: │HD - 1080p ▼ │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Path: │/nfs/movies │ │ + │ ╰────────────────────────────────────────────╯ │ + │ ╭────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────╮╭──────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────╯╰──────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_FilterMovies.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_FilterMovies.snap new file mode 100644 index 0000000..aa620d1 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_FilterMovies.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + + + + + + + + + + + + ╭───────────────── Filter ──────────────────╮ + │Something │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_FilterMoviesError.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_FilterMoviesError.snap new file mode 100644 index 0000000..c2d8b10 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_FilterMoviesError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │The given filter produced empty results│ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_Movies.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_Movies.snap new file mode 100644 index 0000000..850efb6 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_Movies.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_MoviesSortPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_MoviesSortPrompt.snap new file mode 100644 index 0000000..9ac5508 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_MoviesSortPrompt.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + + + + ╭───────────────────────────────╮ + │Something │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_SearchMovie.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_SearchMovie.snap new file mode 100644 index 0000000..487fd86 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_SearchMovie.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + + + + + + + + + + + + ╭───────────────── Search ──────────────────╮ + │Something │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_SearchMovieError.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_SearchMovieError.snap new file mode 100644 index 0000000..9948477 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_SearchMovieError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ No items found matching search │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_UpdateAllMoviesPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_UpdateAllMoviesPrompt.snap new file mode 100644 index 0000000..6c1632f --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_tab_UpdateAllMoviesPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags +=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex + + + + + + + + + + + + + + ╭─────────────────── Update All Movies ───────────────────╮ + │ Do you want to update info and scan your disks for all of │ + │ your movies? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_library_tab_empty_movies.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_library_tab_empty_movies.snap new file mode 100644 index 0000000..e54ebef --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_library_tab_empty_movies.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_library_tab_loading.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_library_tab_loading.snap new file mode 100644 index 0000000..3c01f11 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_library_tab_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_Cast.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_Cast.snap new file mode 100644 index 0000000..d385ec4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_Cast.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_Crew.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_Crew.snap new file mode 100644 index 0000000..d385ec4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_Crew.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_FileInfo.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_FileInfo.snap new file mode 100644 index 0000000..d385ec4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_FileInfo.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_ManualSearch.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_ManualSearch.snap new file mode 100644 index 0000000..d385ec4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_ManualSearch.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_MovieDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_MovieDetails.snap new file mode 100644 index 0000000..d385ec4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_MovieDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_MovieHistory.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_MovieHistory.snap new file mode 100644 index 0000000..d385ec4 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_loading_MovieHistory.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast.snap new file mode 100644 index 0000000..4885012 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Cast Member Character │ + │=> Madison Clarke Johnny Blaze │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast_AutomaticallySearchMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast_AutomaticallySearchMoviePrompt.snap new file mode 100644 index 0000000..e0b6a1d --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast_AutomaticallySearchMoviePrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Cast Member Character │ + │=> Madison Clarke Johnny Blaze │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Movie Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast_UpdateAndScanPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast_UpdateAndScanPrompt.snap new file mode 100644 index 0000000..ff7fce1 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Cast_UpdateAndScanPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Cast Member Character │ + │=> Madison Clarke Johnny Blaze │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew.snap new file mode 100644 index 0000000..807de9b --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Crew Member Job Department │ + │=> Alex Clarke Composition Music │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew_AutomaticallySearchMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew_AutomaticallySearchMoviePrompt.snap new file mode 100644 index 0000000..8c6518d --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew_AutomaticallySearchMoviePrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Crew Member Job Department │ + │=> Alex Clarke Composition Music │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Movie Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew_UpdateAndScanPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew_UpdateAndScanPrompt.snap new file mode 100644 index 0000000..76c813d --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_Crew_UpdateAndScanPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Crew Member Job Department │ + │=> Alex Clarke Composition Music │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo.snap new file mode 100644 index 0000000..6a2f353 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │File Details │ + │Some file info │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Audio Details │ + │Some audio info │ + │ │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Video Details │ + │Some video info │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo_AutomaticallySearchMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo_AutomaticallySearchMoviePrompt.snap new file mode 100644 index 0000000..cef3089 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo_AutomaticallySearchMoviePrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │File Details │ + │Some file info │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Audio Details │ + │Some audio info ╭──────────────── Automatic Movie Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │──────────────────────────────│ │───────────────────────────────│ + │Video Details │ │ │ + │Some video info │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo_UpdateAndScanPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo_UpdateAndScanPrompt.snap new file mode 100644 index 0000000..90fb172 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_FileInfo_UpdateAndScanPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │File Details │ + │Some file info │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Audio Details │ + │Some audio info ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │──────────────────────────────│ │───────────────────────────────│ + │Video Details │ │ │ + │Some video info │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch.snap new file mode 100644 index 0000000..b66682e --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 12 days ⛔ Some movie release The Pirate Bay 0.0 GB 25 / 3 English HD - 1080p │ + │ usenet 22 days ⛔ Some Other movie rele The Pirate Bay 0.0 GB English HD - 1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearchConfirmPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearchConfirmPrompt.snap new file mode 100644 index 0000000..e94e5dd --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearchConfirmPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 12 days ⛔ Some movie release The Pirate Bay 0.0 GB 25 / 3 English HD - 1080p │ + │ usenet 22 days ⛔ Some Other movie rele The Pirate Bay 0.0 GB English HD - 1080p │ + │ │ + │ │ + │ │ + │ ╭───────────────── Download Rejected Release ──────────────────╮ │ + │ │ Do you really want to download the rejected release: Some movie│ │ + │ │ release? │ │ + │ │ │ │ + │ │ │ │ + │ │Rejection reasons: │ │ + │ │• something interesting │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭──────────────────────────────╮╭──────────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰──────────────────────────────╯╰──────────────────────────────╯│ │ + │ ╰────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearchSortPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearchSortPrompt.snap new file mode 100644 index 0000000..faf0a48 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearchSortPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 12 days ⛔ Some movie release The Pirate Bay 0.0 GB 25 / 3 English HD - 1080p │ + │ usenet 22 days ⛔ Some Other movie rele The Pirate Bay 0.0 GB English HD - 1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────╮ │ + │ │Something │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰──────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch_AutomaticallySearchMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch_AutomaticallySearchMoviePrompt.snap new file mode 100644 index 0000000..9d72a3f --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch_AutomaticallySearchMoviePrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 12 days ⛔ Some movie release The Pirate Bay 0.0 GB 25 / 3 English HD - 1080p │ + │ usenet 22 days ⛔ Some Other movie rele The Pirate Bay 0.0 GB English HD - 1080p │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Movie Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch_UpdateAndScanPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch_UpdateAndScanPrompt.snap new file mode 100644 index 0000000..8be4353 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_ManualSearch_UpdateAndScanPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 12 days ⛔ Some movie release The Pirate Bay 0.0 GB 25 / 3 English HD - 1080p │ + │ usenet 22 days ⛔ Some Other movie rele The Pirate Bay 0.0 GB English HD - 1080p │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails.snap new file mode 100644 index 0000000..7f7ec72 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Some information: │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails_AutomaticallySearchMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails_AutomaticallySearchMoviePrompt.snap new file mode 100644 index 0000000..8086e86 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails_AutomaticallySearchMoviePrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Some information: │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Movie Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails_UpdateAndScanPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails_UpdateAndScanPrompt.snap new file mode 100644 index 0000000..3e751ff --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieDetails_UpdateAndScanPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Some information: │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory.snap new file mode 100644 index 0000000..faea751 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Languages Quality Date │ + │=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory_AutomaticallySearchMoviePrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory_AutomaticallySearchMoviePrompt.snap new file mode 100644 index 0000000..2b720c6 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory_AutomaticallySearchMoviePrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Languages Quality Date │ + │=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Movie Search ─────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory_UpdateAndScanPrompt.snap b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory_UpdateAndScanPrompt.snap new file mode 100644 index 0000000..05be306 --- /dev/null +++ b/src/ui/radarr_ui/library/snapshots/managarr__ui__radarr_ui__library__movie_details_ui__movie_details_ui_tests__tests__snapshot_tests__movie_details_render_MovieHistory_UpdateAndScanPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/library/movie_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Movie Info ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Cast │ Crew │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Languages Quality Date │ + │=> Test grabbed English HD - 1080p 2022-12-30 07:37:56 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ movie: Test? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/mod.rs b/src/ui/radarr_ui/mod.rs index 5e18a70..991aa6e 100644 --- a/src/ui/radarr_ui/mod.rs +++ b/src/ui/radarr_ui/mod.rs @@ -1,18 +1,22 @@ -use std::{cmp, iter}; - -use chrono::{Duration, Utc}; +#[cfg(test)] +use crate::ui::ui_test_utils::test_utils::Utc; +use chrono::Duration; +#[cfg(not(test))] +use chrono::Utc; +use ratatui::Frame; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::prelude::Stylize; use ratatui::text::Text; use ratatui::widgets::{Paragraph, Row}; -use ratatui::Frame; +use std::{cmp, iter}; use crate::app::App; use crate::logos::RADARR_LOGO; +use crate::models::Route; use crate::models::radarr_models::{DownloadRecord, Movie}; use crate::models::servarr_data::radarr::radarr_data::RadarrData; use crate::models::servarr_models::{DiskSpace, RootFolder}; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::draw_tabs; use crate::ui::radarr_ui::blocklist::BlocklistUi; use crate::ui::radarr_ui::collections::CollectionsUi; @@ -26,7 +30,6 @@ use crate::ui::utils::{ borderless_block, layout_block, line_gauge_with_label, line_gauge_with_title, title_block, }; use crate::ui::widgets::loading_block::LoadingBlock; -use crate::ui::DrawUi; use crate::utils::convert_to_gb; mod blocklist; @@ -34,6 +37,8 @@ mod collections; mod downloads; mod indexers; mod library; +#[cfg(test)] +mod radarr_ui_tests; mod root_folders; mod system; diff --git a/src/ui/radarr_ui/radarr_ui_tests.rs b/src/ui/radarr_ui/radarr_ui_tests.rs index 44fd4eb..ab43f32 100644 --- a/src/ui/radarr_ui/radarr_ui_tests.rs +++ b/src/ui/radarr_ui/radarr_ui_tests.rs @@ -6,10 +6,12 @@ mod tests { use rstest::rstest; use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; - use crate::ui::radarr_ui::{decorate_with_row_style, RadarrUi}; - use crate::ui::styles::ManagarrStyle; use crate::ui::DrawUi; + use crate::ui::radarr_ui::{RadarrUi, decorate_with_row_style}; + use crate::ui::styles::ManagarrStyle; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_radarr_ui_accepts() { @@ -18,6 +20,34 @@ mod tests { }); } + mod snapshot_tests { + use super::*; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + #[rstest] + #[case(ActiveRadarrBlock::Movies, 0)] + #[case(ActiveRadarrBlock::Collections, 1)] + #[case(ActiveRadarrBlock::Downloads, 2)] + #[case(ActiveRadarrBlock::Blocklist, 3)] + #[case(ActiveRadarrBlock::RootFolders, 4)] + #[case(ActiveRadarrBlock::Indexers, 5)] + #[case(ActiveRadarrBlock::System, 6)] + fn test_radarr_ui_renders_radarr_tabs( + #[case] active_radarr_block: ActiveRadarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + app.data.radarr_data.main_tabs.set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RadarrUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + } + #[rstest] #[case(false, Some("downloading"), false, "", RowStyle::Downloading)] #[case(false, Some("completed"), false, "", RowStyle::AwaitingImport)] diff --git a/src/ui/radarr_ui/root_folders/mod.rs b/src/ui/radarr_ui/root_folders/mod.rs index f2361e1..9c5ecfe 100644 --- a/src/ui/radarr_ui/root_folders/mod.rs +++ b/src/ui/radarr_ui/root_folders/mod.rs @@ -1,17 +1,17 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::servarr_models::RootFolder; -use crate::models::Route; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::layout_block_top_border; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::{draw_input_box_popup, draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_input_box_popup, draw_popup}; use crate::utils::convert_to_gb; #[cfg(test)] @@ -22,11 +22,10 @@ pub(super) struct RootFoldersUi; impl DrawUi for RootFoldersUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return ROOT_FOLDERS_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + ROOT_FOLDERS_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { diff --git a/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs b/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs index 5a312c4..392ffc8 100644 --- a/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +++ b/src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs @@ -2,9 +2,12 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_FOLDERS_BLOCKS}; - use crate::ui::radarr_ui::root_folders::RootFoldersUi; + use crate::models::stateful_table::StatefulTable; use crate::ui::DrawUi; + use crate::ui::radarr_ui::root_folders::RootFoldersUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_root_folders_ui_accepts() { @@ -16,4 +19,54 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use rstest::rstest; + + #[test] + fn test_root_folders_ui_renders_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RootFoldersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_root_folders_ui_renders_empty_root_folders() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into()); + app.data.radarr_data.root_folders = StatefulTable::default(); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RootFoldersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_root_folders_ui_renders_root_folders_tab( + #[values( + ActiveRadarrBlock::RootFolders, + ActiveRadarrBlock::AddRootFolderPrompt, + ActiveRadarrBlock::DeleteRootFolderPrompt + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RootFoldersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + } } diff --git a/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__AddRootFolderPrompt.snap b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__AddRootFolderPrompt.snap new file mode 100644 index 0000000..5d84aa1 --- /dev/null +++ b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__AddRootFolderPrompt.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Path Free Space Unmapped Folders +=> /nfs 204800.00 GB 0 + + + + + + + + + + + + + + + + + + + + + ╭───────────── Add Root Folder ─────────────╮ + │/nfs/movies │ + ╰─────────────────────────────────────────────╯ + cancel diff --git a/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__DeleteRootFolderPrompt.snap b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__DeleteRootFolderPrompt.snap new file mode 100644 index 0000000..41c0ad6 --- /dev/null +++ b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__DeleteRootFolderPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Path Free Space Unmapped Folders +=> /nfs 204800.00 GB 0 + + + + + + + + + + + + + + ╭────────────────── Delete Root Folder ───────────────────╮ + │ Do you really want to delete this root folder: │ + │ /nfs? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__RootFolders.snap b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__RootFolders.snap new file mode 100644 index 0000000..7d3c619 --- /dev/null +++ b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__RootFolders.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Path Free Space Unmapped Folders +=> /nfs 204800.00 GB 0 diff --git a/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_empty_root_folders.snap b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_empty_root_folders.snap new file mode 100644 index 0000000..9464787 --- /dev/null +++ b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_empty_root_folders.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_loading.snap b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_loading.snap new file mode 100644 index 0000000..e4bc2d4 --- /dev/null +++ b/src/ui/radarr_ui/root_folders/snapshots/managarr__ui__radarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/radarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Blocklist.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Blocklist.snap new file mode 100644 index 0000000..c502692 --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Blocklist.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Movie Title ▼ Source Title Languages Quality Formats Date │ +│=> Test z movie English HD - 1080p English 2024-02-10 07:28:45 UTC │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Collections.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Collections.snap new file mode 100644 index 0000000..983cf62 --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Collections.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Collection ▼ Number of Movies Root Folder Path Quality Profile Search on Add Monitored │ +│=> Test Collection 1 /nfs/movies HD - 1080p Yes 🏷 │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Downloads.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Downloads.snap new file mode 100644 index 0000000..16641df --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Downloads.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Title Percent Complete Size Output Path Indexer Download Client │ +│=> Test Download Title 50% 3.30 GB /nfs/movies/Test kickass torrents transmission │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Indexers.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Indexers.snap new file mode 100644 index 0000000..0576c5c --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Indexers.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Indexer ▼ RSS Automatic Search Interactive Search Priority Tags │ +│=> Test Indexer Enabled Enabled Enabled 25 alex │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Movies.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Movies.snap new file mode 100644 index 0000000..82fca3e --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__Movies.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │ +│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__RootFolders.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__RootFolders.snap new file mode 100644 index 0000000..10d0cfe --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__RootFolders.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Path Free Space Unmapped Folders │ +│=> /nfs 204800.00 GB 0 │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__System.snap b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__System.snap new file mode 100644 index 0000000..5f3c163 --- /dev/null +++ b/src/ui/radarr_ui/snapshots/managarr__ui__radarr_ui__radarr_ui_tests__tests__snapshot_tests__System.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/radarr_ui_tests.rs +expression: output +--- +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│╭ Tasks ───────────────────────────────────────────────────────────────────────╮╭ Queued Events ──────────────────────────────────────────────────────────────╮│ +││Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration ││ +││Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored 4 minutes ago 4 minutes a 00:03:03 ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +│╰────────────────────────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────────────────────╯│ +│╭ Logs ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ +││2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +│╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/mod.rs b/src/ui/radarr_ui/system/mod.rs index 715197f..2939924 100644 --- a/src/ui/radarr_ui/system/mod.rs +++ b/src/ui/radarr_ui/system/mod.rs @@ -1,14 +1,17 @@ use std::ops::Sub; +#[cfg(test)] +use crate::ui::ui_test_utils::test_utils::Utc; +#[cfg(not(test))] use chrono::Utc; use ratatui::layout::Layout; use ratatui::style::Style; use ratatui::text::{Span, Text}; use ratatui::widgets::{Cell, Row}; use ratatui::{ + Frame, layout::{Constraint, Rect}, widgets::ListItem, - Frame, }; use crate::app::App; @@ -23,7 +26,7 @@ use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::selectable_list::SelectableList; use crate::{ models::Route, - ui::{utils::title_block, DrawUi}, + ui::{DrawUi, utils::title_block}, }; mod system_details_ui; @@ -52,11 +55,10 @@ pub(super) struct SystemUi; impl DrawUi for SystemUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return SystemDetailsUi::accepts(route) || active_radarr_block == ActiveRadarrBlock::System; - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + SystemDetailsUi::accepts(route) || active_radarr_block == ActiveRadarrBlock::System } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { @@ -126,7 +128,7 @@ pub(super) fn draw_queued_events(f: &mut Frame<'_>, app: &mut App<'_>, area: Rec }; let duration = if event.duration.is_some() { - &event.duration.as_ref().unwrap()[..8] + event.duration.as_ref().map_or("", |it| &it[..8]) } else { "" }; diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemLogs.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemLogs.snap new file mode 100644 index 0000000..8ed88ae --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemLogs.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemQueuedEvents.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemQueuedEvents.snap new file mode 100644 index 0000000..095883f --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemQueuedEvents.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ + │Trigger Status Name Queued Started Duration │ + │manual completed Refresh Monitored Downlo 4 minutes ago 4 minutes ago 00:03:03 │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemTaskStartConfirmPrompt.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemTaskStartConfirmPrompt.snap new file mode 100644 index 0000000..b81d727 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemTaskStartConfirmPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Name Interval Last Execution Last Duration Next Execution │ + │=> Backup 1 hour now 00:00:17 59 minutes │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭────────────────────── Start Task ───────────────────────╮ │ + │ │ Do you want to manually start this task: Backup? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemTasks.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemTasks.snap new file mode 100644 index 0000000..86c0513 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemTasks.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Name Interval Last Execution Last Duration Next Execution │ + │=> Backup 1 hour now 00:00:17 59 minutes │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemUpdates.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemUpdates.snap new file mode 100644 index 0000000..ecc5145 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__SystemUpdates.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Updates ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │The latest version of Radarr is already installed │ + │ │ + │4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) │ + │--------------------------------------------------------------------------------------------------------------------------│ + │New: │ + │ * Cool new thing │ + │Fixed: │ + │ * Some bugs killed │ + │ │ + │ │ + │3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) │ + │--------------------------------------------------------------------------------------------------------------------------│ + │New: │ + │ * Cool new thing (old) │ + │ * Other cool new thing (old) │ + │ │ + │ │ + │2.1.0 - 2023-04-15 02:02:53 UTC │ + │--------------------------------------------------------------------------------------------------------------------------│ + │Fixed: │ + │ * Killed bug 1 │ + │ * Fixed bug 2 │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_logs_loading.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_logs_loading.snap new file mode 100644 index 0000000..8ed88ae --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_logs_loading.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_queued_events_loading.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_queued_events_loading.snap new file mode 100644 index 0000000..93ce129 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_queued_events_loading.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_tasks_loading.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_tasks_loading.snap new file mode 100644 index 0000000..28acfeb --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_renders_tasks_loading.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/radarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab.snap new file mode 100644 index 0000000..b6347ad --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_empty.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_empty.snap new file mode 100644 index 0000000..aaa3add --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_empty.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading.snap new file mode 100644 index 0000000..006d829 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ Loading ... ││ Loading ... │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ │ +│ Loading ... │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading_events_and_tasks.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading_events_and_tasks.snap new file mode 100644 index 0000000..cdcf0a2 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading_events_and_tasks.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ Loading ... ││ Loading ... │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading_logs.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading_logs.snap new file mode 100644 index 0000000..a790318 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__radarr_ui_renders_system_tab_loading_logs.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemLogs.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemLogs.snap new file mode 100644 index 0000000..68c4f5f --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemLogs.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │2025-12-15 16:14:45 UTC|INFO|DownloadDecisionMaker|Processing 545 releases │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +╰───────────────────│ │────────────────────╯ +╭ Logs ───────────│ │────────────────────╮ +│2025-12-15 16:14:45│ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemQueuedEvents.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemQueuedEvents.snap new file mode 100644 index 0000000..18b71e4 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemQueuedEvents.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ │ +│ │Trigger Status Name Queued Started Duration │ │ +│ │manual completed Refresh Monitored Downlo 4 minutes ago 4 minutes ago 00:03:03 │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +╰────────────────────────────────│ │────────────────────────────────╯ +╭ Logs ────────────────────────│ │────────────────────────────────╮ +│2025-12-15 16:14:45 UTC|INFO|Dow│ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemTaskStartConfirmPrompt.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemTaskStartConfirmPrompt.snap new file mode 100644 index 0000000..08c6dc7 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemTaskStartConfirmPrompt.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │ Name Interval Last Execution Last Duration Next Execution │ │ +│ │=> Backup 1 hour now 00:00:17 59 minutes │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ ╭────────────────────── Start Task ───────────────────────╮ │ │ +│ │ │ Do you want to manually start this task: Backup? │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +╰───────────────────│ │ │ │────────────────────╯ +╭ Logs ───────────│ │ │ │────────────────────╮ +│2025-12-15 16:14:45│ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │╭────────────────────────────╮╭───────────────────────────╮│ │ │ +│ │ ││ Yes ││ No ││ │ │ +│ │ │╰────────────────────────────╯╰───────────────────────────╯│ │ │ +│ │ ╰───────────────────────────────────────────────────────────╯ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemTasks.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemTasks.snap new file mode 100644 index 0000000..e5f4537 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemTasks.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │ Name Interval Last Execution Last Duration Next Execution │ │ +│ │=> Backup 1 hour now 00:00:17 59 minutes │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +╰───────────────────│ │────────────────────╯ +╭ Logs ───────────│ │────────────────────╮ +│2025-12-15 16:14:45│ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemUpdates.snap b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemUpdates.snap new file mode 100644 index 0000000..8e22df5 --- /dev/null +++ b/src/ui/radarr_ui/system/snapshots/managarr__ui__radarr_ui__system__system_ui_tests__tests__snapshot_tests__system_details_over_system_tab_SystemUpdates.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/radarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Last Duration Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 00:00:17 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Updates ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │The latest version of Radarr is already installed │ │ +│ │ │ │ +│ │4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) │ │ +│ │--------------------------------------------------------------------------------------------------------------------------│ │ +│ │New: │ │ +│ │ * Cool new thing │ │ +│ │Fixed: │ │ +│ │ * Some bugs killed │ │ +│ │ │ │ +│ │ │ │ +│ │3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) │ │ +│ │--------------------------------------------------------------------------------------------------------------------------│ │ +│ │New: │ │ +│ │ * Cool new thing (old) │ │ +│ │ * Other cool new thing (old) │ │ +│ │ │ │ +│ │ │ │ +╰───────────────────│2.1.0 - 2023-04-15 02:02:53 UTC │────────────────────╯ +╭ Logs ───────────│--------------------------------------------------------------------------------------------------------------------------│────────────────────╮ +│2025-12-15 16:14:45│Fixed: │ │ +│ │ * Killed bug 1 │ │ +│ │ * Fixed bug 2 │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/radarr_ui/system/system_details_ui.rs b/src/ui/radarr_ui/system/system_details_ui.rs index bdd6afd..bc8db27 100644 --- a/src/ui/radarr_ui/system/system_details_ui.rs +++ b/src/ui/radarr_ui/system/system_details_ui.rs @@ -1,14 +1,14 @@ +use ratatui::Frame; use ratatui::layout::Rect; use ratatui::text::{Span, Text}; use ratatui::widgets::{Cell, ListItem, Paragraph, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::radarr_models::RadarrTask; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS}; -use crate::models::Route; use crate::ui::radarr_ui::system::{ - draw_queued_events, extract_task_props, TASK_TABLE_CONSTRAINTS, TASK_TABLE_HEADERS, + TASK_TABLE_CONSTRAINTS, TASK_TABLE_HEADERS, draw_queued_events, extract_task_props, }; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{borderless_block, style_log_list_item, title_block}; @@ -17,7 +17,7 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; #[cfg(test)] #[path = "system_details_ui_tests.rs"] @@ -27,11 +27,10 @@ pub(super) struct SystemDetailsUi; impl DrawUi for SystemDetailsUi { fn accepts(route: Route) -> bool { - if let Route::Radarr(active_radarr_block, _) = route { - return SYSTEM_DETAILS_BLOCKS.contains(&active_radarr_block); - } - - false + let Route::Radarr(active_radarr_block, _) = route else { + return false; + }; + SYSTEM_DETAILS_BLOCKS.contains(&active_radarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { diff --git a/src/ui/radarr_ui/system/system_details_ui_tests.rs b/src/ui/radarr_ui/system/system_details_ui_tests.rs index 0690fb7..2277f3a 100644 --- a/src/ui/radarr_ui/system/system_details_ui_tests.rs +++ b/src/ui/radarr_ui/system/system_details_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, }; - use crate::ui::radarr_ui::system::system_details_ui::SystemDetailsUi; + use crate::ui::DrawUi; + use crate::ui::radarr_ui::system::system_details_ui::SystemDetailsUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_system_details_ui_accepts() { @@ -18,4 +21,69 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use rstest::rstest; + + #[rstest] + fn test_system_details_ui_renders_popups( + #[values( + ActiveRadarrBlock::SystemLogs, + ActiveRadarrBlock::SystemQueuedEvents, + ActiveRadarrBlock::SystemTasks, + ActiveRadarrBlock::SystemTaskStartConfirmPrompt, + ActiveRadarrBlock::SystemUpdates + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_radarr_block.to_string(), output); + } + + #[test] + fn test_system_details_ui_renders_tasks_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_system_details_ui_renders_queued_events_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::SystemQueuedEvents.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_system_details_ui_renders_logs_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveRadarrBlock::SystemLogs.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/radarr_ui/system/system_ui_tests.rs b/src/ui/radarr_ui/system/system_ui_tests.rs index 797e1b0..31bd161 100644 --- a/src/ui/radarr_ui/system/system_ui_tests.rs +++ b/src/ui/radarr_ui/system/system_ui_tests.rs @@ -2,11 +2,13 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::radarr::radarr_data::{ ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS, }; - use crate::ui::radarr_ui::system::SystemUi; use crate::ui::DrawUi; + use crate::ui::radarr_ui::system::SystemUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; #[test] fn test_system_ui_accepts() { @@ -22,4 +24,104 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use crate::models::stateful_list::StatefulList; + use crate::models::stateful_table::StatefulTable; + use rstest::rstest; + + #[test] + fn test_radarr_ui_renders_system_tab_loading() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::System.into()); + app.is_loading = true; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_radarr_ui_renders_system_tab_loading_logs() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::System.into()); + app.data.radarr_data.logs = StatefulList::default(); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_radarr_ui_renders_system_tab_loading_events_and_tasks() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::System.into()); + app.is_loading = true; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_radarr_ui_renders_system_tab() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::System.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_radarr_ui_renders_system_tab_empty() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::System.into()); + { + let radarr_data = &mut app.data.radarr_data; + radarr_data.logs = StatefulList::default(); + radarr_data.tasks = StatefulTable::default(); + radarr_data.queued_events = StatefulTable::default(); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_system_details_ui_renders_popups_over_system_tab( + #[values( + ActiveRadarrBlock::SystemLogs, + ActiveRadarrBlock::SystemQueuedEvents, + ActiveRadarrBlock::SystemTasks, + ActiveRadarrBlock::SystemTaskStartConfirmPrompt, + ActiveRadarrBlock::SystemUpdates + )] + active_radarr_block: ActiveRadarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_radarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("system_details_over_system_tab_{active_radarr_block}"), + output + ); + } + } } diff --git a/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab.snap b/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab.snap new file mode 100644 index 0000000..8f537b7 --- /dev/null +++ b/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/ui_tests.rs +expression: output +--- +╭ Managarr - A Servarr management TUI ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Radarr │ Sonarr to open help│ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭ Stats ──────────────────────────────────────────────────────────────╮╭ Downloads ─────────────────────────────────────────────────────────╮╭──────────────────╮ +│Radarr Version: 1.2.3.4 ││Test Download Title ││ ⠀⣠⣶⢶⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀ │ +│Uptime: 0d 00:00:44 ││50% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━││ ⠀⣿⡇⠀⠈⠙⠻⢿⣶⣤⡀⠀⠀⠀⠀ │ +│Storage: ││ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⠈⠙⠻⢷⣦⡄⠀ │ +│Disk 1: 100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━││ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢉⠻⠀ │ +│Root Folders: ││ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⢀⣠⣴⣾⠿⠀⠀ │ +│/nfs: 204800.00 GB free ││ ││ ⠀⢿⡇⠀⠀⣀⣤⣶⡿⠛⠉⠀⠀⠀⠀ │ +│ ││ ││ ⠀⠀⠰⠶⡿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀ │ +│ ││ ││ │ +╰───────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────╯╰──────────────────╯ +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │ +│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab_error_popup.snap b/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab_error_popup.snap new file mode 100644 index 0000000..72a40f2 --- /dev/null +++ b/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab_error_popup.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/ui_tests.rs +expression: output +--- +╭ Managarr - A Servarr management TUI ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Radarr │ Sonarr to open help│ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭ Stats ──────────────────────────────────────────────────────────────╮╭ Downloads ─────────────────────────────────────────────────────────╮╭──────────────────╮ +│Radarr Version: 1.2.3.4 ╭ Keybindings ──────────────────────────────────────────────────────────────────────────╮ ││ ⠀⣠⣶⢶⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀ │ +│Uptime: 0d 00:00:44 │ Key Alt Key Description │━━━━━━━━━━━━━━━━━││ ⠀⣿⡇⠀⠈⠙⠻⢿⣶⣤⡀⠀⠀⠀⠀ │ +│Storage: │=> a add │ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⠈⠙⠻⢷⣦⡄⠀ │ +│Disk 1: 100% ━━━━━━━━━━━━━━━━━━━━━━│ e edit │ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢉⠻⠀ │ +│Root Folders: │ m toggle monitoring │ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⢀⣠⣴⣾⠿⠀⠀ │ +│/nfs: 204800.00 GB free │ o sort │ ││ ⠀⢿⡇⠀⠀⣀⣤⣶⡿⠛⠉⠀⠀⠀⠀ │ +│ │ del delete │ ││ ⠀⠀⠰⠶⡿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀ │ +│ │ s search │ ││ │ +╰───────────────────────────────────│ f filter │─────────────────╯╰──────────────────╯ +╭ Movies ─────────────────────────│ ctrl-r refresh │─────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ u update all │ │ +│───────────────────────────────────│ enter details │─────────────────────────────────────│ +│ Title ▼ │ esc cancel filter │ofile Monitored Tags │ +│=> Test │ ↑ k scroll up │ 🏷 alex │ +│ │ ↓ j scroll down │ │ +│ │ ← h previous tab │ │ +│ │ → l next tab │ │ +│ │ pgUp ctrl-u page up │ │ +│ │ pgDown ctrl-d page down │ │ +│ │ tab next servarr │ │ +│ │ shift-tab previous servarr │ │ +│ │ q quit │ │ +│ │ ? show/hide keybindings │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab_with_error.snap b/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab_with_error.snap new file mode 100644 index 0000000..17602d3 --- /dev/null +++ b/src/ui/snapshots/managarr__ui__ui_tests__snapshot_tests__radarr_ui_renders_library_tab_with_error.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/ui_tests.rs +expression: output +--- +╭ Managarr - A Servarr management TUI ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Radarr │ Sonarr to open help│ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭ Error | to close ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│Some error │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭ Stats ──────────────────────────────────────────────────────────────╮╭ Downloads ─────────────────────────────────────────────────────────╮╭──────────────────╮ +│Radarr Version: 1.2.3.4 ││Test Download Title ││ ⠀⣠⣶⢶⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀ │ +│Uptime: 0d 00:00:44 ││50% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━││ ⠀⣿⡇⠀⠈⠙⠻⢿⣶⣤⡀⠀⠀⠀⠀ │ +│Storage: ││ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⠈⠙⠻⢷⣦⡄⠀ │ +│Disk 1: 100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━││ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⢉⠻⠀ │ +│Root Folders: ││ ││ ⠀⣿⡇⠀⠀⠀⠀⠀⢀⣠⣴⣾⠿⠀⠀ │ +│/nfs: 204800.00 GB free ││ ││ ⠀⢿⡇⠀⠀⣀⣤⣶⡿⠛⠉⠀⠀⠀⠀ │ +│ ││ ││ ⠀⠀⠰⠶⡿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀ │ +│ ││ ││ │ +╰───────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────╯╰──────────────────╯ +╭ Movies ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Collections │ Downloads │ Blocklist │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Title ▼ Year Studio Runtime Rating Language Size Quality Profile Monitored Tags │ +│=> Test 2023 21st Century Alex 2h 0m R English 3.30 GB HD - 1080p 🏷 alex │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs b/src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs index 009adc0..0ab47b0 100644 --- a/src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +++ b/src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs @@ -1,10 +1,13 @@ #[cfg(test)] mod tests { - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, BLOCKLIST_BLOCKS}; - use crate::ui::sonarr_ui::blocklist::BlocklistUi; - use crate::ui::DrawUi; use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, BLOCKLIST_BLOCKS}; + use crate::ui::DrawUi; + use crate::ui::sonarr_ui::blocklist::BlocklistUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; + #[test] fn test_blocklist_ui_accepts() { ActiveSonarrBlock::iter().for_each(|active_sonarr_block| { @@ -15,4 +18,57 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_blocklist_ui_renders_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::Blocklist.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + BlocklistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_blocklist_ui_renders_empty() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveSonarrBlock::Blocklist.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + BlocklistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_blocklist_ui_renders( + #[values( + ActiveSonarrBlock::Blocklist, + ActiveSonarrBlock::BlocklistItemDetails, + ActiveSonarrBlock::DeleteBlocklistItemPrompt, + ActiveSonarrBlock::BlocklistClearAllItemsPrompt, + ActiveSonarrBlock::BlocklistSortPrompt + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + BlocklistUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("blocklist_tab_{active_sonarr_block}"), output); + } + } } diff --git a/src/ui/sonarr_ui/blocklist/mod.rs b/src/ui/sonarr_ui/blocklist/mod.rs index 32031ae..6eb7f07 100644 --- a/src/ui/sonarr_ui/blocklist/mod.rs +++ b/src/ui/sonarr_ui/blocklist/mod.rs @@ -1,19 +1,19 @@ use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, BLOCKLIST_BLOCKS}; use crate::models::sonarr_models::BlocklistItem; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::layout_block_top_border; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; +use ratatui::Frame; use ratatui::layout::{Alignment, Constraint, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::{Line, Text}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; #[cfg(test)] #[path = "blocklist_ui_tests.rs"] diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_Blocklist.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_Blocklist.snap new file mode 100644 index 0000000..1d83850 --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_Blocklist.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Series Title ▼ Source Title Language Quality Date +=> Test Series Test Source Title English Bluray-1080p 2024-02-10 07:28:45 UTC diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistClearAllItemsPrompt.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistClearAllItemsPrompt.snap new file mode 100644 index 0000000..2d83c6e --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistClearAllItemsPrompt.snap @@ -0,0 +1,34 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Series Title ▼ Source Title Language Quality Date +=> Test Series Test Source Title English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + ╭────── Clear Blocklist ──────╮ + │ Do you want to clear your │ + │ blocklist? │ + │ │ + │ │ + │ │ + │╭──────────────╮╭─────────────╮│ + ││ Yes ││ No ││ + │╰──────────────╯╰─────────────╯│ + ╰───────────────────────────────╯ diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistItemDetails.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistItemDetails.snap new file mode 100644 index 0000000..8c2e63c --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistItemDetails.snap @@ -0,0 +1,34 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Series Title ▼ Source Title Language Quality Date +=> Test Series Test Source Title English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + ╭─────────────────────────────────── Details ───────────────────────────────────╮ + │Name: Test Source Title │ + │Protocol: usenet │ + │Indexer: NZBgeek (Prowlarr) │ + │Message: test message │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistSortPrompt.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistSortPrompt.snap new file mode 100644 index 0000000..5f6e390 --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_BlocklistSortPrompt.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Series Title Source Title Language Quality Date +=> Test Series Test Source Title English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + ╭───────────────────────────────╮ + │Something │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────╯ diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_DeleteBlocklistItemPrompt.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_DeleteBlocklistItemPrompt.snap new file mode 100644 index 0000000..8f2c711 --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_tab_DeleteBlocklistItemPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Series Title ▼ Source Title Language Quality Date +=> Test Series Test Source Title English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + ╭────────────── Remove Item from Blocklist ───────────────╮ + │ Do you want to remove this item from your blocklist: │ + │ Test Source Title? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_empty.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_empty.snap new file mode 100644 index 0000000..c19fb22 --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_empty.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_loading.snap b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_loading.snap new file mode 100644 index 0000000..1d93026 --- /dev/null +++ b/src/ui/sonarr_ui/blocklist/snapshots/managarr__ui__sonarr_ui__blocklist__blocklist_ui_tests__tests__snapshot_tests__blocklist_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/sonarr_ui/blocklist/blocklist_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/sonarr_ui/downloads/downloads_ui_tests.rs b/src/ui/sonarr_ui/downloads/downloads_ui_tests.rs index 2d040ae..19985a5 100644 --- a/src/ui/sonarr_ui/downloads/downloads_ui_tests.rs +++ b/src/ui/sonarr_ui/downloads/downloads_ui_tests.rs @@ -2,9 +2,11 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS}; - use crate::ui::sonarr_ui::downloads::DownloadsUi; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::downloads::DownloadsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_downloads_ui_accepts() { @@ -16,4 +18,55 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_downloads_ui_renders_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::Downloads.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DownloadsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_downloads_ui_renders_empty_downloads() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveSonarrBlock::Downloads.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DownloadsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_downloads_ui_renders( + #[values( + ActiveSonarrBlock::Downloads, + ActiveSonarrBlock::DeleteDownloadPrompt, + ActiveSonarrBlock::UpdateDownloadsPrompt + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DownloadsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("downloads_ui_{active_sonarr_block}"), output); + } + } } diff --git a/src/ui/sonarr_ui/downloads/mod.rs b/src/ui/sonarr_ui/downloads/mod.rs index 643716f..3064827 100644 --- a/src/ui/sonarr_ui/downloads/mod.rs +++ b/src/ui/sonarr_ui/downloads/mod.rs @@ -1,17 +1,17 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS}; use crate::models::sonarr_models::DownloadRecord; use crate::models::{HorizontallyScrollableText, Route}; +use crate::ui::DrawUi; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{get_width_from_percentage, layout_block_top_border}; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; use crate::utils::convert_f64_to_gb; #[cfg(test)] diff --git a/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_DeleteDownloadPrompt.snap b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_DeleteDownloadPrompt.snap new file mode 100644 index 0000000..c5f7dae --- /dev/null +++ b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_DeleteDownloadPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Percent Complete Size Output Path Indexer Download Client +=> Test Download Title 50% 3.30 GB /nfs/tv/Test show/season 1/ kickass torrents transmission + + + + + + + + + + + + + + ╭──────────────────── Cancel Download ────────────────────╮ + │ Do you really want to delete this download: │ + │ Test Download Title? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_Downloads.snap b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_Downloads.snap new file mode 100644 index 0000000..933b0c9 --- /dev/null +++ b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_Downloads.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/sonarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Percent Complete Size Output Path Indexer Download Client +=> Test Download Title 50% 3.30 GB /nfs/tv/Test show/season 1/ kickass torrents transmission diff --git a/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_UpdateDownloadsPrompt.snap b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_UpdateDownloadsPrompt.snap new file mode 100644 index 0000000..19a85cc --- /dev/null +++ b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_UpdateDownloadsPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Percent Complete Size Output Path Indexer Download Client +=> Test Download Title 50% 3.30 GB /nfs/tv/Test show/season 1/ kickass torrents transmission + + + + + + + + + + + + + + ╭─────────────────── Update Downloads ────────────────────╮ + │ Do you want to update your downloads? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_renders_empty_downloads.snap b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_renders_empty_downloads.snap new file mode 100644 index 0000000..c42cac3 --- /dev/null +++ b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_renders_empty_downloads.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/sonarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_renders_loading.snap b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_renders_loading.snap new file mode 100644 index 0000000..080e4fa --- /dev/null +++ b/src/ui/sonarr_ui/downloads/snapshots/managarr__ui__sonarr_ui__downloads__downloads_ui_tests__tests__snapshot_tests__downloads_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/sonarr_ui/downloads/downloads_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/sonarr_ui/history/history_ui_tests.rs b/src/ui/sonarr_ui/history/history_ui_tests.rs index bae662e..21ef724 100644 --- a/src/ui/sonarr_ui/history/history_ui_tests.rs +++ b/src/ui/sonarr_ui/history/history_ui_tests.rs @@ -1,10 +1,13 @@ #[cfg(test)] mod tests { - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS}; - use crate::ui::sonarr_ui::history::HistoryUi; - use crate::ui::DrawUi; use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTORY_BLOCKS}; + use crate::ui::DrawUi; + use crate::ui::sonarr_ui::history::HistoryUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; + #[test] fn test_history_ui_accepts() { ActiveSonarrBlock::iter().for_each(|active_sonarr_block| { @@ -15,4 +18,62 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_history_ui_renders_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::History.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + HistoryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_history_ui_renders_empty( + #[values(ActiveSonarrBlock::History, ActiveSonarrBlock::HistoryItemDetails)] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + HistoryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("loading_history_tab_{active_sonarr_block}"), output); + } + + #[rstest] + fn test_history_ui_renders( + #[values( + ActiveSonarrBlock::History, + ActiveSonarrBlock::HistoryItemDetails, + ActiveSonarrBlock::HistorySortPrompt, + ActiveSonarrBlock::FilterHistory, + ActiveSonarrBlock::FilterHistoryError, + ActiveSonarrBlock::SearchHistory, + ActiveSonarrBlock::SearchHistoryError + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + HistoryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("history_tab_{active_sonarr_block}"), output); + } + } } diff --git a/src/ui/sonarr_ui/history/mod.rs b/src/ui/sonarr_ui/history/mod.rs index c8ff35f..20747ea 100644 --- a/src/ui/sonarr_ui/history/mod.rs +++ b/src/ui/sonarr_ui/history/mod.rs @@ -1,19 +1,19 @@ 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::Route; +use crate::ui::DrawUi; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{get_width_from_percentage, layout_block_top_border}; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; +use ratatui::Frame; use ratatui::layout::{Alignment, Constraint, Rect}; use ratatui::style::Style; use ratatui::text::Text; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use super::sonarr_ui_utils::{ create_download_failed_history_event_details, diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_FilterHistory.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_FilterHistory.snap new file mode 100644 index 0000000..fd21b4e --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_FilterHistory.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title ▼ Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + + ╭───────────────── Filter ──────────────────╮ + │test filter │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_FilterHistoryError.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_FilterHistoryError.snap new file mode 100644 index 0000000..5e35a5a --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_FilterHistoryError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title ▼ Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │The given filter produced empty results│ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_History.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_History.snap new file mode 100644 index 0000000..b28692c --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_History.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title ▼ Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_HistoryItemDetails.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_HistoryItemDetails.snap new file mode 100644 index 0000000..77e2c98 --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_HistoryItemDetails.snap @@ -0,0 +1,34 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title ▼ Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + ╭─────────────────────────────────── Details ───────────────────────────────────╮ + │Source Title: Test source │ + │Indexer: │ + │Release Group: │ + │Series Match Type: │ + │NZB Info URL: │ + │Download Client Name: │ + │Age: 0 days │ + │Published Date: 1970-01-01 00:00:00 UTC │ + ╰─────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_HistorySortPrompt.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_HistorySortPrompt.snap new file mode 100644 index 0000000..1d784c9 --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_HistorySortPrompt.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + ╭───────────────────────────────╮ + │Something │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────╯ diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_SearchHistory.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_SearchHistory.snap new file mode 100644 index 0000000..f7923ef --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_SearchHistory.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title ▼ Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + + ╭───────────────── Search ──────────────────╮ + │test search │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_SearchHistoryError.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_SearchHistoryError.snap new file mode 100644 index 0000000..21e184f --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_tab_SearchHistoryError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Source Title ▼ Event Type Language Quality Date +=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ No items found matching search │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_ui_renders_loading.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_ui_renders_loading.snap new file mode 100644 index 0000000..7d88e78 --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__history_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__loading_history_tab_History.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__loading_history_tab_History.snap new file mode 100644 index 0000000..3cc6564 --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__loading_history_tab_History.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__loading_history_tab_HistoryItemDetails.snap b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__loading_history_tab_HistoryItemDetails.snap new file mode 100644 index 0000000..71155ea --- /dev/null +++ b/src/ui/sonarr_ui/history/snapshots/managarr__ui__sonarr_ui__history__history_ui_tests__tests__snapshot_tests__loading_history_tab_HistoryItemDetails.snap @@ -0,0 +1,34 @@ +--- +source: src/ui/sonarr_ui/history/history_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + + + + + + + + + + + + + + + + + + ╭─────────────────────────────────── Details ───────────────────────────────────╮ + │Source Title: │ + │ │ + │No additional data available │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/edit_indexer_ui.rs b/src/ui/sonarr_ui/indexers/edit_indexer_ui.rs index 58d716f..c12cafe 100644 --- a/src/ui/sonarr_ui/indexers/edit_indexer_ui.rs +++ b/src/ui/sonarr_ui/indexers/edit_indexer_ui.rs @@ -1,8 +1,8 @@ use std::sync::atomic::Ordering; use crate::app::App; -use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS}; use crate::models::Route; +use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS}; use crate::render_selectable_input_box; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::title_block_centered; @@ -11,9 +11,9 @@ use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; -use ratatui::layout::{Constraint, Flex, Layout, Rect}; +use crate::ui::{DrawUi, draw_popup}; use ratatui::Frame; +use ratatui::layout::{Constraint, Flex, Layout, Rect}; #[cfg(test)] #[path = "edit_indexer_ui_tests.rs"] @@ -23,11 +23,10 @@ pub(super) struct EditIndexerUi; impl DrawUi for EditIndexerUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return EDIT_INDEXER_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + EDIT_INDEXER_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { @@ -55,15 +54,20 @@ fn draw_edit_indexer_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { Layout::horizontal([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)]) .margin(1) .areas(settings_area); - let [name_area, rss_area, auto_search_area, interactive_search_area, priority_area] = - Layout::vertical([ - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - ]) - .areas(left_side_area); + let [ + name_area, + rss_area, + auto_search_area, + interactive_search_area, + priority_area, + ] = Layout::vertical([ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + ]) + .areas(left_side_area); let [url_area, api_key_area, seed_ratio_area, tags_area] = Layout::vertical([ Constraint::Length(3), Constraint::Length(3), diff --git a/src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs b/src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs index 362bc61..a1ed716 100644 --- a/src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs +++ b/src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs @@ -1,10 +1,17 @@ #[cfg(test)] mod tests { - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS}; - use crate::ui::sonarr_ui::indexers::edit_indexer_ui::EditIndexerUi; - use crate::ui::DrawUi; use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::{ + ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, + }; + use crate::models::servarr_models::Indexer; + use crate::ui::DrawUi; + use crate::ui::sonarr_ui::indexers::edit_indexer_ui::EditIndexerUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; + #[test] fn test_edit_indexer_ui_accepts() { ActiveSonarrBlock::iter().for_each(|active_sonarr_block| { @@ -15,4 +22,60 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::models::servarr_data::sonarr::sonarr_data::EDIT_INDEXER_NZB_SELECTION_BLOCKS; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::indexer; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + use super::*; + + #[test] + fn test_edit_indexer_ui_renders_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.data.sonarr_data.edit_indexer_modal = None; + app.push_navigation_stack(ActiveSonarrBlock::EditIndexerPrompt.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_TORRENT_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditIndexerUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_edit_indexer_ui_renders_edit_torrent_indexer() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EditIndexerPrompt.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_TORRENT_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditIndexerUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_edit_indexer_ui_renders_edit_usenet_indexer() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EditIndexerPrompt.into()); + app.data.sonarr_data.indexers.set_items(vec![Indexer { + protocol: "usenet".into(), + ..indexer() + }]); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_NZB_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditIndexerUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/indexers/indexer_settings_ui.rs b/src/ui/sonarr_ui/indexers/indexer_settings_ui.rs index 3e01503..5dcdce9 100644 --- a/src/ui/sonarr_ui/indexers/indexer_settings_ui.rs +++ b/src/ui/sonarr_ui/indexers/indexer_settings_ui.rs @@ -1,11 +1,11 @@ -use ratatui::layout::{Constraint, Flex, Layout, Rect}; use ratatui::Frame; +use ratatui::layout::{Constraint, Flex, Layout, Rect}; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS, }; -use crate::models::Route; use crate::render_selectable_input_box; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::title_block_centered; @@ -13,7 +13,7 @@ use crate::ui::widgets::button::Button; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; #[cfg(test)] #[path = "indexer_settings_ui_tests.rs"] @@ -23,11 +23,10 @@ pub(super) struct IndexerSettingsUi; impl DrawUi for IndexerSettingsUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return INDEXER_SETTINGS_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + INDEXER_SETTINGS_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { @@ -46,18 +45,25 @@ fn draw_edit_indexer_settings_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: f.render_widget(block, area); let indexer_settings = indexer_settings_option.as_ref().unwrap(); - let [_, min_age_area, retention_area, max_size_area, rss_sync_area, _, buttons_area] = - Layout::vertical([ - Constraint::Fill(1), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Fill(1), - Constraint::Length(3), - ]) - .margin(1) - .areas(area); + let [ + _, + min_age_area, + retention_area, + max_size_area, + rss_sync_area, + _, + buttons_area, + ] = Layout::vertical([ + Constraint::Fill(1), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) + .margin(1) + .areas(area); if let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() { let min_age = indexer_settings.minimum_age.to_string(); diff --git a/src/ui/sonarr_ui/indexers/indexer_settings_ui_tests.rs b/src/ui/sonarr_ui/indexers/indexer_settings_ui_tests.rs index f95304f..884d0ee 100644 --- a/src/ui/sonarr_ui/indexers/indexer_settings_ui_tests.rs +++ b/src/ui/sonarr_ui/indexers/indexer_settings_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; + use crate::models::BlockSelectionState; use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS, + ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS, INDEXER_SETTINGS_SELECTION_BLOCKS, }; - use crate::ui::sonarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_indexer_settings_ui_accepts() { @@ -18,4 +21,24 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + use super::*; + + #[test] + fn test_indexer_settings_ui_renders_indexer_settings() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::IndexerSettingsMinimumAgeInput.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexerSettingsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/indexers/indexers_ui_tests.rs b/src/ui/sonarr_ui/indexers/indexers_ui_tests.rs index 84a548d..0db0575 100644 --- a/src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +++ b/src/ui/sonarr_ui/indexers/indexers_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, INDEXERS_BLOCKS, INDEXER_SETTINGS_BLOCKS, + ActiveSonarrBlock, EDIT_INDEXER_BLOCKS, INDEXER_SETTINGS_BLOCKS, INDEXERS_BLOCKS, }; - use crate::ui::sonarr_ui::indexers::IndexersUi; + use crate::models::servarr_models::Indexer; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::indexers::IndexersUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_indexers_ui_accepts() { @@ -24,4 +27,130 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::{ + EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, + }; + use crate::network::sonarr_network::sonarr_network_test_utils::test_utils::indexer; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_indexers_ui_renders_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::Indexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_loading_test_results() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::TestIndexer.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_loading_test_results_when_indexer_test_errors_is_none() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::TestIndexer.into()); + app.data.sonarr_data.indexer_test_errors = None; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_empty_indexers() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveSonarrBlock::Indexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_indexers_ui_renders( + #[values( + ActiveSonarrBlock::DeleteIndexerPrompt, + ActiveSonarrBlock::Indexers, + ActiveSonarrBlock::TestIndexer + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("indexers_ui_{active_sonarr_block}"), output); + } + + #[test] + fn test_indexers_ui_renders_test_all_over_indexers() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::TestAllIndexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_edit_usenet_indexer_over_indexers() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EditIndexerPrompt.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_NZB_SELECTION_BLOCKS); + app.data.sonarr_data.indexers.set_items(vec![Indexer { + protocol: "usenet".into(), + ..indexer() + }]); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_indexers_ui_renders_edit_torrent_indexer_over_indexers() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EditIndexerPrompt.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(EDIT_INDEXER_TORRENT_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + IndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/indexers/mod.rs b/src/ui/sonarr_ui/indexers/mod.rs index fa7e3f4..86b08b0 100644 --- a/src/ui/sonarr_ui/indexers/mod.rs +++ b/src/ui/sonarr_ui/indexers/mod.rs @@ -1,13 +1,14 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::Text; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, INDEXERS_BLOCKS}; use crate::models::servarr_models::Indexer; -use crate::models::Route; +use crate::ui::DrawUi; use crate::ui::sonarr_ui::indexers::edit_indexer_ui::EditIndexerUi; use crate::ui::sonarr_ui::indexers::indexer_settings_ui::IndexerSettingsUi; use crate::ui::sonarr_ui::indexers::test_all_indexers_ui::TestAllIndexersUi; @@ -18,7 +19,6 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; mod edit_indexer_ui; mod indexer_settings_ui; diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_torrent_indexer.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_torrent_indexer.snap new file mode 100644 index 0000000..a0b6c2a --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_torrent_indexer.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Name: │DrunkenSlug │ URL: │http://127.0.0.1:9696/1/ │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable RSS: │ ✔ │ API Key: │someApiKey │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Automatic Search: │ ✔ │ Seed Ratio: │ratio │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Interactive Search: │ ✔ │ Tags: │25 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭─────────────────────────╮ │ + │ Indexer Priority ▴▾: │1 │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_usenet_indexer.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_usenet_indexer.snap new file mode 100644 index 0000000..896e728 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_edit_usenet_indexer.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Name: │DrunkenSlug │ URL: │http://127.0.0.1:9696/1/ │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable RSS: │ ✔ │ API Key: │someApiKey │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Automatic Search: │ ✔ │ Tags: │25 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Interactive Search: │ ✔ │ Indexer Priority ▴▾: │1 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_loading.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_loading.snap new file mode 100644 index 0000000..2d1f45a --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__edit_indexer_ui__edit_indexer_ui_tests__tests__snapshot_tests__edit_indexer_ui_renders_loading.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/indexers/edit_indexer_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexer_settings_ui__indexer_settings_ui_tests__tests__snapshot_tests__indexer_settings_ui_renders_indexer_settings.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexer_settings_ui__indexer_settings_ui_tests__tests__snapshot_tests__indexer_settings_ui_renders_indexer_settings.snap new file mode 100644 index 0000000..5452cda --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexer_settings_ui__indexer_settings_ui_tests__tests__snapshot_tests__indexer_settings_ui_renders_indexer_settings.snap @@ -0,0 +1,40 @@ +--- +source: src/ui/sonarr_ui/indexers/indexer_settings_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + + ╭─────────────────── Configure All Indexer Settings ───────────────────╮ + │ │ + │ │ + │ │ + │ ╭────────────────────────────────╮ │ + │ Minimum Age (minutes) ▴▾: │1 │ │ + │ ╰────────────────────────────────╯ │ + │ ╭────────────────────────────────╮ │ + │ Retention (days) ▴▾: │1 │ │ + │ ╰────────────────────────────────╯ │ + │ ╭────────────────────────────────╮ │ + │ Maximum Size (MB) ▴▾: │12345 │ │ + │ ╰────────────────────────────────╯ │ + │ ╭────────────────────────────────╮ │ + │ RSS Sync Interval (minutes) ▴▾: │60 │ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ ╭────────────────╮╭────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰────────────────╯╰────────────────╯ │ + ╰────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_DeleteIndexerPrompt.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_DeleteIndexerPrompt.snap new file mode 100644 index 0000000..4bbef8a --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_DeleteIndexerPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + ╭──────────────────── Delete Indexer ─────────────────────╮ + │ Do you really want to delete this indexer: │ + │ Test Indexer? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_Indexers.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_Indexers.snap new file mode 100644 index 0000000..5392f4e --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_Indexers.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_TestIndexer.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_TestIndexer.snap new file mode 100644 index 0000000..d7d1ec7 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_TestIndexer.snap @@ -0,0 +1,35 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ error │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_edit_torrent_indexer_over_indexers.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_edit_torrent_indexer_over_indexers.snap new file mode 100644 index 0000000..d29787f --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_edit_torrent_indexer_over_indexers.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Name: │DrunkenSlug │ URL: │http://127.0.0.1:9696/1/ │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable RSS: │ ✔ │ API Key: │someApiKey │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Automatic Search: │ ✔ │ Seed Ratio: │ratio │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Interactive Search: │ ✔ │ Tags: │25 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭─────────────────────────╮ │ + │ Indexer Priority ▴▾: │1 │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_edit_usenet_indexer_over_indexers.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_edit_usenet_indexer_over_indexers.snap new file mode 100644 index 0000000..585f82b --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_edit_usenet_indexer_over_indexers.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + ╭──────────────────────────────────────────────── Edit Indexer ─────────────────────────────────────────────────╮ + │ │ + │ ╭─────────────────────────╮ ╭─────────────────────────╮ │ + │ Name: │DrunkenSlug │ URL: │http://127.0.0.1:9696/1/ │ │ + │ ╰─────────────────────────╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable RSS: │ ✔ │ API Key: │someApiKey │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Automatic Search: │ ✔ │ Tags: │25 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ ╭───╮ ╭─────────────────────────╮ │ + │ Enable Interactive Search: │ ✔ │ Indexer Priority ▴▾: │1 │ │ + │ ╰───╯ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────────────────╮╭──────────────────────────╮ │ + │ │ Save ││ Cancel │ │ + │ ╰───────────────────────────╯╰──────────────────────────╯ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_empty_indexers.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_empty_indexers.snap new file mode 100644 index 0000000..fc61280 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_empty_indexers.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading.snap new file mode 100644 index 0000000..7a8ba71 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading_test_results.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading_test_results.snap new file mode 100644 index 0000000..d9d8ee2 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading_test_results.snap @@ -0,0 +1,35 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... + + + + + + + + + + + + + + + + ╭ Testing Indexer ────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading_test_results_when_indexer_test_errors_is_none.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading_test_results_when_indexer_test_errors_is_none.snap new file mode 100644 index 0000000..f893fed --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_loading_test_results_when_indexer_test_errors_is_none.snap @@ -0,0 +1,35 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + + + + + + + + + + + + + + ╭ Testing Indexer ────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_all_over_indexers.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_all_over_indexers.snap new file mode 100644 index 0000000..a18b8a2 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__indexers_ui_tests__tests__snapshot_tests__indexers_ui_renders_test_all_over_indexers.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/indexers/indexers_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Indexer RSS Automatic Search Interactive Search Priority Tags +=> Test Indexer Enabled Enabled Enabled 25 alex + + + + ╭ Test All Indexers ─────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Indexer Pass/Fail Failure Messages │ + │=> DrunkenSlug ❌ Some failure │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders.snap new file mode 100644 index 0000000..9312f77 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/indexers/test_all_indexers_ui_tests.rs +expression: output +--- + + + + + + + ╭ Test All Indexers ─────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Indexer Pass/Fail Failure Messages │ + │=> DrunkenSlug ❌ Some failure │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders_loading.snap b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders_loading.snap new file mode 100644 index 0000000..25b7593 --- /dev/null +++ b/src/ui/sonarr_ui/indexers/snapshots/managarr__ui__sonarr_ui__indexers__test_all_indexers_ui__test_all_indexers_ui_tests__tests__snapshot_tests__test_all_indexers_ui_renders_loading.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/indexers/test_all_indexers_ui_tests.rs +expression: output +--- + + + + + + + ╭ Test All Indexers ─────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs b/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs index 5e53cac..f7256ec 100644 --- a/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs +++ b/src/ui/sonarr_ui/indexers/test_all_indexers_ui.rs @@ -1,15 +1,15 @@ use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; -use crate::models::Route; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{get_width_from_percentage, title_block}; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::Size; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; #[cfg(test)] #[path = "test_all_indexers_ui_tests.rs"] diff --git a/src/ui/sonarr_ui/indexers/test_all_indexers_ui_tests.rs b/src/ui/sonarr_ui/indexers/test_all_indexers_ui_tests.rs index 16f7e2e..695ab20 100644 --- a/src/ui/sonarr_ui/indexers/test_all_indexers_ui_tests.rs +++ b/src/ui/sonarr_ui/indexers/test_all_indexers_ui_tests.rs @@ -2,9 +2,11 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock; - use crate::ui::sonarr_ui::indexers::test_all_indexers_ui::TestAllIndexersUi; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::indexers::test_all_indexers_ui::TestAllIndexersUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_test_all_indexers_ui_accepts() { @@ -16,4 +18,35 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + use super::*; + + #[test] + fn test_test_all_indexers_ui_renders_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::TestAllIndexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + TestAllIndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_test_all_indexers_ui_renders() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::TestAllIndexers.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + TestAllIndexersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/library/add_series_ui.rs b/src/ui/sonarr_ui/library/add_series_ui.rs index f601532..a59e282 100644 --- a/src/ui/sonarr_ui/library/add_series_ui.rs +++ b/src/ui/sonarr_ui/library/add_series_ui.rs @@ -1,13 +1,13 @@ use std::sync::atomic::Ordering; +use ratatui::Frame; use ratatui::layout::{Constraint, Layout, Rect}; use ratatui::widgets::{Cell, ListItem, Row}; -use ratatui::Frame; -use crate::models::servarr_data::sonarr::modals::AddSeriesModal; -use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ADD_SERIES_BLOCKS}; -use crate::models::sonarr_models::AddSeriesSearchResult; use crate::models::Route; +use crate::models::servarr_data::sonarr::modals::AddSeriesModal; +use crate::models::servarr_data::sonarr::sonarr_data::{ADD_SERIES_BLOCKS, ActiveSonarrBlock}; +use crate::models::sonarr_models::AddSeriesSearchResult; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{ get_width_from_percentage, layout_block, layout_paragraph_borderless, title_block_centered, @@ -19,8 +19,8 @@ use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; -use crate::{render_selectable_input_box, App}; +use crate::ui::{DrawUi, draw_popup}; +use crate::{App, render_selectable_input_box}; #[cfg(test)] #[path = "add_series_ui_tests.rs"] @@ -30,11 +30,10 @@ pub(super) struct AddSeriesUi; impl DrawUi for AddSeriesUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return ADD_SERIES_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + ADD_SERIES_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { @@ -81,14 +80,14 @@ fn draw_add_series_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .add_series_search .as_ref() - .unwrap() + .expect("add_series_search must be populated") .text; let offset = app .data .sonarr_data .add_series_search .as_ref() - .unwrap() + .expect("add_series_search must be populated") .offset .load(Ordering::SeqCst); let search_results_row_mapping = |series: &AddSeriesSearchResult| { @@ -233,7 +232,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .add_searched_series .as_ref() - .unwrap() + .expect("add_searched_series must be populated") .current_selection() .title .text, @@ -242,7 +241,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .add_searched_series .as_ref() - .unwrap() + .expect("add_searched_series must be populated") .current_selection() .overview .clone() @@ -262,7 +261,12 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { use_season_folder, tags, .. - } = app.data.sonarr_data.add_series_modal.as_ref().unwrap(); + } = app + .data + .sonarr_data + .add_series_modal + .as_ref() + .expect("add_series_modal must exist in this context"); let selected_monitor = monitor_list.current_selection(); let selected_series_type = series_type_list.current_selection(); @@ -272,21 +276,31 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { f.render_widget(title_block_centered(&title), area); - let [paragraph_area, root_folder_area, monitor_area, quality_profile_area, language_profile_area, series_type_area, season_folder_area, tags_area, _, buttons_area] = - Layout::vertical([ - Constraint::Length(6), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Fill(1), - Constraint::Length(3), - ]) - .margin(1) - .areas(area); + let [ + paragraph_area, + root_folder_area, + monitor_area, + quality_profile_area, + language_profile_area, + series_type_area, + season_folder_area, + tags_area, + _, + buttons_area, + ] = Layout::vertical([ + Constraint::Length(6), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) + .margin(1) + .areas(area); let prompt_paragraph = layout_paragraph_borderless(&prompt); f.render_widget(prompt_paragraph, paragraph_area); @@ -358,7 +372,7 @@ fn draw_add_series_select_monitor_popup(f: &mut Frame<'_>, app: &mut App<'_>) { .sonarr_data .add_series_modal .as_mut() - .unwrap() + .expect("add_series_modal must exist in this context") .monitor_list, |monitor| ListItem::new(monitor.to_display_str().to_owned()), ); @@ -374,7 +388,7 @@ fn draw_add_series_select_series_type_popup(f: &mut Frame<'_>, app: &mut App<'_> .sonarr_data .add_series_modal .as_mut() - .unwrap() + .expect("add_series_modal must exist in this context") .series_type_list, |series_type| ListItem::new(series_type.to_display_str().to_owned()), ); @@ -390,7 +404,7 @@ fn draw_add_series_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App .sonarr_data .add_series_modal .as_mut() - .unwrap() + .expect("add_series_modal must exist in this context") .quality_profile_list, |quality_profile| ListItem::new(quality_profile.clone()), ); @@ -406,7 +420,7 @@ fn draw_add_series_select_language_profile_popup(f: &mut Frame<'_>, app: &mut Ap .sonarr_data .add_series_modal .as_mut() - .unwrap() + .expect("add_series_modal must exist in this context") .language_profile_list, |language_profile| ListItem::new(language_profile.clone()), ); @@ -422,7 +436,7 @@ fn draw_add_series_select_root_folder_popup(f: &mut Frame<'_>, app: &mut App<'_> .sonarr_data .add_series_modal .as_mut() - .unwrap() + .expect("add_series_modal must exist in this context") .root_folder_list, |root_folder| ListItem::new(root_folder.path.to_owned()), ); diff --git a/src/ui/sonarr_ui/library/add_series_ui_tests.rs b/src/ui/sonarr_ui/library/add_series_ui_tests.rs index 6bd15cd..40974db 100644 --- a/src/ui/sonarr_ui/library/add_series_ui_tests.rs +++ b/src/ui/sonarr_ui/library/add_series_ui_tests.rs @@ -2,9 +2,12 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ADD_SERIES_BLOCKS}; - use crate::ui::sonarr_ui::library::add_series_ui::AddSeriesUi; + use crate::app::App; + use crate::models::HorizontallyScrollableText; + use crate::models::servarr_data::sonarr::sonarr_data::{ADD_SERIES_BLOCKS, ActiveSonarrBlock}; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::library::add_series_ui::AddSeriesUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_add_series_ui_accepts() { @@ -16,4 +19,53 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::ADD_SERIES_SELECTION_BLOCKS; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_add_series_ui_renders_loading_search() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchResults.into()); + app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AddSeriesUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_add_series_ui_renders( + #[values( + ActiveSonarrBlock::AddSeriesAlreadyInLibrary, + ActiveSonarrBlock::AddSeriesEmptySearchResults, + ActiveSonarrBlock::AddSeriesPrompt, + ActiveSonarrBlock::AddSeriesSearchResults, + ActiveSonarrBlock::AddSeriesSelectLanguageProfile, + ActiveSonarrBlock::AddSeriesSelectMonitor, + ActiveSonarrBlock::AddSeriesSelectQualityProfile, + ActiveSonarrBlock::AddSeriesSelectRootFolder, + ActiveSonarrBlock::AddSeriesSelectSeriesType + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + app.data.sonarr_data.selected_block = BlockSelectionState::new(ADD_SERIES_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + AddSeriesUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("add_series_ui_{active_sonarr_block}"), output); + } + } } diff --git a/src/ui/sonarr_ui/library/delete_series_ui.rs b/src/ui/sonarr_ui/library/delete_series_ui.rs index 13e8ebb..c5e33b0 100644 --- a/src/ui/sonarr_ui/library/delete_series_ui.rs +++ b/src/ui/sonarr_ui/library/delete_series_ui.rs @@ -1,13 +1,13 @@ -use ratatui::layout::Rect; use ratatui::Frame; +use ratatui::layout::Rect; use crate::app::App; -use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS}; use crate::models::Route; +use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS}; +use crate::ui::DrawUi; use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::DrawUi; #[cfg(test)] #[path = "delete_series_ui_tests.rs"] @@ -17,11 +17,10 @@ pub(super) struct DeleteSeriesUi; impl DrawUi for DeleteSeriesUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return DELETE_SERIES_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + DELETE_SERIES_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { diff --git a/src/ui/sonarr_ui/library/delete_series_ui_tests.rs b/src/ui/sonarr_ui/library/delete_series_ui_tests.rs index 17c61b1..a28501e 100644 --- a/src/ui/sonarr_ui/library/delete_series_ui_tests.rs +++ b/src/ui/sonarr_ui/library/delete_series_ui_tests.rs @@ -2,9 +2,14 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS}; - use crate::ui::sonarr_ui::library::delete_series_ui::DeleteSeriesUi; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::{ + ActiveSonarrBlock, DELETE_SERIES_BLOCKS, DELETE_SERIES_SELECTION_BLOCKS, + }; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::library::delete_series_ui::DeleteSeriesUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_delete_series_ui_accepts() { @@ -16,4 +21,24 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + + use super::*; + + #[test] + fn test_delete_series_ui_renders_delete_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::DeleteSeriesPrompt.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(DELETE_SERIES_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + DeleteSeriesUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/library/edit_series_ui.rs b/src/ui/sonarr_ui/library/edit_series_ui.rs index 9307235..40c7f45 100644 --- a/src/ui/sonarr_ui/library/edit_series_ui.rs +++ b/src/ui/sonarr_ui/library/edit_series_ui.rs @@ -1,16 +1,16 @@ use std::sync::atomic::Ordering; +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::prelude::Layout; use ratatui::widgets::ListItem; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::sonarr::modals::EditSeriesModal; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EDIT_SERIES_BLOCKS, SERIES_DETAILS_BLOCKS, }; -use crate::models::Route; use crate::render_selectable_input_box; use crate::ui::styles::ManagarrStyle; @@ -20,7 +20,7 @@ use crate::ui::widgets::checkbox::Checkbox; use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; use super::series_details_ui::SeriesDetailsUi; @@ -32,19 +32,18 @@ pub(super) struct EditSeriesUi; impl DrawUi for EditSeriesUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return EDIT_SERIES_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + EDIT_SERIES_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { if let Route::Sonarr(active_sonarr_block, context_option) = app.get_current_route() { - if let Some(context) = context_option { - if SERIES_DETAILS_BLOCKS.contains(&context) { - draw_popup(f, app, SeriesDetailsUi::draw, Size::Large); - } + if let Some(context) = context_option + && SERIES_DETAILS_BLOCKS.contains(&context) + { + draw_popup(f, app, SeriesDetailsUi::draw, Size::Large); } let draw_edit_series_prompt = |f: &mut Frame<'_>, app: &mut App<'_>, prompt_area: Rect| { @@ -100,26 +99,41 @@ fn draw_edit_series_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, ar use_season_folders, path, tags, - } = app.data.sonarr_data.edit_series_modal.as_ref().unwrap(); + } = app + .data + .sonarr_data + .edit_series_modal + .as_ref() + .expect("edit_series_modal must exist in this context"); let selected_series_type = series_type_list.current_selection(); let selected_quality_profile = quality_profile_list.current_selection(); let selected_language_profile = language_profile_list.current_selection(); - let [paragraph_area, monitored_area, season_folder_area, quality_profile_area, language_profile_area, series_type_area, path_area, tags_area, _, buttons_area] = - Layout::vertical([ - Constraint::Length(6), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Fill(1), - Constraint::Length(3), - ]) - .margin(1) - .areas(area); + let [ + paragraph_area, + monitored_area, + season_folder_area, + quality_profile_area, + language_profile_area, + series_type_area, + path_area, + tags_area, + _, + buttons_area, + ] = Layout::vertical([ + Constraint::Length(6), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) + .margin(1) + .areas(area); let [save_area, cancel_area] = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) .areas(buttons_area); @@ -193,7 +207,7 @@ fn draw_edit_series_select_series_type_popup(f: &mut Frame<'_>, app: &mut App<'_ .sonarr_data .edit_series_modal .as_mut() - .unwrap() + .expect("edit_series_modal must exist in this context") .series_type_list, |series_type| ListItem::new(series_type.to_display_str().to_owned()), ); @@ -209,7 +223,7 @@ fn draw_edit_series_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut Ap .sonarr_data .edit_series_modal .as_mut() - .unwrap() + .expect("edit_series_modal must exist in this context") .quality_profile_list, |quality_profile| ListItem::new(quality_profile.clone()), ); @@ -225,7 +239,7 @@ fn draw_edit_series_select_language_profile_popup(f: &mut Frame<'_>, app: &mut A .sonarr_data .edit_series_modal .as_mut() - .unwrap() + .expect("edit_series_modal must exist in this context") .language_profile_list, |language_profile| ListItem::new(language_profile.clone()), ); diff --git a/src/ui/sonarr_ui/library/edit_series_ui_tests.rs b/src/ui/sonarr_ui/library/edit_series_ui_tests.rs index c138fa1..c6961db 100644 --- a/src/ui/sonarr_ui/library/edit_series_ui_tests.rs +++ b/src/ui/sonarr_ui/library/edit_series_ui_tests.rs @@ -2,9 +2,14 @@ mod tests { use strum::IntoEnumIterator; - use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_SERIES_BLOCKS}; - use crate::ui::sonarr_ui::library::edit_series_ui::EditSeriesUi; + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::{ + ActiveSonarrBlock, EDIT_SERIES_BLOCKS, EDIT_SERIES_SELECTION_BLOCKS, + }; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::library::edit_series_ui::EditSeriesUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_edit_series_ui_accepts() { @@ -16,4 +21,59 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveSonarrBlock::EditSeriesPrompt, None)] + #[case(ActiveSonarrBlock::EditSeriesConfirmPrompt, None)] + #[case(ActiveSonarrBlock::EditSeriesSelectSeriesType, None)] + #[case(ActiveSonarrBlock::EditSeriesSelectQualityProfile, None)] + #[case(ActiveSonarrBlock::EditSeriesSelectLanguageProfile, None)] + #[case( + ActiveSonarrBlock::EditSeriesPrompt, + Some(ActiveSonarrBlock::SeriesDetails) + )] + #[case( + ActiveSonarrBlock::EditSeriesConfirmPrompt, + Some(ActiveSonarrBlock::SeriesDetails) + )] + #[case( + ActiveSonarrBlock::EditSeriesSelectSeriesType, + Some(ActiveSonarrBlock::SeriesDetails) + )] + #[case( + ActiveSonarrBlock::EditSeriesSelectQualityProfile, + Some(ActiveSonarrBlock::SeriesDetails) + )] + #[case( + ActiveSonarrBlock::EditSeriesSelectLanguageProfile, + Some(ActiveSonarrBlock::SeriesDetails) + )] + fn test_edit_series_ui_renders( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] context: Option, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack((active_sonarr_block, context).into()); + app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EditSeriesUi::draw(f, app, f.area()); + }); + + if let Some(context) = context { + insta::assert_snapshot!( + format!("edit_series_{active_sonarr_block}_{context}"), + output + ); + } else { + insta::assert_snapshot!(format!("edit_series_{active_sonarr_block}"), output); + } + } + } } diff --git a/src/ui/sonarr_ui/library/episode_details_ui.rs b/src/ui/sonarr_ui/library/episode_details_ui.rs index ad2c87d..af07c2f 100644 --- a/src/ui/sonarr_ui/library/episode_details_ui.rs +++ b/src/ui/sonarr_ui/library/episode_details_ui.rs @@ -1,10 +1,10 @@ use crate::app::App; +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::models::Route; use crate::ui::sonarr_ui::sonarr_ui_utils::{ create_download_failed_history_event_details, create_download_folder_imported_history_event_details, @@ -22,14 +22,14 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::{draw_popup, draw_tabs, DrawUi}; +use crate::ui::{DrawUi, draw_popup, draw_tabs}; use crate::utils::convert_to_gb; use chrono::Utc; +use ratatui::Frame; use ratatui::layout::{Alignment, Constraint, Layout, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::{Line, Span, Text}; use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; -use ratatui::Frame; use serde_json::Number; #[cfg(test)] @@ -40,84 +40,87 @@ pub(super) struct EpisodeDetailsUi; impl DrawUi for EpisodeDetailsUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return EPISODE_DETAILS_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + EPISODE_DETAILS_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { - if let Some(season_details_modal) = app.data.sonarr_data.season_details_modal.as_ref() { - if season_details_modal.episode_details_modal.is_some() { - if let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() { - let draw_episode_details_popup = - |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| { - let content_area = draw_tabs( - f, - popup_area, - "Episode Details", - &app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episode_details_modal - .as_ref() - .unwrap() - .episode_details_tabs, - ); - draw_episode_details_tabs(f, app, content_area); + if let Some(season_details_modal) = app.data.sonarr_data.season_details_modal.as_ref() + && season_details_modal.episode_details_modal.is_some() + && let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() + { + let draw_episode_details_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| { + let content_area = draw_tabs( + f, + popup_area, + "Episode Details", + &app + .data + .sonarr_data + .season_details_modal + .as_ref() + .expect("season_details_modal must exist in this context") + .episode_details_modal + .as_ref() + .expect("episode_details_modal must exist in this context") + .episode_details_tabs, + ); + draw_episode_details_tabs(f, app, content_area); - match active_sonarr_block { - ActiveSonarrBlock::AutomaticallySearchEpisodePrompt => { - let prompt = format!( - "Do you want to trigger an automatic search of your indexers for the episode: {}", - app.data.sonarr_data.season_details_modal.as_ref().unwrap().episodes.current_selection().title - ); - let confirmation_prompt = ConfirmationPrompt::new() - .title("Automatic Episode Search") - .prompt(&prompt) - .yes_no_value(app.data.sonarr_data.prompt_confirm); + match active_sonarr_block { + ActiveSonarrBlock::AutomaticallySearchEpisodePrompt => { + let prompt = format!( + "Do you want to trigger an automatic search of your indexers for the episode: {}", + app + .data + .sonarr_data + .season_details_modal + .as_ref() + .expect("season_details_modal must exist in this context") + .episodes + .current_selection() + .title + ); + let confirmation_prompt = ConfirmationPrompt::new() + .title("Automatic Episode Search") + .prompt(&prompt) + .yes_no_value(app.data.sonarr_data.prompt_confirm); - f.render_widget( - Popup::new(confirmation_prompt).size(Size::MediumPrompt), - f.area(), - ); - } - ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt => { - draw_manual_episode_search_confirm_prompt(f, app); - } - ActiveSonarrBlock::EpisodeHistoryDetails => { - draw_history_item_details_popup(f, app, popup_area); - } - _ => (), - } - }; - - draw_popup(f, app, draw_episode_details_popup, Size::Large); + f.render_widget( + Popup::new(confirmation_prompt).size(Size::MediumPrompt), + f.area(), + ); + } + ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt => { + draw_manual_episode_search_confirm_prompt(f, app); + } + ActiveSonarrBlock::EpisodeHistoryDetails => { + draw_history_item_details_popup(f, app, popup_area); + } + _ => (), } - } + }; + + draw_popup(f, app, draw_episode_details_popup, Size::Large); } } } pub fn draw_episode_details_tabs(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { - if let Some(season_details_modal) = app.data.sonarr_data.season_details_modal.as_ref() { - if let Some(episode_details_modal) = season_details_modal.episode_details_modal.as_ref() { - if let Route::Sonarr(active_sonarr_block, _) = episode_details_modal - .episode_details_tabs - .get_active_route() - { - match active_sonarr_block { - ActiveSonarrBlock::EpisodeDetails => draw_episode_details(f, app, area), - ActiveSonarrBlock::EpisodeHistory => draw_episode_history_table(f, app, area), - ActiveSonarrBlock::EpisodeFile => draw_file_info(f, app, area), - ActiveSonarrBlock::ManualEpisodeSearch => draw_episode_releases(f, app, area), - _ => (), - } - } + if let Some(season_details_modal) = app.data.sonarr_data.season_details_modal.as_ref() + && let Some(episode_details_modal) = season_details_modal.episode_details_modal.as_ref() + && let Route::Sonarr(active_sonarr_block, _) = episode_details_modal + .episode_details_tabs + .get_active_route() + { + match active_sonarr_block { + ActiveSonarrBlock::EpisodeDetails => draw_episode_details(f, app, area), + ActiveSonarrBlock::EpisodeHistory => draw_episode_history_table(f, app, area), + ActiveSonarrBlock::EpisodeFile => draw_file_info(f, app, area), + ActiveSonarrBlock::ManualEpisodeSearch => draw_episode_releases(f, app, area), + _ => (), } } } @@ -179,7 +182,7 @@ fn draw_episode_details(f: &mut Frame<'_>, app: &App<'_>, area: Rect) { .sonarr_data .season_details_modal .as_ref() - .unwrap() + .expect("season_details_modal must exist in this context") .episode_details_modal .is_none(), block, @@ -191,15 +194,20 @@ fn draw_episode_details(f: &mut Frame<'_>, app: &App<'_>, area: Rect) { fn draw_file_info(f: &mut Frame<'_>, app: &App<'_>, area: Rect) { match app.data.sonarr_data.season_details_modal.as_ref() { - Some(season_details_modal) => match season_details_modal.episode_details_modal.as_ref() { - Some(episode_details_modal) - if !episode_details_modal.file_details.is_empty() && !app.is_loading => - { - let file_info = episode_details_modal.file_details.to_owned(); - let audio_details = episode_details_modal.audio_details.to_owned(); - let video_details = episode_details_modal.video_details.to_owned(); - let [file_details_title_area, file_details_area, audio_details_title_area, audio_details_area, video_details_title_area, video_details_area] = - Layout::vertical([ + Some(season_details_modal) if !app.is_loading => { + match season_details_modal.episode_details_modal.as_ref() { + Some(episode_details_modal) if !episode_details_modal.file_details.is_empty() => { + let file_info = episode_details_modal.file_details.to_owned(); + let audio_details = episode_details_modal.audio_details.to_owned(); + let video_details = episode_details_modal.video_details.to_owned(); + let [ + file_details_title_area, + file_details_area, + audio_details_title_area, + audio_details_area, + video_details_title_area, + video_details_area, + ] = Layout::vertical([ Constraint::Length(2), Constraint::Length(5), Constraint::Length(1), @@ -209,36 +217,37 @@ fn draw_file_info(f: &mut Frame<'_>, app: &App<'_>, area: Rect) { ]) .areas(area); - let file_details_title_paragraph = - Paragraph::new("File Details".bold()).block(layout_block_top_border()); - let audio_details_title_paragraph = - Paragraph::new("Audio Details".bold()).block(borderless_block()); - let video_details_title_paragraph = - Paragraph::new("Video Details".bold()).block(borderless_block()); + let file_details_title_paragraph = + Paragraph::new("File Details".bold()).block(layout_block_top_border()); + let audio_details_title_paragraph = + Paragraph::new("Audio Details".bold()).block(borderless_block()); + let video_details_title_paragraph = + Paragraph::new("Video Details".bold()).block(borderless_block()); - let file_details = Text::from(file_info); - let audio_details = Text::from(audio_details); - let video_details = Text::from(video_details); + let file_details = Text::from(file_info); + let audio_details = Text::from(audio_details); + let video_details = Text::from(video_details); - let file_details_paragraph = Paragraph::new(file_details) - .block(layout_block_bottom_border()) - .wrap(Wrap { trim: false }); - let audio_details_paragraph = Paragraph::new(audio_details) - .block(layout_block_bottom_border()) - .wrap(Wrap { trim: false }); - let video_details_paragraph = Paragraph::new(video_details) - .block(borderless_block()) - .wrap(Wrap { trim: false }); + let file_details_paragraph = Paragraph::new(file_details) + .block(layout_block_bottom_border()) + .wrap(Wrap { trim: false }); + let audio_details_paragraph = Paragraph::new(audio_details) + .block(layout_block_bottom_border()) + .wrap(Wrap { trim: false }); + let video_details_paragraph = Paragraph::new(video_details) + .block(borderless_block()) + .wrap(Wrap { trim: false }); - f.render_widget(file_details_title_paragraph, file_details_title_area); - f.render_widget(file_details_paragraph, file_details_area); - f.render_widget(audio_details_title_paragraph, audio_details_title_area); - f.render_widget(audio_details_paragraph, audio_details_area); - f.render_widget(video_details_title_paragraph, video_details_title_area); - f.render_widget(video_details_paragraph, video_details_area); + f.render_widget(file_details_title_paragraph, file_details_title_area); + f.render_widget(file_details_paragraph, file_details_area); + f.render_widget(audio_details_title_paragraph, audio_details_title_area); + f.render_widget(audio_details_paragraph, audio_details_area); + f.render_widget(video_details_title_paragraph, video_details_title_area); + f.render_widget(video_details_paragraph, video_details_area); + } + _ => f.render_widget(layout_block_top_border(), area), } - _ => f.render_widget(layout_block_top_border(), area), - }, + } _ => f.render_widget( LoadingBlock::new(app.is_loading, layout_block_top_border()), area, @@ -301,10 +310,10 @@ fn draw_episode_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) .sonarr_data .season_details_modal .as_mut() - .unwrap() + .expect("season_details_modal must exist in this context") .episode_details_modal .as_mut() - .unwrap() + .expect("episode_details_modal must exist in this context") .episode_history; let history_table = ManagarrTable::new(Some(&mut episode_history_table), history_row_mapping) @@ -330,7 +339,7 @@ fn draw_episode_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) .sonarr_data .season_details_modal .as_ref() - .unwrap() + .expect("season_details_modal must exist in this context") .episode_details_modal .is_none(), layout_block_top_border(), @@ -476,10 +485,10 @@ fn draw_episode_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .season_details_modal .as_mut() - .unwrap() + .expect("season_details_modal must exist in this context") .episode_details_modal .as_mut() - .unwrap() + .expect("episode_details_modal must exist in this context") .episode_releases; let release_table = ManagarrTable::new( Some(&mut episode_release_table), @@ -515,7 +524,7 @@ fn draw_episode_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .season_details_modal .as_ref() - .unwrap() + .expect("season_details_modal must exist in this context") .episode_details_modal .is_none(), layout_block_top_border(), @@ -531,10 +540,10 @@ fn draw_manual_episode_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_ .sonarr_data .season_details_modal .as_ref() - .unwrap() + .expect("season_details_modal must exist in this context") .episode_details_modal .as_ref() - .unwrap() + .expect("episode_details_modal must exist in this context") .episode_releases .current_selection(); let title = if current_selection.rejected { @@ -604,10 +613,10 @@ fn style_from_status(download: Option<&DownloadRecord>, episode: &Episode) -> St return Style::new().unmonitored_missing(); } - if let Some(air_date) = episode.air_date_utc.as_ref() { - if air_date > &Utc::now() { - return Style::new().unreleased(); - } + if let Some(air_date) = episode.air_date_utc.as_ref() + && air_date > &Utc::now() + { + return Style::new().unreleased(); } return Style::new().missing(); diff --git a/src/ui/sonarr_ui/library/episode_details_ui_tests.rs b/src/ui/sonarr_ui/library/episode_details_ui_tests.rs index dc8e654..5eb2c4d 100644 --- a/src/ui/sonarr_ui/library/episode_details_ui_tests.rs +++ b/src/ui/sonarr_ui/library/episode_details_ui_tests.rs @@ -1,11 +1,14 @@ #[cfg(test)] mod tests { + use strum::IntoEnumIterator; + + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS, }; - use crate::ui::sonarr_ui::library::episode_details_ui::EpisodeDetailsUi; use crate::ui::DrawUi; - use strum::IntoEnumIterator; + use crate::ui::sonarr_ui::library::episode_details_ui::EpisodeDetailsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_episode_details_ui_accepts() { @@ -17,4 +20,124 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveSonarrBlock::EpisodeDetails, 0)] + #[case(ActiveSonarrBlock::EpisodeHistory, 1)] + #[case(ActiveSonarrBlock::EpisodeHistoryDetails, 1)] + #[case(ActiveSonarrBlock::EpisodeFile, 2)] + #[case(ActiveSonarrBlock::ManualEpisodeSearch, 3)] + #[case(ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt, 3)] + #[case(ActiveSonarrBlock::ManualEpisodeSearchSortPrompt, 3)] + #[case(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt, 0)] + #[case(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt, 1)] + #[case(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt, 2)] + #[case(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt, 3)] + fn test_episode_details_ui_renders( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + app + .data + .sonarr_data + .season_details_modal + .as_mut() + .unwrap() + .episode_details_modal + .as_mut() + .unwrap() + .episode_details_tabs + .set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EpisodeDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("episode_details_{active_sonarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveSonarrBlock::EpisodeDetails, 0)] + #[case(ActiveSonarrBlock::EpisodeHistory, 1)] + #[case(ActiveSonarrBlock::EpisodeFile, 2)] + #[case(ActiveSonarrBlock::ManualEpisodeSearch, 3)] + fn test_episode_details_ui_renders_loading( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(active_sonarr_block.into()); + app + .data + .sonarr_data + .season_details_modal + .as_mut() + .unwrap() + .episode_details_modal + .as_mut() + .unwrap() + .episode_details_tabs + .set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EpisodeDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("loading_episode_details_{active_sonarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveSonarrBlock::EpisodeDetails, 0)] + #[case(ActiveSonarrBlock::EpisodeHistory, 1)] + #[case(ActiveSonarrBlock::EpisodeHistoryDetails, 1)] + #[case(ActiveSonarrBlock::EpisodeFile, 2)] + #[case(ActiveSonarrBlock::ManualEpisodeSearch, 3)] + fn test_episode_details_ui_renders_empty( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + { + let episode_details_modal = app + .data + .sonarr_data + .season_details_modal + .as_mut() + .unwrap() + .episode_details_modal + .as_mut() + .unwrap(); + episode_details_modal.episode_details_tabs.set_index(index); + episode_details_modal.episode_details = Default::default(); + episode_details_modal.episode_history = Default::default(); + episode_details_modal.file_details = Default::default(); + episode_details_modal.episode_releases = Default::default(); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + EpisodeDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("empty_episode_details_{active_sonarr_block}_{index}"), + output + ); + } + } } diff --git a/src/ui/sonarr_ui/library/library_ui_tests.rs b/src/ui/sonarr_ui/library/library_ui_tests.rs index f740d39..7d65fdc 100644 --- a/src/ui/sonarr_ui/library/library_ui_tests.rs +++ b/src/ui/sonarr_ui/library/library_ui_tests.rs @@ -1,15 +1,15 @@ #[cfg(test)] mod tests { use crate::models::servarr_data::sonarr::sonarr_data::{ - ActiveSonarrBlock, ADD_SERIES_BLOCKS, DELETE_SERIES_BLOCKS, EDIT_SERIES_BLOCKS, + ADD_SERIES_BLOCKS, ActiveSonarrBlock, DELETE_SERIES_BLOCKS, EDIT_SERIES_BLOCKS, EPISODE_DETAILS_BLOCKS, SEASON_DETAILS_BLOCKS, SERIES_DETAILS_BLOCKS, }; use crate::models::{ servarr_data::sonarr::sonarr_data::LIBRARY_BLOCKS, sonarr_models::SeriesStatus, }; + use crate::ui::DrawUi; use crate::ui::sonarr_ui::library::LibraryUi; use crate::ui::styles::ManagarrStyle; - use crate::ui::DrawUi; use pretty_assertions::assert_eq; use ratatui::widgets::{Cell, Row}; use strum::IntoEnumIterator; @@ -134,8 +134,8 @@ mod tests { } #[test] - fn test_decorate_row_with_style_unreleased_when_continuing_and_all_monitored_episodes_are_present( - ) { + fn test_decorate_row_with_style_unreleased_when_continuing_and_all_monitored_episodes_are_present() + { let seasons = vec![ Season { monitored: false, @@ -245,4 +245,142 @@ mod tests { assert_eq!(style, row.indeterminate()); } + + mod snapshot_tests { + use crate::app::App; + use crate::models::BlockSelectionState; + use crate::models::servarr_data::sonarr::sonarr_data::{ + ADD_SERIES_SELECTION_BLOCKS, ActiveSonarrBlock, DELETE_SERIES_SELECTION_BLOCKS, + EDIT_SERIES_SELECTION_BLOCKS, + }; + use rstest::rstest; + + use crate::ui::DrawUi; + use crate::ui::sonarr_ui::library::LibraryUi; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; + + #[rstest] + fn test_library_ui_renders( + #[values( + ActiveSonarrBlock::Series, + ActiveSonarrBlock::SeriesSortPrompt, + ActiveSonarrBlock::SearchSeries, + ActiveSonarrBlock::SearchSeriesError, + ActiveSonarrBlock::FilterSeries, + ActiveSonarrBlock::FilterSeriesError, + ActiveSonarrBlock::UpdateAllSeriesPrompt + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("sonarr_library_{active_sonarr_block}"), output); + } + + #[test] + fn test_library_ui_renders_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::Series.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_empty() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveSonarrBlock::Series.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_series_details_over_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::SeriesDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_season_details_over_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::SeasonDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_episode_details_over_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EpisodeDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_delete_episode_over_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::DeleteSeriesPrompt.into()); + app.data.sonarr_data.selected_block = + BlockSelectionState::new(DELETE_SERIES_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_edit_series_over_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into()); + app.data.sonarr_data.selected_block = BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_library_ui_renders_add_series_over_series() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into()); + app.data.sonarr_data.selected_block = BlockSelectionState::new(ADD_SERIES_SELECTION_BLOCKS); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + LibraryUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/library/mod.rs b/src/ui/sonarr_ui/library/mod.rs index 2140743..cb7c6a9 100644 --- a/src/ui/sonarr_ui/library/mod.rs +++ b/src/ui/sonarr_ui/library/mod.rs @@ -2,9 +2,9 @@ use add_series_ui::AddSeriesUi; use delete_series_ui::DeleteSeriesUi; use edit_series_ui::EditSeriesUi; use ratatui::{ + Frame, layout::{Constraint, Rect}, widgets::{Cell, Row}, - Frame, }; use series_details_ui::SeriesDetailsUi; @@ -16,15 +16,15 @@ use crate::utils::convert_to_gb; use crate::{ app::App, models::{ + Route, servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, LIBRARY_BLOCKS}, sonarr_models::{Series, SeriesStatus}, - Route, }, ui::{ + DrawUi, styles::ManagarrStyle, utils::{get_width_from_percentage, layout_block_top_border}, widgets::managarr_table::ManagarrTable, - DrawUi, }, }; @@ -106,28 +106,21 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .map_or(0f64, |stats| convert_to_gb(stats.size_on_disk)); let quality_profile = quality_profile_map .get_by_left(&series.quality_profile_id) - .unwrap() + .expect("Quality profile ID must exist in quality_profile_map") .to_owned(); let language_profile = language_profile_map .get_by_left(&series.language_profile_id) - .unwrap() + .expect("Language profile ID must exist in language_profile_map") .to_owned(); - let empty_tag = String::new(); - let tags = if !series.tags.is_empty() { - series - .tags - .iter() - .map(|tag_id| { - tags_map - .get_by_left(&tag_id.as_i64().unwrap()) - .unwrap_or(&empty_tag) - .clone() - }) - .collect::>() - .join(", ") - } else { - String::new() - }; + let tags = series + .tags + .iter() + .filter_map(|tag_id| { + let id = tag_id.as_i64()?; + tags_map.get_by_left(&id).cloned() + }) + .collect::>() + .join(", "); decorate_series_row_with_style( series, diff --git a/src/ui/sonarr_ui/library/season_details_ui.rs b/src/ui/sonarr_ui/library/season_details_ui.rs index c1a5cf0..aea91bd 100644 --- a/src/ui/sonarr_ui/library/season_details_ui.rs +++ b/src/ui/sonarr_ui/library/season_details_ui.rs @@ -1,9 +1,9 @@ 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, }; -use crate::models::Route; use crate::ui::sonarr_ui::library::episode_details_ui::EpisodeDetailsUi; use crate::ui::sonarr_ui::sonarr_ui_utils::{ create_download_failed_history_event_details, @@ -21,13 +21,13 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::{draw_popup, draw_tabs, DrawUi}; +use crate::ui::{DrawUi, draw_popup, draw_tabs}; use crate::utils::convert_to_gb; use chrono::Utc; +use ratatui::Frame; use ratatui::layout::{Alignment, Constraint, Rect}; use ratatui::prelude::{Line, Style, Stylize, Text}; use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; -use ratatui::Frame; use serde_json::Number; #[cfg(test)] @@ -38,111 +38,115 @@ pub(super) struct SeasonDetailsUi; impl DrawUi for SeasonDetailsUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return EpisodeDetailsUi::accepts(route) - || SEASON_DETAILS_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + EpisodeDetailsUi::accepts(route) || SEASON_DETAILS_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { let route = app.get_current_route(); - if app.data.sonarr_data.season_details_modal.is_some() { - if let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() { - let draw_season_details_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| { - let content_area = draw_tabs( - f, - popup_area, - &format!( - "Season {} Details", + if app.data.sonarr_data.season_details_modal.is_some() + && let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() + { + let draw_season_details_popup = |f: &mut Frame<'_>, app: &mut App<'_>, popup_area: Rect| { + let content_area = draw_tabs( + f, + popup_area, + &format!( + "Season {} Details", + app + .data + .sonarr_data + .seasons + .current_selection() + .season_number + ), + &app + .data + .sonarr_data + .season_details_modal + .as_ref() + .expect("season_details_modal must exist in this context") + .season_details_tabs, + ); + draw_season_details(f, app, content_area); + + match active_sonarr_block { + ActiveSonarrBlock::AutomaticallySearchSeasonPrompt => { + let prompt = format!( + "Do you want to trigger an automatic search of your indexers for season packs for: {}", app .data .sonarr_data .seasons .current_selection() - .season_number - ), - &app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .season_details_tabs, - ); - draw_season_details(f, app, content_area); + .title + .as_ref() + .unwrap() + ); + let confirmation_prompt = ConfirmationPrompt::new() + .title("Automatic Season Search") + .prompt(&prompt) + .yes_no_value(app.data.sonarr_data.prompt_confirm); - match active_sonarr_block { - ActiveSonarrBlock::AutomaticallySearchSeasonPrompt => { - let prompt = format!( - "Do you want to trigger an automatic search of your indexers for season packs for: {}", - app.data.sonarr_data.seasons.current_selection().title.as_ref().unwrap() - ); - let confirmation_prompt = ConfirmationPrompt::new() - .title("Automatic Season Search") - .prompt(&prompt) - .yes_no_value(app.data.sonarr_data.prompt_confirm); - - f.render_widget( - Popup::new(confirmation_prompt).size(Size::MediumPrompt), - f.area(), - ); - } - ActiveSonarrBlock::DeleteEpisodeFilePrompt => { - let prompt = format!( - "Do you really want to delete this episode: \n{}?", - app - .data - .sonarr_data - .season_details_modal - .as_ref() - .unwrap() - .episodes - .current_selection() - .title - ); - let confirmation_prompt = ConfirmationPrompt::new() - .title("Delete Episode") - .prompt(&prompt) - .yes_no_value(app.data.sonarr_data.prompt_confirm); - - f.render_widget( - Popup::new(confirmation_prompt).size(Size::MediumPrompt), - f.area(), - ); - } - ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt => { - draw_manual_season_search_confirm_prompt(f, app); - } - ActiveSonarrBlock::SeasonHistoryDetails => { - draw_history_item_details_popup(f, app, popup_area); - } - _ => (), + f.render_widget( + Popup::new(confirmation_prompt).size(Size::MediumPrompt), + f.area(), + ); } - }; + ActiveSonarrBlock::DeleteEpisodeFilePrompt => { + let prompt = format!( + "Do you really want to delete this episode: \n{}?", + app + .data + .sonarr_data + .season_details_modal + .as_ref() + .expect("season_details_modal must exist in this context") + .episodes + .current_selection() + .title + ); + let confirmation_prompt = ConfirmationPrompt::new() + .title("Delete Episode") + .prompt(&prompt) + .yes_no_value(app.data.sonarr_data.prompt_confirm); - draw_popup(f, app, draw_season_details_popup, Size::XLarge); - - if EpisodeDetailsUi::accepts(route) { - EpisodeDetailsUi::draw(f, app, _area); + f.render_widget( + Popup::new(confirmation_prompt).size(Size::MediumPrompt), + f.area(), + ); + } + ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt => { + draw_manual_season_search_confirm_prompt(f, app); + } + ActiveSonarrBlock::SeasonHistoryDetails => { + draw_history_item_details_popup(f, app, popup_area); + } + _ => (), } + }; + + draw_popup(f, app, draw_season_details_popup, Size::XLarge); + + if EpisodeDetailsUi::accepts(route) { + EpisodeDetailsUi::draw(f, app, _area); } } } } pub fn draw_season_details(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { - if let Some(season_details_modal) = app.data.sonarr_data.season_details_modal.as_ref() { - if let Route::Sonarr(active_sonarr_block, _) = + if let Some(season_details_modal) = app.data.sonarr_data.season_details_modal.as_ref() + && let Route::Sonarr(active_sonarr_block, _) = season_details_modal.season_details_tabs.get_active_route() - { - match active_sonarr_block { - ActiveSonarrBlock::SeasonDetails => draw_episodes_table(f, app, area), - ActiveSonarrBlock::SeasonHistory => draw_season_history_table(f, app, area), - ActiveSonarrBlock::ManualSeasonSearch => draw_season_releases(f, app, area), - _ => (), - } + { + match active_sonarr_block { + ActiveSonarrBlock::SeasonDetails => draw_episodes_table(f, app, area), + ActiveSonarrBlock::SeasonHistory => draw_season_history_table(f, app, area), + ActiveSonarrBlock::ManualSeasonSearch => draw_season_releases(f, app, area), + _ => (), } } } @@ -296,7 +300,7 @@ fn draw_season_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .season_details_modal .as_mut() - .unwrap() + .expect("season_details_modal must exist in this context") .season_history; let history_table = ManagarrTable::new(Some(&mut season_history_table), history_row_mapping) @@ -432,7 +436,7 @@ fn draw_season_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .sonarr_data .season_details_modal .as_mut() - .unwrap() + .expect("season_details_modal must exist in this context") .season_releases; let release_table = ManagarrTable::new(Some(&mut season_release_table), season_release_row_mapping) @@ -473,7 +477,7 @@ fn draw_manual_season_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_> .sonarr_data .season_details_modal .as_ref() - .unwrap() + .expect("season_details_modal must exist in this context") .season_releases .current_selection(); let title = if current_selection.rejected { @@ -598,10 +602,10 @@ fn decorate_with_row_style<'a>( return row.unmonitored_missing(); } - if let Some(air_date) = episode.air_date_utc.as_ref() { - if air_date > &Utc::now() { - return row.unreleased(); - } + if let Some(air_date) = episode.air_date_utc.as_ref() + && air_date > &Utc::now() + { + return row.unreleased(); } return row.missing(); diff --git a/src/ui/sonarr_ui/library/season_details_ui_tests.rs b/src/ui/sonarr_ui/library/season_details_ui_tests.rs index 7145fbc..26cd503 100644 --- a/src/ui/sonarr_ui/library/season_details_ui_tests.rs +++ b/src/ui/sonarr_ui/library/season_details_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS, SEASON_DETAILS_BLOCKS, }; - use crate::ui::sonarr_ui::library::season_details_ui::SeasonDetailsUi; + use crate::models::stateful_table::StatefulTable; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::library::season_details_ui::SeasonDetailsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_season_details_ui_accepts() { @@ -21,4 +24,125 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveSonarrBlock::SeasonDetails, 0)] + #[case(ActiveSonarrBlock::SeasonHistory, 1)] + #[case(ActiveSonarrBlock::SearchEpisodes, 0)] + #[case(ActiveSonarrBlock::SearchEpisodesError, 0)] + #[case(ActiveSonarrBlock::AutomaticallySearchSeasonPrompt, 0)] + #[case(ActiveSonarrBlock::AutomaticallySearchSeasonPrompt, 1)] + #[case(ActiveSonarrBlock::AutomaticallySearchSeasonPrompt, 2)] + #[case(ActiveSonarrBlock::SearchSeasonHistory, 1)] + #[case(ActiveSonarrBlock::SearchSeasonHistoryError, 1)] + #[case(ActiveSonarrBlock::FilterSeasonHistory, 1)] + #[case(ActiveSonarrBlock::FilterSeasonHistoryError, 1)] + #[case(ActiveSonarrBlock::SeasonHistorySortPrompt, 1)] + #[case(ActiveSonarrBlock::SeasonHistoryDetails, 1)] + #[case(ActiveSonarrBlock::ManualSeasonSearch, 2)] + #[case(ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt, 2)] + #[case(ActiveSonarrBlock::ManualSeasonSearchSortPrompt, 2)] + #[case(ActiveSonarrBlock::DeleteEpisodeFilePrompt, 0)] + fn test_season_details_ui_renders( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + app + .data + .sonarr_data + .season_details_modal + .as_mut() + .unwrap() + .season_details_tabs + .set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeasonDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("season_details_renders_{active_sonarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveSonarrBlock::SeasonDetails, 0)] + #[case(ActiveSonarrBlock::SeasonHistory, 1)] + #[case(ActiveSonarrBlock::SeasonHistoryDetails, 1)] + #[case(ActiveSonarrBlock::ManualSeasonSearch, 2)] + fn test_season_details_ui_renders_loading( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(active_sonarr_block.into()); + { + let season_details_modal = app.data.sonarr_data.season_details_modal.as_mut().unwrap(); + season_details_modal.season_releases = StatefulTable::default(); + season_details_modal.season_history = StatefulTable::default(); + season_details_modal.episodes = StatefulTable::default(); + season_details_modal.season_details_tabs.set_index(index); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeasonDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("loading_season_details_{active_sonarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveSonarrBlock::SeasonDetails, 0)] + #[case(ActiveSonarrBlock::SeasonHistory, 1)] + #[case(ActiveSonarrBlock::SeasonHistoryDetails, 1)] + #[case(ActiveSonarrBlock::ManualSeasonSearch, 2)] + fn test_season_details_ui_renders_empty( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + { + let season_details_modal = app.data.sonarr_data.season_details_modal.as_mut().unwrap(); + season_details_modal.season_releases = StatefulTable::default(); + season_details_modal.season_history = StatefulTable::default(); + season_details_modal.episodes = StatefulTable::default(); + season_details_modal.season_details_tabs.set_index(index); + } + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeasonDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("empty_season_details_{active_sonarr_block}_{index}"), + output + ); + } + + #[test] + fn test_season_details_ui_renders_episode_details_over_season_details() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EpisodeDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeasonDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/library/series_details_ui.rs b/src/ui/sonarr_ui/library/series_details_ui.rs index 0f18c0f..b395ee2 100644 --- a/src/ui/sonarr_ui/library/series_details_ui.rs +++ b/src/ui/sonarr_ui/library/series_details_ui.rs @@ -1,18 +1,18 @@ use chrono::Utc; use deunicode::deunicode; +use ratatui::Frame; use ratatui::layout::{Alignment, Constraint, Layout, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::text::{Line, Text}; use ratatui::widgets::{Cell, Paragraph, Row, Wrap}; -use ratatui::Frame; 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::Route; 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::{ @@ -31,7 +31,7 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::message::Message; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::{draw_popup, draw_tabs, DrawUi}; +use crate::ui::{DrawUi, draw_popup, draw_tabs}; use crate::utils::convert_to_gb; #[cfg(test)] @@ -42,13 +42,12 @@ pub(super) struct SeriesDetailsUi; impl DrawUi for SeriesDetailsUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return SeasonDetailsUi::accepts(route) - || EpisodeDetailsUi::accepts(route) - || SERIES_DETAILS_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + SeasonDetailsUi::accepts(route) + || EpisodeDetailsUi::accepts(route) + || SERIES_DETAILS_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { @@ -75,7 +74,8 @@ impl DrawUi for SeriesDetailsUi { match active_sonarr_block { ActiveSonarrBlock::AutomaticallySearchSeriesPrompt => { let prompt = format!( - "Do you want to trigger an automatic search of your indexers for all monitored episode(s) for the series: {}", app.data.sonarr_data.series.current_selection().title + "Do you want to trigger an automatic search of your indexers for all monitored episode(s) for the series: {}", + app.data.sonarr_data.series.current_selection().title ); let confirmation_prompt = ConfirmationPrompt::new() .title("Automatic Series Search") @@ -252,7 +252,7 @@ fn draw_seasons_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { let row = Row::new(vec![ Cell::from(season_monitored.to_owned()), - Cell::from(title.clone().unwrap()), + Cell::from(title.clone().unwrap_or_default()), Cell::from(format!("{episode_file_count}/{episode_count}")), Cell::from(format!("{size:.2} GB")), ]); @@ -339,7 +339,12 @@ fn draw_series_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { ]) .primary() }; - let mut series_history_table = app.data.sonarr_data.series_history.as_mut().unwrap(); + let mut series_history_table = app + .data + .sonarr_data + .series_history + .as_mut() + .expect("series_history must be populated"); let history_table = ManagarrTable::new(Some(&mut series_history_table), history_row_mapping) .block(layout_block_top_border()) diff --git a/src/ui/sonarr_ui/library/series_details_ui_tests.rs b/src/ui/sonarr_ui/library/series_details_ui_tests.rs index 9923c87..85ab39c 100644 --- a/src/ui/sonarr_ui/library/series_details_ui_tests.rs +++ b/src/ui/sonarr_ui/library/series_details_ui_tests.rs @@ -2,11 +2,13 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS, SEASON_DETAILS_BLOCKS, SERIES_DETAILS_BLOCKS, }; - use crate::ui::sonarr_ui::library::series_details_ui::SeriesDetailsUi; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::library::series_details_ui::SeriesDetailsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_series_details_ui_accepts() { @@ -22,4 +24,115 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::models::stateful_table::StatefulTable; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveSonarrBlock::SeriesDetails, 0)] + #[case(ActiveSonarrBlock::SeriesHistory, 1)] + #[case(ActiveSonarrBlock::SearchSeason, 0)] + #[case(ActiveSonarrBlock::SearchSeasonError, 0)] + #[case(ActiveSonarrBlock::UpdateAndScanSeriesPrompt, 0)] + #[case(ActiveSonarrBlock::UpdateAndScanSeriesPrompt, 1)] + #[case(ActiveSonarrBlock::AutomaticallySearchSeriesPrompt, 0)] + #[case(ActiveSonarrBlock::AutomaticallySearchSeriesPrompt, 1)] + #[case(ActiveSonarrBlock::SearchSeriesHistory, 1)] + #[case(ActiveSonarrBlock::SearchSeriesHistoryError, 1)] + #[case(ActiveSonarrBlock::FilterSeriesHistory, 1)] + #[case(ActiveSonarrBlock::FilterSeriesHistoryError, 1)] + #[case(ActiveSonarrBlock::SeriesHistorySortPrompt, 1)] + #[case(ActiveSonarrBlock::SeriesHistoryDetails, 1)] + fn test_series_details_ui_renders_series_details( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + app.data.sonarr_data.series_info_tabs.set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeriesDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("series_details_ui_{active_sonarr_block}_{index}"), + output + ); + } + + #[rstest] + #[case(ActiveSonarrBlock::SeriesDetails, 0)] + #[case(ActiveSonarrBlock::SeriesHistory, 1)] + fn test_series_details_ui_renders_series_details_loading( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + app.data.sonarr_data.series_info_tabs.set_index(index); + app.is_loading = true; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeriesDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("loading_series_details_{active_sonarr_block}"), + output + ); + } + + #[rstest] + #[case(ActiveSonarrBlock::SeriesDetails, 0)] + #[case(ActiveSonarrBlock::SeriesHistory, 1)] + #[case(ActiveSonarrBlock::SeriesHistoryDetails, 1)] + fn test_series_details_ui_renders_series_details_empty( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.data.sonarr_data.seasons = StatefulTable::default(); + app.data.sonarr_data.series_history = Some(StatefulTable::default()); + app.data.sonarr_data.series_info_tabs.set_index(index); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeriesDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("empty_series_details_{active_sonarr_block}"), + output + ); + } + + #[test] + fn test_series_details_ui_renders_season_details_over_series_details() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::SeasonDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeriesDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_series_details_ui_renders_episode_details_over_series_details() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::EpisodeDetails.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SeriesDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + } } diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesAlreadyInLibrary.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesAlreadyInLibrary.snap new file mode 100644 index 0000000..d39b8d2 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesAlreadyInLibrary.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Series ─────────────────────────────────────────────────────╮ + │something │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ✔ Title Year Network Seasons Rating Genres │ + │=> Test 2023 Prime Video 8.4 3 cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Error ───────────────╮ │ + │ │This series is already in your library │ │ + │ │ │ │ + │ ╰───────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesEmptySearchResults.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesEmptySearchResults.snap new file mode 100644 index 0000000..9a5e62e --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesEmptySearchResults.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Series ─────────────────────────────────────────────────────╮ + │something │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Error ───────────────╮ │ + │ │ No series found matching your query! │ │ + │ │ │ │ + │ ╰───────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesPrompt.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesPrompt.snap new file mode 100644 index 0000000..2c83b81 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │Bluray-1080p ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Language Profile: │English ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Series Type: │Standard ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSearchResults.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSearchResults.snap new file mode 100644 index 0000000..1dea6ec --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSearchResults.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Series ─────────────────────────────────────────────────────╮ + │something │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ ✔ Title Year Network Seasons Rating Genres │ + │=> Test 2023 Prime Video 8.4 3 cool, family, fun │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectLanguageProfile.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectLanguageProfile.snap new file mode 100644 index 0000000..68859e7 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectLanguageProfile.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╭───────────────────────────────╮──────────────────────────────╯ │ │ + │ │ │English │──────────────────────────────╮ │ │ + │ │ Qual│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ Langu│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │ │ │ + │ │ Se│ │ │ │ + │ │ │ │ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ ╰───────────────────────────────╯ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectMonitor.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectMonitor.snap new file mode 100644 index 0000000..0e76f39 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectMonitor.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╭───────────────────────────────╮──────────────────────────────╯ │ │ + │ │ │All Episodes │──────────────────────────────╮ │ │ + │ │ Qual│Unknown │ ▼ │ │ │ + │ │ │Future Episodes │──────────────────────────────╯ │ │ + │ │ │Missing Episodes │──────────────────────────────╮ │ │ + │ │ Langu│Existing Episodes │ ▼ │ │ │ + │ │ │Only First Season │──────────────────────────────╯ │ │ + │ │ │Only Last Season │──────────────────────────────╮ │ │ + │ │ │Only Latest Season │ ▼ │ │ │ + │ │ │Pilot Episode │──────────────────────────────╯ │ │ + │ │ │Recent Episodes │ │ │ + │ │ Se│Only Specials │ │ │ + │ │ │Not Specials │ │ │ + │ │ │None │──────────────────────────────╮ │ │ + │ │ ╰───────────────────────────────╯ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectQualityProfile.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectQualityProfile.snap new file mode 100644 index 0000000..dcc57ae --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectQualityProfile.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╭───────────────────────────────╮──────────────────────────────╯ │ │ + │ │ │Bluray-1080p │──────────────────────────────╮ │ │ + │ │ Qual│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ Langu│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │ │ │ + │ │ Se│ │ │ │ + │ │ │ │ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ ╰───────────────────────────────╯ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectRootFolder.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectRootFolder.snap new file mode 100644 index 0000000..924f085 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectRootFolder.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╭───────────────────────────────╮──────────────────────────────╯ │ │ + │ │ │/nfs │──────────────────────────────╮ │ │ + │ │ Qual│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ Langu│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │ │ │ + │ │ Se│ │ │ │ + │ │ │ │ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ ╰───────────────────────────────╯ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectSeriesType.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectSeriesType.snap new file mode 100644 index 0000000..7434c27 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_AddSeriesSelectSeriesType.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╭───────────────────────────────╮──────────────────────────────╯ │ │ + │ │ │Standard │──────────────────────────────╮ │ │ + │ │ Qual│Daily │ ▼ │ │ │ + │ │ │Anime │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ Langu│ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ │ │ ▼ │ │ │ + │ │ │ │──────────────────────────────╯ │ │ + │ │ │ │ │ │ + │ │ Se│ │ │ │ + │ │ │ │ │ │ + │ │ │ │──────────────────────────────╮ │ │ + │ │ ╰───────────────────────────────╯ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_renders_loading_search.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_renders_loading_search.snap new file mode 100644 index 0000000..07dcfec --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__add_series_ui__add_series_ui_tests__tests__snapshot_tests__add_series_ui_renders_loading_search.snap @@ -0,0 +1,47 @@ +--- +source: src/ui/sonarr_ui/library/add_series_ui_tests.rs +expression: output +--- + + + + + + + + ╭───────────────────────────────────────────────────── Add Series ─────────────────────────────────────────────────────╮ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__delete_series_ui__delete_series_ui_tests__tests__snapshot_tests__delete_series_ui_renders_delete_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__delete_series_ui__delete_series_ui_tests__tests__snapshot_tests__delete_series_ui_renders_delete_series.snap new file mode 100644 index 0000000..84ece76 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__delete_series_ui__delete_series_ui_tests__tests__snapshot_tests__delete_series_ui_renders_delete_series.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/library/delete_series_ui_tests.rs +expression: output +--- + + + + + + + + + + + + + + + + + ╭───────────────────── Delete Series ─────────────────────╮ + │ Do you really want to delete the series: │ + │ Test? │ + │ │ + │ │ + │ ╭───╮ │ + │ Delete Series File: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Add List Exclusion: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesConfirmPrompt.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesConfirmPrompt.snap new file mode 100644 index 0000000..fd06895 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesConfirmPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + + + + ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Season Folder: │ ✔ │ │ + │ ╰───╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Quality Profile: │Bluray-1080p ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Language Profile: │English ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Series Type: │Standard ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Path: │/nfs/tv │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesConfirmPrompt_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesConfirmPrompt_SeriesDetails.snap new file mode 100644 index 0000000..be8a8fe --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesConfirmPrompt_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ │ + │Status: Continuing │ Blah blah blah │ │ + │Genres: cool, famil│ │ │ + │Rating: 84% │ │ │ + │Year: 2022 │ │ │ + │Runtime: 63 minutes│ │ │ + │Path: /nfs/tv/Test │ │ │ + │Quality Profile: Bl│ ╭───╮ │ │ + │Language Profile: E│ Monitored: │ ✔ │ │ │ + │Monitored: Yes │ ╰───╯ │ │ + │Size on Disk: 59.51│ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │╭ Series Details │ Quality Profile: │Bluray-1080p ▼ │ │────────────────────╮│ + ││ Seasons │ History│ ╰─────────────────────────────────────────────────╯ │ ││ + ││──────────────────│ ╭─────────────────────────────────────────────────╮ │────────────────────││ + ││ Monitored Seaso│ Language Profile: │English ▼ │ │ ││ + ││=> 🏷 Seaso│ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ ╭─────────────────────────────────────────────────╮ │ ││ + ││ │ Series Type: │Standard ▼ │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ ╭─────────────────────────────────────────────────╮ │ ││ + ││ │ Path: │/nfs/tv │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ ╭─────────────────────────────────────────────────╮ │ ││ + ││ │ Tags: │alex │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ ││ + ││ ││ Save ││ Cancel ││ ││ + ││ │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesPrompt.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesPrompt.snap new file mode 100644 index 0000000..fd06895 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + + + + ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Season Folder: │ ✔ │ │ + │ ╰───╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Quality Profile: │Bluray-1080p ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Language Profile: │English ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Series Type: │Standard ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Path: │/nfs/tv │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesPrompt_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesPrompt_SeriesDetails.snap new file mode 100644 index 0000000..be8a8fe --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesPrompt_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ │ + │Status: Continuing │ Blah blah blah │ │ + │Genres: cool, famil│ │ │ + │Rating: 84% │ │ │ + │Year: 2022 │ │ │ + │Runtime: 63 minutes│ │ │ + │Path: /nfs/tv/Test │ │ │ + │Quality Profile: Bl│ ╭───╮ │ │ + │Language Profile: E│ Monitored: │ ✔ │ │ │ + │Monitored: Yes │ ╰───╯ │ │ + │Size on Disk: 59.51│ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │╭ Series Details │ Quality Profile: │Bluray-1080p ▼ │ │────────────────────╮│ + ││ Seasons │ History│ ╰─────────────────────────────────────────────────╯ │ ││ + ││──────────────────│ ╭─────────────────────────────────────────────────╮ │────────────────────││ + ││ Monitored Seaso│ Language Profile: │English ▼ │ │ ││ + ││=> 🏷 Seaso│ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ ╭─────────────────────────────────────────────────╮ │ ││ + ││ │ Series Type: │Standard ▼ │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ ╭─────────────────────────────────────────────────╮ │ ││ + ││ │ Path: │/nfs/tv │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ ╭─────────────────────────────────────────────────╮ │ ││ + ││ │ Tags: │alex │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ ││ + ││ ││ Save ││ Cancel ││ ││ + ││ │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectLanguageProfile.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectLanguageProfile.snap new file mode 100644 index 0000000..9990fb3 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectLanguageProfile.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + + + + ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Season Folder: │ ✔ │ │ + │ ╭───────────────────────────────╮ │ + │ │English │──────────────────────────────╮ │ + │ Qual│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Langu│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ ╰───────────────────────────────╯ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectLanguageProfile_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectLanguageProfile_SeriesDetails.snap new file mode 100644 index 0000000..f882c48 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectLanguageProfile_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ │ + │Status: Continuing │ Blah blah blah │ │ + │Genres: cool, famil│ │ │ + │Rating: 84% │ │ │ + │Year: 2022 │ │ │ + │Runtime: 63 minutes│ │ │ + │Path: /nfs/tv/Test │ │ │ + │Quality Profile: Bl│ ╭───╮ │ │ + │Language Profile: E│ Monitored: │ ✔ │ │ │ + │Monitored: Yes │ ╰───╯ │ │ + │Size on Disk: 59.51│ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╭───────────────────────────────╮ │ │ + │ │ │English │──────────────────────────────╮ │ │ + │╭ Series Details │ Qual│ │ ▼ │ │────────────────────╮│ + ││ Seasons │ History│ │ │──────────────────────────────╯ │ ││ + ││──────────────────│ │ │──────────────────────────────╮ │────────────────────││ + ││ Monitored Seaso│ Langu│ │ ▼ │ │ ││ + ││=> 🏷 Seaso│ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ │ │ ▼ │ │ ││ + ││ │ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ │ │ │ │ ││ + ││ │ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ ╰───────────────────────────────╯ │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ ││ + ││ ││ Save ││ Cancel ││ ││ + ││ │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectQualityProfile.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectQualityProfile.snap new file mode 100644 index 0000000..3cc0c3e --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectQualityProfile.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + + + + ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Season Folder: │ ✔ │ │ + │ ╭───────────────────────────────╮ │ + │ │Bluray-1080p │──────────────────────────────╮ │ + │ Qual│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Langu│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ ╰───────────────────────────────╯ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectQualityProfile_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectQualityProfile_SeriesDetails.snap new file mode 100644 index 0000000..7f9f544 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectQualityProfile_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ │ + │Status: Continuing │ Blah blah blah │ │ + │Genres: cool, famil│ │ │ + │Rating: 84% │ │ │ + │Year: 2022 │ │ │ + │Runtime: 63 minutes│ │ │ + │Path: /nfs/tv/Test │ │ │ + │Quality Profile: Bl│ ╭───╮ │ │ + │Language Profile: E│ Monitored: │ ✔ │ │ │ + │Monitored: Yes │ ╰───╯ │ │ + │Size on Disk: 59.51│ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╭───────────────────────────────╮ │ │ + │ │ │Bluray-1080p │──────────────────────────────╮ │ │ + │╭ Series Details │ Qual│ │ ▼ │ │────────────────────╮│ + ││ Seasons │ History│ │ │──────────────────────────────╯ │ ││ + ││──────────────────│ │ │──────────────────────────────╮ │────────────────────││ + ││ Monitored Seaso│ Langu│ │ ▼ │ │ ││ + ││=> 🏷 Seaso│ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ │ │ ▼ │ │ ││ + ││ │ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ │ │ │ │ ││ + ││ │ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ ╰───────────────────────────────╯ │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ ││ + ││ ││ Save ││ Cancel ││ ││ + ││ │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectSeriesType.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectSeriesType.snap new file mode 100644 index 0000000..cd0e5be --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectSeriesType.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + + + + ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Season Folder: │ ✔ │ │ + │ ╭───────────────────────────────╮ │ + │ │Standard │──────────────────────────────╮ │ + │ Qual│Daily │ ▼ │ │ + │ │Anime │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ Langu│ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ ▼ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ │ │ │ │ + │ │ │──────────────────────────────╯ │ + │ │ │──────────────────────────────╮ │ + │ ╰───────────────────────────────╯ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectSeriesType_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectSeriesType_SeriesDetails.snap new file mode 100644 index 0000000..8d22ec9 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__edit_series_ui__edit_series_ui_tests__tests__snapshot_tests__edit_series_EditSeriesSelectSeriesType_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/edit_series_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ │ + │Status: Continuing │ Blah blah blah │ │ + │Genres: cool, famil│ │ │ + │Rating: 84% │ │ │ + │Year: 2022 │ │ │ + │Runtime: 63 minutes│ │ │ + │Path: /nfs/tv/Test │ │ │ + │Quality Profile: Bl│ ╭───╮ │ │ + │Language Profile: E│ Monitored: │ ✔ │ │ │ + │Monitored: Yes │ ╰───╯ │ │ + │Size on Disk: 59.51│ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╭───────────────────────────────╮ │ │ + │ │ │Standard │──────────────────────────────╮ │ │ + │╭ Series Details │ Qual│Daily │ ▼ │ │────────────────────╮│ + ││ Seasons │ History│ │Anime │──────────────────────────────╯ │ ││ + ││──────────────────│ │ │──────────────────────────────╮ │────────────────────││ + ││ Monitored Seaso│ Langu│ │ ▼ │ │ ││ + ││=> 🏷 Seaso│ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ │ │ ▼ │ │ ││ + ││ │ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ │ │ │ │ ││ + ││ │ │ │──────────────────────────────╯ │ ││ + ││ │ │ │──────────────────────────────╮ │ ││ + ││ │ ╰───────────────────────────────╯ │ │ ││ + ││ │ ╰─────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ ││ + ││ ││ Save ││ Cancel ││ ││ + ││ │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeDetails_0.snap new file mode 100644 index 0000000..3175a60 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeDetails_0.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeFile_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeFile_2.snap new file mode 100644 index 0000000..3175a60 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeFile_2.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeHistoryDetails_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeHistoryDetails_1.snap new file mode 100644 index 0000000..e8150f4 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeHistoryDetails_1.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────── Details ─────────────────────────╮ │ + │ │Source Title: │ │ + │ │ │ │ + │ │No additional data available │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeHistory_1.snap new file mode 100644 index 0000000..3175a60 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_EpisodeHistory_1.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_ManualEpisodeSearch_3.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_ManualEpisodeSearch_3.snap new file mode 100644 index 0000000..a1074e1 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__empty_episode_details_ManualEpisodeSearch_3.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_0.snap new file mode 100644 index 0000000..bf73223 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_0.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Some episode details: │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Automatic Episode Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the episode: Something cool │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_1.snap new file mode 100644 index 0000000..4cf2444 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_1.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Automatic Episode Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the episode: Something cool │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_2.snap new file mode 100644 index 0000000..43a03f9 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_2.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │File Details │ + │Some file details │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Audio Details │ + │Some audio details ╭─────────────── Automatic Episode Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the episode: Something cool │ │ + │ │ │ │ + │ │ │ │ + │──────────────────────────────│ │───────────────────────────────│ + │Video Details │ │ │ + │Some video details │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_3.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_3.snap new file mode 100644 index 0000000..19969df --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_AutomaticallySearchEpisodePrompt_3.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p│ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p│ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────── Automatic Episode Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for the episode: Something cool │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeDetails_0.snap new file mode 100644 index 0000000..b579484 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeDetails_0.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Some episode details: │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeFile_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeFile_2.snap new file mode 100644 index 0000000..5dc8e69 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeFile_2.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │File Details │ + │Some file details │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Audio Details │ + │Some audio details │ + │ │ + │ │ + │ │ + │ │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │Video Details │ + │Some video details │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeHistoryDetails_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeHistoryDetails_1.snap new file mode 100644 index 0000000..0ae4533 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeHistoryDetails_1.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────── Details ─────────────────────────╮ │ + │ │Source Title: Test source │ │ + │ │Indexer: │ │ + │ │Release Group: │ │ + │ │Series Match Type: │ │ + │ │NZB Info URL: │ │ + │ │Download Client Name: │ │ + │ ╰────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeHistory_1.snap new file mode 100644 index 0000000..5dca4e2 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_EpisodeHistory_1.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearchConfirmPrompt_3.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearchConfirmPrompt_3.snap new file mode 100644 index 0000000..5822cba --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearchConfirmPrompt_3.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p│ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p│ + │ │ + │ │ + │ │ + │ ╭───────────────── Download Rejected Release ──────────────────╮ │ + │ │ Do you really want to download the rejected release: Test │ │ + │ │ Release? │ │ + │ │ │ │ + │ │ │ │ + │ │Rejection reasons: │ │ + │ │• Unknown quality profile │ │ + │ │• Release is already mapped │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭──────────────────────────────╮╭──────────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰──────────────────────────────╯╰──────────────────────────────╯│ │ + │ ╰────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearchSortPrompt_3.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearchSortPrompt_3.snap new file mode 100644 index 0000000..2c17647 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearchSortPrompt_3.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p│ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────╮ │ + │ │Something │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰──────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearch_3.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearch_3.snap new file mode 100644 index 0000000..cb7aac1 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__episode_details_ManualEpisodeSearch_3.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p│ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeDetails_0.snap new file mode 100644 index 0000000..a1074e1 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeDetails_0.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeFile_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeFile_2.snap new file mode 100644 index 0000000..a1074e1 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeFile_2.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeHistory_1.snap new file mode 100644 index 0000000..a1074e1 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_EpisodeHistory_1.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_ManualEpisodeSearch_3.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_ManualEpisodeSearch_3.snap new file mode 100644 index 0000000..a1074e1 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__episode_details_ui__episode_details_ui_tests__tests__snapshot_tests__loading_episode_details_ManualEpisodeSearch_3.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/episode_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Details │ History │ File │ Manual Search │ + │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_add_series_over_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_add_series_over_series.snap new file mode 100644 index 0000000..c5f433a --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_add_series_over_series.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + ╭────────────────────────────────────────── Add Series - Test ──────────────────────────────────────────╮ + ╭──────│ New series blah blah blah │───────╮ + │someth│ │ │ + ╰──────│ │───────╯ + ╭──────│ │───────╮ + │ ✔ │ │ │ + │=> │ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Root Folder: │/nfs ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Monitor: │All Episodes ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Quality Profile: │Bluray-1080p ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Language Profile: │English ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Series Type: │Standard ▼ │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ ╭───╮ │ │ + │ │ Season Folder: │ ✔ │ │ │ + │ │ ╰───╯ │ │ + │ │ ╭─────────────────────────────────────────────────╮ │ │ + │ │ Tags: │alex │ │ │ + │ │ ╰─────────────────────────────────────────────────╯ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ │ + │ ││ Add ││ Cancel ││ │ + ╰──────│╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│───────╯ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_episode_over_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_episode_over_series.snap new file mode 100644 index 0000000..5d15d26 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_delete_episode_over_series.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + + + + ╭───────────────────── Delete Series ─────────────────────╮ + │ Do you really want to delete the series: │ + │ Test? │ + │ │ + │ │ + │ ╭───╮ │ + │ Delete Series File: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Add List Exclusion: │ ✔ │ │ + │ ╰───╯ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_edit_series_over_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_edit_series_over_series.snap new file mode 100644 index 0000000..7fe1a71 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_edit_series_over_series.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + ╭───────────────────────────────────────────── Edit - Test ─────────────────────────────────────────────╮ + │ Blah blah blah │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───╮ │ + │ Monitored: │ ✔ │ │ + │ ╰───╯ │ + │ ╭───╮ │ + │ Season Folder: │ ✔ │ │ + │ ╰───╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Quality Profile: │Bluray-1080p ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Language Profile: │English ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Series Type: │Standard ▼ │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Path: │/nfs/tv │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ ╭─────────────────────────────────────────────────╮ │ + │ Tags: │alex │ │ + │ ╰─────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭───────────────────────────────────────────────────╮╭──────────────────────────────────────────────────╮│ + ││ Save ││ Cancel ││ + │╰───────────────────────────────────────────────────╯╰──────────────────────────────────────────────────╯│ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_empty.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_empty.snap new file mode 100644 index 0000000..ad20c30 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_empty.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_episode_details_over_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_episode_details_over_series.snap new file mode 100644 index 0000000..a2da567 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_episode_details_over_series.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Titl╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ + │Over│ Episodes │ History │ Manual Search │ │ + │Netw│──────╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮─────│ │ + │Stat│ 🏷 │ Details │ History │ File │ Manual Search │file │ │ + │Genr│=> 🏷 │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│p │ │ + │Rati│ │Some episode details: │ │ │ + │Year│ │ │ │ │ + │Runt│ │ │ │ │ + │Path│ │ │ │ │ + │Qual│ │ │ │ │ + │Lang│ │ │ │ │ + │Moni│ │ │ │ │ + │Size│ │ │ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │╭ S│ │ │ │─────╮│ + ││ Se│ │ │ │ ││ + ││───│ │ │ │─────││ + ││ │ │ │ │ ││ + ││=> │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_loading.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_loading.snap new file mode 100644 index 0000000..c229cc2 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_season_details_over_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_season_details_over_series.snap new file mode 100644 index 0000000..2d4535c --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_season_details_over_series.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Titl╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ + │Over│ Episodes │ History │ Manual Search │ │ + │Netw│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ │ + │Stat│ 🏷 # Title Air Date Size on Disk Quality Profile │ │ + │Genr│=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ │ + │Rati│ │ │ + │Year│ │ │ + │Runt│ │ │ + │Path│ │ │ + │Qual│ │ │ + │Lang│ │ │ + │Moni│ │ │ + │Size│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │╭ S│ │─────╮│ + ││ Se│ │ ││ + ││───│ │─────││ + ││ │ │ ││ + ││=> │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_series_details_over_series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_series_details_over_series.snap new file mode 100644 index 0000000..81ab929 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__library_ui_renders_series_details_over_series.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Monitored Season Episode Count Size on Disk ││ + ││=> 🏷 Season title 10/10 34.19 GB ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_FilterSeries.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_FilterSeries.snap new file mode 100644 index 0000000..4b2598c --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_FilterSeries.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + + + + + + + + + ╭───────────────── Filter ──────────────────╮ + │series filter │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_FilterSeriesError.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_FilterSeriesError.snap new file mode 100644 index 0000000..9bef7e7 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_FilterSeriesError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │The given filter produced empty results│ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SearchSeries.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SearchSeries.snap new file mode 100644 index 0000000..7d230a7 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SearchSeries.snap @@ -0,0 +1,28 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + + + + + + + + + ╭───────────────── Search ──────────────────╮ + │series search │ + ╰─────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SearchSeriesError.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SearchSeriesError.snap new file mode 100644 index 0000000..57eaf04 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SearchSeriesError.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + + + + + + + + + + + ╭─────────────── Error ───────────────╮ + │ No items found matching search │ + │ │ + ╰───────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_Series.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_Series.snap new file mode 100644 index 0000000..95e1e51 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_Series.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SeriesSortPrompt.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SeriesSortPrompt.snap new file mode 100644 index 0000000..166527f --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_SeriesSortPrompt.snap @@ -0,0 +1,42 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + ╭───────────────────────────────╮ + │Something │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_UpdateAllSeriesPrompt.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_UpdateAllSeriesPrompt.snap new file mode 100644 index 0000000..b43cea3 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__library_ui_tests__tests__snapshot_tests__sonarr_library_UpdateAllSeriesPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/library/library_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags +=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 + + + + + + + + + + + + + + ╭─────────────────── Update All Series ───────────────────╮ + │ Do you want to update info and scan your disks for all of │ + │ your series? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_ManualSeasonSearch_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_ManualSeasonSearch_2.snap new file mode 100644 index 0000000..2d7f490 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_ManualSeasonSearch_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonDetails_0.snap new file mode 100644 index 0000000..26d5a94 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonDetails_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonHistoryDetails_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonHistoryDetails_1.snap new file mode 100644 index 0000000..b0bd2ac --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonHistoryDetails_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────────── Details ────────────────────────────╮ │ + │ │Source Title: │ │ + │ │ │ │ + │ │No additional data available │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰───────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonHistory_1.snap new file mode 100644 index 0000000..26d5a94 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__empty_season_details_SeasonHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_ManualSeasonSearch_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_ManualSeasonSearch_2.snap new file mode 100644 index 0000000..2d7f490 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_ManualSeasonSearch_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonDetails_0.snap new file mode 100644 index 0000000..2d7f490 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonDetails_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonHistoryDetails_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonHistoryDetails_1.snap new file mode 100644 index 0000000..7c519e8 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonHistoryDetails_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────────── Details ────────────────────────────╮ │ + │ │Source Title: │ │ + │ │ │ │ + │ │No additional data available │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰───────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonHistory_1.snap new file mode 100644 index 0000000..2d7f490 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__loading_season_details_SeasonHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_0.snap new file mode 100644 index 0000000..3ea342c --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ 🏷 # Title Air Date Size on Disk Quality Profile │ + │=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Season Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for season packs for: Season title │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_1.snap new file mode 100644 index 0000000..a976fef --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Season Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for season packs for: Season title │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_2.snap new file mode 100644 index 0000000..4dcfb7e --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_AutomaticallySearchSeasonPrompt_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────── Automatic Season Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for season packs for: Season title │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_DeleteEpisodeFilePrompt_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_DeleteEpisodeFilePrompt_0.snap new file mode 100644 index 0000000..cefc809 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_DeleteEpisodeFilePrompt_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ 🏷 # Title Air Date Size on Disk Quality Profile │ + │=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────── Delete Episode ─────────────────────╮ │ + │ │ Do you really want to delete this episode: │ │ + │ │ Something cool? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_FilterSeasonHistoryError_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_FilterSeasonHistoryError_1.snap new file mode 100644 index 0000000..55e0a12 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_FilterSeasonHistoryError_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────── Error ────────────╮ │ + │ │ The given filter produced empty│ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_FilterSeasonHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_FilterSeasonHistory_1.snap new file mode 100644 index 0000000..25d8c76 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_FilterSeasonHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────── Filter ──────────────╮ │ + │ │season history filter │ │ + │ ╰─────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearchConfirmPrompt_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearchConfirmPrompt_2.snap new file mode 100644 index 0000000..b5d1814 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearchConfirmPrompt_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────────── Download Rejected Release ──────────────────╮ │ + │ │ Do you really want to download the rejected release: Test │ │ + │ │ Release? │ │ + │ │ │ │ + │ │ │ │ + │ │Rejection reasons: │ │ + │ │• Unknown quality profile │ │ + │ │• Release is already mapped │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭──────────────────────────────╮╭──────────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰──────────────────────────────╯╰──────────────────────────────╯│ │ + │ ╰────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearchSortPrompt_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearchSortPrompt_2.snap new file mode 100644 index 0000000..5892849 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearchSortPrompt_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────╮ │ + │ │Something │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearch_2.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearch_2.snap new file mode 100644 index 0000000..8f62f05 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_ManualSeasonSearch_2.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source ▼ Age ⛔ Title Indexer Size Peers Language Quality │ + │=> torrent 1 days ⛔ Test Release kickass torrents 0.0 GB 2 / 1 English Bluray-1080p │ + │ usenet 1 days ⛔ Test Release DrunkenSlug 0.0 GB English Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchEpisodesError_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchEpisodesError_0.snap new file mode 100644 index 0000000..7e035fb --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchEpisodesError_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ 🏷 # Title Air Date Size on Disk Quality Profile │ + │=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────── Error ────────────╮ │ + │ │ No items found matching search │ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchEpisodes_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchEpisodes_0.snap new file mode 100644 index 0000000..6c651db --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchEpisodes_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ 🏷 # Title Air Date Size on Disk Quality Profile │ + │=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────── Search ──────────────╮ │ + │ │episode search │ │ + │ ╰─────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchSeasonHistoryError_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchSeasonHistoryError_1.snap new file mode 100644 index 0000000..029d6b0 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchSeasonHistoryError_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────── Error ────────────╮ │ + │ │ No items found matching search │ │ + │ ╰────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchSeasonHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchSeasonHistory_1.snap new file mode 100644 index 0000000..4f189dd --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SearchSeasonHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭───────────── Search ──────────────╮ │ + │ │season history search │ │ + │ ╰─────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonDetails_0.snap new file mode 100644 index 0000000..65c3117 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonDetails_0.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ 🏷 # Title Air Date Size on Disk Quality Profile │ + │=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistoryDetails_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistoryDetails_1.snap new file mode 100644 index 0000000..6fe8412 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistoryDetails_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭──────────────────────────── Details ────────────────────────────╮ │ + │ │Source Title: Test source │ │ + │ │Indexer: │ │ + │ │Release Group: │ │ + │ │Series Match Type: │ │ + │ │NZB Info URL: │ │ + │ │Download Client Name: │ │ + │ ╰───────────────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistorySortPrompt_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistorySortPrompt_1.snap new file mode 100644 index 0000000..033ca8a --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistorySortPrompt_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭─────────────────────────╮ │ + │ │Something │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰─────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistory_1.snap new file mode 100644 index 0000000..60cb3c2 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_renders_SeasonHistory_1.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ + │ Source Title ▼ Event Type Language Quality Date │ + │=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_ui_renders_episode_details_over_season_details.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_ui_renders_episode_details_over_season_details.snap new file mode 100644 index 0000000..f5f399a --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__season_details_ui__season_details_ui_tests__tests__snapshot_tests__season_details_ui_renders_episode_details_over_season_details.snap @@ -0,0 +1,50 @@ +--- +source: src/ui/sonarr_ui/library/season_details_ui_tests.rs +expression: output +--- + + + + + ╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Episodes │ History │ Manual Search │ + │──────╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮─────│ + │ 🏷 │ Details │ History │ File │ Manual Search │file │ + │=> 🏷 │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│p │ + │ │Some episode details: │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ + │ │ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesDetails.snap new file mode 100644 index 0000000..8d7f917 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesHistory.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesHistory.snap new file mode 100644 index 0000000..8d7f917 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesHistory.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesHistoryDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesHistoryDetails.snap new file mode 100644 index 0000000..f70e2fe --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__empty_series_details_SeriesHistoryDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ╭─────────────────────────────── Details ───────────────────────────────╮ ││ + ││───────────────────────────────────│Source Title: │───────────────────────────────────││ + ││ │ │ ││ + ││ │No additional data available │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__loading_series_details_SeriesDetails.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__loading_series_details_SeriesDetails.snap new file mode 100644 index 0000000..f7e287f --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__loading_series_details_SeriesDetails.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ ││ + ││ ││ + ││ Loading ... ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__loading_series_details_SeriesHistory.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__loading_series_details_SeriesHistory.snap new file mode 100644 index 0000000..f7e287f --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__loading_series_details_SeriesHistory.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ ││ + ││ ││ + ││ Loading ... ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_AutomaticallySearchSeriesPrompt_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_AutomaticallySearchSeriesPrompt_0.snap new file mode 100644 index 0000000..385ee3e --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_AutomaticallySearchSeriesPrompt_0.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB ╭──────────────── Automatic Series Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for all monitored episode(s) for the series: Test │ │ + │ │ │ │ + │╭ Series Details ───────────────────────│ │───────────────────────────────────────────╮│ + ││ Seasons │ History │ │ ││ + ││─────────────────────────────────────────│ │───────────────────────────────────────────││ + ││ Monitored Season │ │Size on Disk ││ + ││=> 🏷 Season title │ │34.19 GB ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭────────────────────────────╮╭───────────────────────────╮│ ││ + ││ ││ Yes ││ No ││ ││ + ││ │╰────────────────────────────╯╰───────────────────────────╯│ ││ + ││ ╰───────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_AutomaticallySearchSeriesPrompt_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_AutomaticallySearchSeriesPrompt_1.snap new file mode 100644 index 0000000..accf608 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_AutomaticallySearchSeriesPrompt_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB ╭──────────────── Automatic Series Search ────────────────╮ │ + │ │Do you want to trigger an automatic search of your indexers│ │ + │ │ for all monitored episode(s) for the series: Test │ │ + │ │ │ │ + │╭ Series Details ───────────────────────│ │───────────────────────────────────────────╮│ + ││ Seasons │ History │ │ ││ + ││─────────────────────────────────────────│ │───────────────────────────────────────────││ + ││ Source Title ▼ │ │ty Date ││ + ││=> Test source │ │y-1080p 2024-02-10 07:28:45 UTC ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭────────────────────────────╮╭───────────────────────────╮│ ││ + ││ ││ Yes ││ No ││ ││ + ││ │╰────────────────────────────╯╰───────────────────────────╯│ ││ + ││ ╰───────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_FilterSeriesHistoryError_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_FilterSeriesHistoryError_1.snap new file mode 100644 index 0000000..7e0ca69 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_FilterSeriesHistoryError_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Source Title ▼ Event Type Language Quality Date ││ + ││=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭──────────── Error ─────────────╮ ││ + ││ │ The given filter produced empty │ ││ + ││ ╰──────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_FilterSeriesHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_FilterSeriesHistory_1.snap new file mode 100644 index 0000000..3e37c14 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_FilterSeriesHistory_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Source Title ▼ Event Type Language Quality Date ││ + ││=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭────────────── Filter ───────────────╮ ││ + ││ │series history filter │ ││ + ││ ╰───────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeasonError_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeasonError_0.snap new file mode 100644 index 0000000..3bd7da7 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeasonError_0.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Monitored Season Episode Count Size on Disk ││ + ││=> 🏷 Season title 10/10 34.19 GB ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭──────────── Error ─────────────╮ ││ + ││ │ No items found matching search │ ││ + ││ ╰──────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeason_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeason_0.snap new file mode 100644 index 0000000..a594073 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeason_0.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Monitored Season Episode Count Size on Disk ││ + ││=> 🏷 Season title 10/10 34.19 GB ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭────────────── Search ───────────────╮ ││ + ││ │season search │ ││ + ││ ╰───────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeriesHistoryError_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeriesHistoryError_1.snap new file mode 100644 index 0000000..c213bf2 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeriesHistoryError_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Source Title ▼ Event Type Language Quality Date ││ + ││=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭──────────── Error ─────────────╮ ││ + ││ │ No items found matching search │ ││ + ││ ╰──────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeriesHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeriesHistory_1.snap new file mode 100644 index 0000000..afd0fa0 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SearchSeriesHistory_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Source Title ▼ Event Type Language Quality Date ││ + ││=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭────────────── Search ───────────────╮ ││ + ││ │series history search │ ││ + ││ ╰───────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesDetails_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesDetails_0.snap new file mode 100644 index 0000000..1f91c3a --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesDetails_0.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Monitored Season Episode Count Size on Disk ││ + ││=> 🏷 Season title 10/10 34.19 GB ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistoryDetails_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistoryDetails_1.snap new file mode 100644 index 0000000..756cf8f --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistoryDetails_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ╭─────────────────────────────── Details ───────────────────────────────╮ ││ + ││───────────────────────────────────│Source Title: Test source │───────────────────────────────────││ + ││ Source Title ▼ │Indexer: │ Date ││ + ││=> Test source │Release Group: │ 2024-02-10 07:28:45 UTC ││ + ││ │Series Match Type: │ ││ + ││ │NZB Info URL: │ ││ + ││ │Download Client Name: │ ││ + ││ │Age: 0 days │ ││ + ││ ╰─────────────────────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistorySortPrompt_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistorySortPrompt_1.snap new file mode 100644 index 0000000..4c982de --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistorySortPrompt_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Source Title Event Type Language Quality Date ││ + ││=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC ││ + ││ ││ + ││ ││ + ││ ││ + ││ ╭───────────────────────────╮ ││ + ││ │Something │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ ╰───────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistory_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistory_1.snap new file mode 100644 index 0000000..7633027 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_SeriesHistory_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB │ + │ │ + │ │ + │ │ + │╭ Series Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ + ││ Seasons │ History ││ + ││─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────││ + ││ Source Title ▼ Event Type Language Quality Date ││ + ││=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_UpdateAndScanSeriesPrompt_0.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_UpdateAndScanSeriesPrompt_0.snap new file mode 100644 index 0000000..0596611 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_UpdateAndScanSeriesPrompt_0.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ series: Test? │ │ + │ │ │ │ + │╭ Series Details ───────────────────────│ │───────────────────────────────────────────╮│ + ││ Seasons │ History │ │ ││ + ││─────────────────────────────────────────│ │───────────────────────────────────────────││ + ││ Monitored Season │ │Size on Disk ││ + ││=> 🏷 Season title │ │34.19 GB ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭────────────────────────────╮╭───────────────────────────╮│ ││ + ││ ││ Yes ││ No ││ ││ + ││ │╰────────────────────────────╯╰───────────────────────────╯│ ││ + ││ ╰───────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_UpdateAndScanSeriesPrompt_1.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_UpdateAndScanSeriesPrompt_1.snap new file mode 100644 index 0000000..2e1e2ee --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_UpdateAndScanSeriesPrompt_1.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Title: Test │ + │Overview: Blah blah blah │ + │Network: HBO │ + │Status: Continuing │ + │Genres: cool, family, fun │ + │Rating: 84% │ + │Year: 2022 │ + │Runtime: 63 minutes │ + │Path: /nfs/tv/Test │ + │Quality Profile: Bluray-1080p │ + │Language Profile: English │ + │Monitored: Yes │ + │Size on Disk: 59.51 GB ╭──────────────────── Update and Scan ────────────────────╮ │ + │ │ Do you want to trigger an update and disk scan for the │ │ + │ │ series: Test? │ │ + │ │ │ │ + │╭ Series Details ───────────────────────│ │───────────────────────────────────────────╮│ + ││ Seasons │ History │ │ ││ + ││─────────────────────────────────────────│ │───────────────────────────────────────────││ + ││ Source Title ▼ │ │ty Date ││ + ││=> Test source │ │y-1080p 2024-02-10 07:28:45 UTC ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │╭────────────────────────────╮╭───────────────────────────╮│ ││ + ││ ││ Yes ││ No ││ ││ + ││ │╰────────────────────────────╯╰───────────────────────────╯│ ││ + ││ ╰───────────────────────────────────────────────────────────╯ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + ││ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_renders_episode_details_over_series_details.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_renders_episode_details_over_series_details.snap new file mode 100644 index 0000000..32906b6 --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_renders_episode_details_over_series_details.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Titl╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ + │Over│ Episodes │ History │ Manual Search │ │ + │Netw│──────╭ Episode Details ───────────────────────────────────────────────────────────────────────────────────────────────────────╮─────│ │ + │Stat│ 🏷 │ Details │ History │ File │ Manual Search │file │ │ + │Genr│=> 🏷 │──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│p │ │ + │Rati│ │Some episode details: │ │ │ + │Year│ │ │ │ │ + │Runt│ │ │ │ │ + │Path│ │ │ │ │ + │Qual│ │ │ │ │ + │Lang│ │ │ │ │ + │Moni│ │ │ │ │ + │Size│ │ │ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ + │╭ S│ │ │ │─────╮│ + ││ Se│ │ │ │ ││ + ││───│ │ │ │─────││ + ││ │ │ │ │ ││ + ││=> │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ │ │ │ ││ + ││ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ ││ + ││ │ │ ││ + ││ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_renders_season_details_over_series_details.snap b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_renders_season_details_over_series_details.snap new file mode 100644 index 0000000..677c48d --- /dev/null +++ b/src/ui/sonarr_ui/library/snapshots/managarr__ui__sonarr_ui__library__series_details_ui__series_details_ui_tests__tests__snapshot_tests__series_details_ui_renders_season_details_over_series_details.snap @@ -0,0 +1,52 @@ +--- +source: src/ui/sonarr_ui/library/series_details_ui_tests.rs +expression: output +--- + + + + ╭ Test ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │Titl╭ Season 1 Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ + │Over│ Episodes │ History │ Manual Search │ │ + │Netw│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ │ + │Stat│ 🏷 # Title Air Date Size on Disk Quality Profile │ │ + │Genr│=> 🏷 1 Something cool 2024-02-10 07:28:45 UTC 3.30 GB Bluray-1080p │ │ + │Rati│ │ │ + │Year│ │ │ + │Runt│ │ │ + │Path│ │ │ + │Qual│ │ │ + │Lang│ │ │ + │Moni│ │ │ + │Size│ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │╭ S│ │─────╮│ + ││ Se│ │ ││ + ││───│ │─────││ + ││ │ │ ││ + ││=> │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ │ │ ││ + ││ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ││ + │╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ + ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/mod.rs b/src/ui/sonarr_ui/mod.rs index 20d9f60..bbe1979 100644 --- a/src/ui/sonarr_ui/mod.rs +++ b/src/ui/sonarr_ui/mod.rs @@ -1,17 +1,21 @@ use std::{cmp, iter}; +#[cfg(test)] +use crate::ui::ui_test_utils::test_utils::Utc; use blocklist::BlocklistUi; -use chrono::{Duration, Utc}; +use chrono::Duration; +#[cfg(not(test))] +use chrono::Utc; use downloads::DownloadsUi; use history::HistoryUi; use indexers::IndexersUi; use library::LibraryUi; use ratatui::{ + Frame, layout::{Constraint, Layout, Rect}, style::Stylize, text::Text, widgets::Paragraph, - Frame, }; use root_folders::RootFoldersUi; use system::SystemUi; @@ -20,22 +24,21 @@ use crate::{ app::App, logos::SONARR_LOGO, models::{ + Route, servarr_data::sonarr::sonarr_data::SonarrData, servarr_models::{DiskSpace, RootFolder}, sonarr_models::DownloadRecord, - Route, }, utils::convert_to_gb, }; use super::{ - draw_tabs, + DrawUi, draw_tabs, styles::ManagarrStyle, utils::{ borderless_block, layout_block, line_gauge_with_label, line_gauge_with_title, title_block, }, widgets::loading_block::LoadingBlock, - DrawUi, }; mod blocklist; diff --git a/src/ui/sonarr_ui/root_folders/mod.rs b/src/ui/sonarr_ui/root_folders/mod.rs index 1d2728e..db98c24 100644 --- a/src/ui/sonarr_ui/root_folders/mod.rs +++ b/src/ui/sonarr_ui/root_folders/mod.rs @@ -1,17 +1,17 @@ +use ratatui::Frame; use ratatui::layout::{Constraint, Rect}; use ratatui::widgets::{Cell, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS}; use crate::models::servarr_models::RootFolder; -use crate::models::Route; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::layout_block_top_border; use crate::ui::widgets::confirmation_prompt::ConfirmationPrompt; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; -use crate::ui::{draw_input_box_popup, draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_input_box_popup, draw_popup}; use crate::utils::convert_to_gb; #[cfg(test)] diff --git a/src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs b/src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs index 1e9e6c0..e2a113d 100644 --- a/src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs +++ b/src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs @@ -2,9 +2,11 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_FOLDERS_BLOCKS}; - use crate::ui::sonarr_ui::root_folders::RootFoldersUi; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::root_folders::RootFoldersUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_root_folders_ui_accepts() { @@ -16,4 +18,55 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_root_folders_ui_renders_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RootFoldersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_root_folders_ui_renders_empty_root_folders() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RootFoldersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_root_folders_ui_renders_root_folders_tab( + #[values( + ActiveSonarrBlock::RootFolders, + ActiveSonarrBlock::AddRootFolderPrompt, + ActiveSonarrBlock::DeleteRootFolderPrompt + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + RootFoldersUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(active_sonarr_block.to_string(), output); + } + } } diff --git a/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__AddRootFolderPrompt.snap b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__AddRootFolderPrompt.snap new file mode 100644 index 0000000..89588c8 --- /dev/null +++ b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__AddRootFolderPrompt.snap @@ -0,0 +1,31 @@ +--- +source: src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Path Free Space Unmapped Folders +=> /nfs 204800.00 GB 0 + + + + + + + + + + + + + + + + + + + + + ╭───────────── Add Root Folder ─────────────╮ + │/nfs/tv │ + ╰─────────────────────────────────────────────╯ + cancel diff --git a/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__DeleteRootFolderPrompt.snap b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__DeleteRootFolderPrompt.snap new file mode 100644 index 0000000..e3e2165 --- /dev/null +++ b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__DeleteRootFolderPrompt.snap @@ -0,0 +1,38 @@ +--- +source: src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Path Free Space Unmapped Folders +=> /nfs 204800.00 GB 0 + + + + + + + + + + + + + + ╭────────────────── Delete Root Folder ───────────────────╮ + │ Do you really want to delete this root folder: │ + │ /nfs? │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │╭────────────────────────────╮╭───────────────────────────╮│ + ││ Yes ││ No ││ + │╰────────────────────────────╯╰───────────────────────────╯│ + ╰───────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__RootFolders.snap b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__RootFolders.snap new file mode 100644 index 0000000..2700bd5 --- /dev/null +++ b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__RootFolders.snap @@ -0,0 +1,7 @@ +--- +source: src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Path Free Space Unmapped Folders +=> /nfs 204800.00 GB 0 diff --git a/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_empty_root_folders.snap b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_empty_root_folders.snap new file mode 100644 index 0000000..a0ffd33 --- /dev/null +++ b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_empty_root_folders.snap @@ -0,0 +1,5 @@ +--- +source: src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_loading.snap b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_loading.snap new file mode 100644 index 0000000..c3709be --- /dev/null +++ b/src/ui/sonarr_ui/root_folders/snapshots/managarr__ui__sonarr_ui__root_folders__root_folders_ui_tests__tests__snapshot_tests__root_folders_ui_renders_loading.snap @@ -0,0 +1,8 @@ +--- +source: src/ui/sonarr_ui/root_folders/root_folders_ui_tests.rs +expression: output +--- +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + Loading ... diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Blocklist.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Blocklist.snap new file mode 100644 index 0000000..8954c9e --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Blocklist.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Series Title ▼ Source Title Language Quality Date │ +│=> Test Series Test Source Title English Bluray-1080p 2024-02-10 07:28:45 UTC │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Downloads.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Downloads.snap new file mode 100644 index 0000000..06ca6ee --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Downloads.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Title Percent Complete Size Output Path Indexer Download Client │ +│=> Test Download Title 50% 3.30 GB /nfs/tv/Test show/season 1/ kickass torrents transmission │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_History.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_History.snap new file mode 100644 index 0000000..537275c --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_History.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Source Title ▼ Event Type Language Quality Date │ +│=> Test source grabbed English Bluray-1080p 2024-02-10 07:28:45 UTC │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Indexers.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Indexers.snap new file mode 100644 index 0000000..6e26942 --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Indexers.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Indexer RSS Automatic Search Interactive Search Priority Tags │ +│=> Test Indexer Enabled Enabled Enabled 25 alex │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_RootFolders.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_RootFolders.snap new file mode 100644 index 0000000..767cad4 --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_RootFolders.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Path Free Space Unmapped Folders │ +│=> /nfs 204800.00 GB 0 │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Series.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Series.snap new file mode 100644 index 0000000..b364ada --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_Series.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────│ +│ Title ▼ Year Network Status Rating Type Quality Profile Language Size Monitored Tags │ +│=> Test 2022 HBO Continuin TV-MA Standard Bluray-1080p English 59.51 GB 🏷 │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_System.snap b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_System.snap new file mode 100644 index 0000000..c163cd3 --- /dev/null +++ b/src/ui/sonarr_ui/snapshots/managarr__ui__sonarr_ui__sonarr_ui_tests__tests__snapshot_tests__sonarr_tabs_System.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/sonarr_ui_tests.rs +expression: output +--- +╭ Series ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ Library │ Downloads │ Blocklist │ History │ Root Folders │ Indexers │ System │ +│╭ Tasks ───────────────────────────────────────────────────────────────────────╮╭ Queued Events ──────────────────────────────────────────────────────────────╮│ +││Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration ││ +││Backup 1 hour now 59 minutes ││manual completed Refresh Monitored 4 minutes ago 4 minutes a 00:03:03 ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +││ ││ ││ +│╰────────────────────────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────────────────────╯│ +│╭ Logs ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮│ +││2025-12-16 16:40:59 UTC|INFO|ImportListSyncService|No list items to process ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +││ ││ +│╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯│ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/sonarr_ui_tests.rs b/src/ui/sonarr_ui/sonarr_ui_tests.rs index 6a1630e..d52b62a 100644 --- a/src/ui/sonarr_ui/sonarr_ui_tests.rs +++ b/src/ui/sonarr_ui/sonarr_ui_tests.rs @@ -3,8 +3,9 @@ mod tests { use strum::IntoEnumIterator; use crate::{ + app::App, models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock, - ui::{sonarr_ui::SonarrUi, DrawUi}, + ui::{DrawUi, sonarr_ui::SonarrUi, ui_test_utils::test_utils::render_to_string_with_app}, }; #[test] @@ -13,4 +14,34 @@ mod tests { assert!(SonarrUi::accepts(active_sonarr_block.into())); }); } + + mod snapshot_tests { + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[rstest] + #[case(ActiveSonarrBlock::Series, 0)] + #[case(ActiveSonarrBlock::Downloads, 1)] + #[case(ActiveSonarrBlock::Blocklist, 2)] + #[case(ActiveSonarrBlock::History, 3)] + #[case(ActiveSonarrBlock::RootFolders, 4)] + #[case(ActiveSonarrBlock::Indexers, 5)] + #[case(ActiveSonarrBlock::System, 6)] + fn test_sonarr_ui_renders_sonarr_tabs( + #[case] active_sonarr_block: ActiveSonarrBlock, + #[case] index: usize, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + app.data.sonarr_data.main_tabs.set_index(index); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SonarrUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("sonarr_tabs_{active_sonarr_block}"), output); + } + } } diff --git a/src/ui/sonarr_ui/system/mod.rs b/src/ui/sonarr_ui/system/mod.rs index d4fd709..96d06ee 100644 --- a/src/ui/sonarr_ui/system/mod.rs +++ b/src/ui/sonarr_ui/system/mod.rs @@ -1,14 +1,17 @@ use std::ops::Sub; +#[cfg(test)] +use crate::ui::ui_test_utils::test_utils::Utc; +#[cfg(not(test))] use chrono::Utc; use ratatui::layout::Layout; use ratatui::style::Style; use ratatui::text::{Span, Text}; use ratatui::widgets::{Cell, Row}; use ratatui::{ + Frame, layout::{Constraint, Rect}, widgets::ListItem, - Frame, }; use crate::app::App; @@ -23,7 +26,7 @@ use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::selectable_list::SelectableList; use crate::{ models::Route, - ui::{utils::title_block, DrawUi}, + ui::{DrawUi, utils::title_block}, }; mod system_details_ui; @@ -46,11 +49,10 @@ pub(super) struct SystemUi; impl DrawUi for SystemUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return SystemDetailsUi::accepts(route) || active_sonarr_block == ActiveSonarrBlock::System; - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + SystemDetailsUi::accepts(route) || active_sonarr_block == ActiveSonarrBlock::System } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemLogs.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemLogs.snap new file mode 100644 index 0000000..679fc1d --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemLogs.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemQueuedEvents.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemQueuedEvents.snap new file mode 100644 index 0000000..1f76436 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemQueuedEvents.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemTasks.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemTasks.snap new file mode 100644 index 0000000..8850c6d --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__empty_SystemTasks.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemLogs.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemLogs.snap new file mode 100644 index 0000000..2a54bbb --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemLogs.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemQueuedEvents.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemQueuedEvents.snap new file mode 100644 index 0000000..778cfdc --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemQueuedEvents.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemTasks.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemTasks.snap new file mode 100644 index 0000000..f6364ff --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemTasks.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemUpdates.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemUpdates.snap new file mode 100644 index 0000000..ed21afc --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__loading_SystemUpdates.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Updates ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemLogs.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemLogs.snap new file mode 100644 index 0000000..37b4d25 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemLogs.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │2025-12-16 16:40:59 UTC|INFO|ImportListSyncService|No list items to process │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemQueuedEvents.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemQueuedEvents.snap new file mode 100644 index 0000000..8f4fb2a --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemQueuedEvents.snap @@ -0,0 +1,44 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + + + + + ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ + │Trigger Status Name Queued Started Duration │ + │manual completed Refresh Monitored Downlo 4 minutes ago 4 minutes ago 00:03:03 │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemTaskStartConfirmPrompt.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemTaskStartConfirmPrompt.snap new file mode 100644 index 0000000..adc698a --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemTaskStartConfirmPrompt.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Name Interval Last Execution Next Execution │ + │=> Backup 1 hour now 59 minutes │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ ╭────────────────────── Start Task ───────────────────────╮ │ + │ │ Do you want to manually start this task: Backup? │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │ │ │ + │ │╭────────────────────────────╮╭───────────────────────────╮│ │ + │ ││ Yes ││ No ││ │ + │ │╰────────────────────────────╯╰───────────────────────────╯│ │ + │ ╰───────────────────────────────────────────────────────────╯ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemTasks.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemTasks.snap new file mode 100644 index 0000000..dfc226c --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemTasks.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ Name Interval Last Execution Next Execution │ + │=> Backup 1 hour now 59 minutes │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemUpdates.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemUpdates.snap new file mode 100644 index 0000000..e893c41 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__popup_SystemUpdates.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Updates ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │The latest version of Sonarr is already installed │ + │ │ + │4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) │ + │--------------------------------------------------------------------------------------------------------------------------│ + │New: │ + │ * Cool new thing │ + │Fixed: │ + │ * Some bugs killed │ + │ │ + │ │ + │3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) │ + │--------------------------------------------------------------------------------------------------------------------------│ + │New: │ + │ * Cool new thing (old) │ + │ * Other cool new thing (old) │ + │ │ + │ │ + │2.1.0 - 2023-04-15 02:02:53 UTC │ + │--------------------------------------------------------------------------------------------------------------------------│ + │Fixed: │ + │ * Killed bug 1 │ + │ * Fixed bug 2 │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_updates_popup_loading_when_empty.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_updates_popup_loading_when_empty.snap new file mode 100644 index 0000000..ed21afc --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_details_ui__system_details_ui_tests__tests__snapshot_tests__system_details_ui_updates_popup_loading_when_empty.snap @@ -0,0 +1,48 @@ +--- +source: src/ui/sonarr_ui/system/system_details_ui_tests.rs +expression: output +--- + + + + + + + ╭ Updates ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ │ + │ │ + │ Loading ... │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemLogs.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemLogs.snap new file mode 100644 index 0000000..fc263ca --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemLogs.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Log Details ───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │2025-12-16 16:40:59 UTC|INFO|ImportListSyncService|No list items to process │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +╰───────────────────│ │────────────────────╯ +╭ Logs ───────────│ │────────────────────╮ +│2025-12-16 16:40:59│ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemQueuedEvents.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemQueuedEvents.snap new file mode 100644 index 0000000..056e356 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemQueuedEvents.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Queued Events ────────────────────────────────────────────────────────────────────────────────╮ │ +│ │Trigger Status Name Queued Started Duration │ │ +│ │manual completed Refresh Monitored Downlo 4 minutes ago 4 minutes ago 00:03:03 │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +╰────────────────────────────────│ │────────────────────────────────╯ +╭ Logs ────────────────────────│ │────────────────────────────────╮ +│2025-12-16 16:40:59 UTC|INFO|Imp│ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemTaskStartConfirmPrompt.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemTaskStartConfirmPrompt.snap new file mode 100644 index 0000000..2ef27cf --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemTaskStartConfirmPrompt.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │ Name Interval Last Execution Next Execution │ │ +│ │=> Backup 1 hour now 59 minutes │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ ╭────────────────────── Start Task ───────────────────────╮ │ │ +│ │ │ Do you want to manually start this task: Backup? │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +╰───────────────────│ │ │ │────────────────────╯ +╭ Logs ───────────│ │ │ │────────────────────╮ +│2025-12-16 16:40:59│ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ │ │╭────────────────────────────╮╭───────────────────────────╮│ │ │ +│ │ ││ Yes ││ No ││ │ │ +│ │ │╰────────────────────────────╯╰───────────────────────────╯│ │ │ +│ │ ╰───────────────────────────────────────────────────────────╯ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemTasks.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemTasks.snap new file mode 100644 index 0000000..443f812 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemTasks.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Tasks ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │ Name Interval Last Execution Next Execution │ │ +│ │=> Backup 1 hour now 59 minutes │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +╰───────────────────│ │────────────────────╯ +╭ Logs ───────────│ │────────────────────╮ +│2025-12-16 16:40:59│ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemUpdates.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemUpdates.snap new file mode 100644 index 0000000..3e3fe6d --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__popups_over_system_ui_SystemUpdates.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ╭ Updates ───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ │The latest version of Sonarr is already installed │ │ +│ │ │ │ +│ │4.3.2.1 - 2023-04-15 02:02:53 UTC (Currently Installed) │ │ +│ │--------------------------------------------------------------------------------------------------------------------------│ │ +│ │New: │ │ +│ │ * Cool new thing │ │ +│ │Fixed: │ │ +│ │ * Some bugs killed │ │ +│ │ │ │ +│ │ │ │ +│ │3.2.1.0 - 2023-04-15 02:02:53 UTC (Previously Installed) │ │ +│ │--------------------------------------------------------------------------------------------------------------------------│ │ +│ │New: │ │ +│ │ * Cool new thing (old) │ │ +│ │ * Other cool new thing (old) │ │ +│ │ │ │ +│ │ │ │ +╰───────────────────│2.1.0 - 2023-04-15 02:02:53 UTC │────────────────────╯ +╭ Logs ───────────│--------------------------------------------------------------------------------------------------------------------------│────────────────────╮ +│2025-12-16 16:40:59│Fixed: │ │ +│ │ * Killed bug 1 │ │ +│ │ * Fixed bug 2 │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_logs_loading.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_logs_loading.snap new file mode 100644 index 0000000..c7ce3d6 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_logs_loading.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ Loading ... ││ Loading ... │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ │ +│ Loading ... │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab.snap new file mode 100644 index 0000000..5d8e5c1 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│Name Interval Last Execution Next Execution ││Trigger Status Name Queued Started Duration │ +│Backup 1 hour now 59 minutes ││manual completed Refresh Monitored D 4 minutes ago 4 minutes a 00:03:03 │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│2025-12-16 16:40:59 UTC|INFO|ImportListSyncService|No list items to process │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_empty.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_empty.snap new file mode 100644 index 0000000..feabe8e --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_empty.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_loading.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_loading.snap new file mode 100644 index 0000000..c7ce3d6 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_loading.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ Loading ... ││ Loading ... │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ │ +│ Loading ... │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_task_and_events_loading.snap b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_task_and_events_loading.snap new file mode 100644 index 0000000..cbfcdc4 --- /dev/null +++ b/src/ui/sonarr_ui/system/snapshots/managarr__ui__sonarr_ui__system__system_ui_tests__tests__snapshot_tests__system_ui_renders_system_tab_task_and_events_loading.snap @@ -0,0 +1,54 @@ +--- +source: src/ui/sonarr_ui/system/system_ui_tests.rs +expression: output +--- +╭ Tasks ────────────────────────────────────────────────────────────────────────╮╭ Queued Events ───────────────────────────────────────────────────────────────╮ +│ ││ │ +│ ││ │ +│ Loading ... ││ Loading ... │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +╰─────────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────────────────────────────────────────────────────────╯ +╭ Logs ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +│2025-12-16 16:40:59 UTC|INFO|ImportListSyncService|No list items to process │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/src/ui/sonarr_ui/system/system_details_ui.rs b/src/ui/sonarr_ui/system/system_details_ui.rs index ffdfd47..f25c5e9 100644 --- a/src/ui/sonarr_ui/system/system_details_ui.rs +++ b/src/ui/sonarr_ui/system/system_details_ui.rs @@ -1,14 +1,14 @@ +use ratatui::Frame; use ratatui::layout::Rect; use ratatui::text::{Span, Text}; use ratatui::widgets::{Cell, ListItem, Paragraph, Row}; -use ratatui::Frame; use crate::app::App; +use crate::models::Route; use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS}; use crate::models::sonarr_models::SonarrTask; -use crate::models::Route; use crate::ui::sonarr_ui::system::{ - draw_queued_events, extract_task_props, TASK_TABLE_CONSTRAINTS, TASK_TABLE_HEADERS, + TASK_TABLE_CONSTRAINTS, TASK_TABLE_HEADERS, draw_queued_events, extract_task_props, }; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{borderless_block, style_log_list_item, title_block}; @@ -17,7 +17,7 @@ use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::managarr_table::ManagarrTable; use crate::ui::widgets::popup::{Popup, Size}; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::{draw_popup, DrawUi}; +use crate::ui::{DrawUi, draw_popup}; #[cfg(test)] #[path = "system_details_ui_tests.rs"] @@ -27,11 +27,10 @@ pub(super) struct SystemDetailsUi; impl DrawUi for SystemDetailsUi { fn accepts(route: Route) -> bool { - if let Route::Sonarr(active_sonarr_block, _) = route { - return SYSTEM_DETAILS_BLOCKS.contains(&active_sonarr_block); - } - - false + let Route::Sonarr(active_sonarr_block, _) = route else { + return false; + }; + SYSTEM_DETAILS_BLOCKS.contains(&active_sonarr_block) } fn draw(f: &mut Frame<'_>, app: &mut App<'_>, _area: Rect) { diff --git a/src/ui/sonarr_ui/system/system_details_ui_tests.rs b/src/ui/sonarr_ui/system/system_details_ui_tests.rs index 80dc239..ec42b04 100644 --- a/src/ui/sonarr_ui/system/system_details_ui_tests.rs +++ b/src/ui/sonarr_ui/system/system_details_ui_tests.rs @@ -2,11 +2,14 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS, }; - use crate::ui::sonarr_ui::system::system_details_ui::SystemDetailsUi; + use crate::ui::DrawUi; + use crate::ui::sonarr_ui::system::system_details_ui::SystemDetailsUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_system_details_ui_accepts() { @@ -18,4 +21,86 @@ mod tests { } }); } + + mod snapshot_tests { + use super::*; + use crate::models::ScrollableText; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + #[rstest] + fn test_system_details_ui_popups( + #[values( + ActiveSonarrBlock::SystemLogs, + ActiveSonarrBlock::SystemQueuedEvents, + ActiveSonarrBlock::SystemTasks, + ActiveSonarrBlock::SystemTaskStartConfirmPrompt, + ActiveSonarrBlock::SystemUpdates + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("popup_{active_sonarr_block}"), output); + } + + #[rstest] + fn test_system_details_ui_loading( + #[values( + ActiveSonarrBlock::SystemLogs, + ActiveSonarrBlock::SystemQueuedEvents, + ActiveSonarrBlock::SystemTasks, + ActiveSonarrBlock::SystemUpdates + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("loading_{active_sonarr_block}"), output); + } + + #[test] + fn test_system_details_ui_updates_popup_loading_when_empty() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::SystemUpdates.into()); + app.data.sonarr_data.updates = ScrollableText::with_string("".to_string()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_system_details_ui_popups_empty( + #[values( + ActiveSonarrBlock::SystemLogs, + ActiveSonarrBlock::SystemQueuedEvents, + ActiveSonarrBlock::SystemTasks + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemDetailsUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(format!("empty_{active_sonarr_block}"), output); + } + } } diff --git a/src/ui/sonarr_ui/system/system_ui_tests.rs b/src/ui/sonarr_ui/system/system_ui_tests.rs index dc43bdc..39b258c 100644 --- a/src/ui/sonarr_ui/system/system_ui_tests.rs +++ b/src/ui/sonarr_ui/system/system_ui_tests.rs @@ -2,11 +2,13 @@ mod tests { use strum::IntoEnumIterator; + use crate::app::App; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS, }; - use crate::ui::sonarr_ui::system::SystemUi; use crate::ui::DrawUi; + use crate::ui::sonarr_ui::system::SystemUi; + use crate::ui::ui_test_utils::test_utils::render_to_string_with_app; #[test] fn test_system_ui_accepts() { @@ -22,4 +24,100 @@ mod tests { } }); } + + mod snapshot_tests { + use crate::models::stateful_list::StatefulList; + use crate::ui::ui_test_utils::test_utils::TerminalSize; + use rstest::rstest; + + use super::*; + + #[test] + fn test_system_ui_renders_system_tab_loading() { + let mut app = App::test_default(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::System.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_system_ui_renders_logs_loading() { + let mut app = App::test_default_fully_populated(); + app.is_loading = true; + app.push_navigation_stack(ActiveSonarrBlock::System.into()); + app.data.sonarr_data.logs = StatefulList::default(); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_system_ui_renders_system_tab_task_and_events_loading() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::System.into()); + app.is_loading = true; + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_system_ui_renders_system_tab() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveSonarrBlock::System.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_system_ui_renders_system_tab_empty() { + let mut app = App::test_default(); + app.push_navigation_stack(ActiveSonarrBlock::System.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!(output); + } + + #[rstest] + fn test_system_details_ui_renders_popups_over_system_ui( + #[values( + ActiveSonarrBlock::SystemLogs, + ActiveSonarrBlock::SystemQueuedEvents, + ActiveSonarrBlock::SystemTasks, + ActiveSonarrBlock::SystemTaskStartConfirmPrompt, + ActiveSonarrBlock::SystemUpdates + )] + active_sonarr_block: ActiveSonarrBlock, + ) { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(active_sonarr_block.into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + SystemUi::draw(f, app, f.area()); + }); + + insta::assert_snapshot!( + format!("popups_over_system_ui_{active_sonarr_block}"), + output + ); + } + } } diff --git a/src/ui/styles.rs b/src/ui/styles.rs index 3bc4ef6..306f794 100644 --- a/src/ui/styles.rs +++ b/src/ui/styles.rs @@ -40,31 +40,94 @@ where } fn awaiting_import(self) -> T { - THEME.with(|theme| self.fg(theme.get().awaiting_import.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .awaiting_import + .expect("awaiting_import style must be defined in theme") + .color + .expect("awaiting_import color must be defined"), + ) + }) } fn indeterminate(self) -> T { - THEME.with(|theme| self.fg(theme.get().indeterminate.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .indeterminate + .expect("indeterminate style must be defined in theme") + .color + .expect("indeterminate color must be defined"), + ) + }) } fn default(self) -> T { - THEME.with(|theme| self.fg(theme.get().default.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .default + .expect("default style must be defined in theme") + .color + .expect("default color must be defined"), + ) + }) } fn downloaded(self) -> T { - THEME.with(|theme| self.fg(theme.get().downloaded.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .downloaded + .expect("downloaded style must be defined in theme") + .color + .expect("downloaded color must be defined"), + ) + }) } fn downloading(self) -> T { - THEME.with(|theme| self.fg(theme.get().downloading.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .downloading + .expect("downloading style must be defined in theme") + .color + .expect("downloading color must be defined"), + ) + }) } fn failure(self) -> T { - THEME.with(|theme| self.fg(theme.get().failure.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .failure + .expect("failure style must be defined in theme") + .color + .expect("failure color must be defined"), + ) + }) } fn help(self) -> T { - THEME.with(|theme| self.fg(theme.get().help.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .help + .expect("help style must be defined in theme") + .color + .expect("help color must be defined"), + ) + }) } fn highlight(self) -> T { @@ -72,38 +135,119 @@ where } fn missing(self) -> T { - THEME.with(|theme| self.fg(theme.get().missing.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .missing + .expect("missing style must be defined in theme") + .color + .expect("missing color must be defined"), + ) + }) } fn primary(self) -> T { - THEME.with(|theme| self.fg(theme.get().primary.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .primary + .expect("primary style must be defined in theme") + .color + .expect("primary color must be defined"), + ) + }) } fn secondary(self) -> T { - THEME.with(|theme| self.fg(theme.get().secondary.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .secondary + .expect("secondary style must be defined in theme") + .color + .expect("secondary color must be defined"), + ) + }) } fn success(self) -> T { - THEME.with(|theme| self.fg(theme.get().success.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .success + .expect("success style must be defined in theme") + .color + .expect("success color must be defined"), + ) + }) } fn system_function(self) -> T { - THEME.with(|theme| self.fg(theme.get().system_function.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .system_function + .expect("system_function style must be defined in theme") + .color + .expect("system_function color must be defined"), + ) + }) } fn unmonitored(self) -> T { - THEME.with(|theme| self.fg(theme.get().unmonitored.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .unmonitored + .expect("unmonitored style must be defined in theme") + .color + .expect("unmonitored color must be defined"), + ) + }) } fn unmonitored_missing(self) -> T { - THEME.with(|theme| self.fg(theme.get().unmonitored_missing.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .unmonitored_missing + .expect("unmonitored_missing style must be defined in theme") + .color + .expect("unmonitored_missing color must be defined"), + ) + }) } fn unreleased(self) -> T { - THEME.with(|theme| self.fg(theme.get().unreleased.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .unreleased + .expect("unreleased style must be defined in theme") + .color + .expect("unreleased color must be defined"), + ) + }) } fn warning(self) -> T { - THEME.with(|theme| self.fg(theme.get().warning.unwrap().color.unwrap())) + THEME.with(|theme| { + self.fg( + theme + .get() + .warning + .expect("warning style must be defined in theme") + .color + .expect("warning color must be defined"), + ) + }) } } diff --git a/src/ui/ui_property_tests.rs b/src/ui/ui_property_tests.rs new file mode 100644 index 0000000..03431e2 --- /dev/null +++ b/src/ui/ui_property_tests.rs @@ -0,0 +1,268 @@ +#[cfg(test)] +mod ui_invariant_tests { + use proptest::prelude::*; + use ratatui::Terminal; + use ratatui::backend::TestBackend; + use ratatui::layout::Rect; + + use crate::app::App; + use crate::models::radarr_models::Movie; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; + use crate::models::sonarr_models::Series; + use crate::models::{Scrollable, stateful_table::StatefulTable}; + use crate::ui::DrawUi; + use crate::ui::radarr_ui::RadarrUi; + use crate::ui::sonarr_ui::SonarrUi; + use prop::bool::ANY; + + proptest! { + #[test] + fn test_radarr_library_never_panics_on_large_datasets( + num_movies in 0usize..500, + viewport_height in 10u16..100, + ) { + let backend = TestBackend::new(120, viewport_height); + let mut terminal = Terminal::new(backend).unwrap(); + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + + let mut quality_profile_map = bimap::BiMap::new(); + quality_profile_map.insert(0, "Any".to_string()); + app.data.radarr_data.quality_profile_map = quality_profile_map; + + let movies: Vec = (0..num_movies) + .map(|i| Movie { + id: i as i64, + title: format!("Movie {}", i).into(), + ..Movie::default() + }) + .collect(); + + let mut table = StatefulTable::default(); + table.set_items(movies); + app.data.radarr_data.movies = table; + + terminal + .draw(|f| { + RadarrUi::draw(f, &mut app, f.area()); + }) + .unwrap(); + + let buffer = terminal.backend().buffer(); + prop_assert!(buffer.area().height <= viewport_height); + prop_assert!(buffer.area().width <= 120); + } + + #[test] + fn test_sonarr_library_never_panics_on_large_datasets( + num_series in 0usize..500, + viewport_height in 10u16..100, + ) { + let backend = TestBackend::new(120, viewport_height); + let mut terminal = Terminal::new(backend).unwrap(); + let mut app = App::test_default(); + app.push_navigation_stack( + crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock::Series.into() + ); + + let mut language_profiles_map = bimap::BiMap::new(); + language_profiles_map.insert(0, "English".to_string()); + app.data.sonarr_data.language_profiles_map = language_profiles_map; + + let mut quality_profile_map = bimap::BiMap::new(); + quality_profile_map.insert(0, "Any".to_string()); + app.data.sonarr_data.quality_profile_map = quality_profile_map; + + let series: Vec = (0..num_series) + .map(|i| Series { + id: i as i64, + title: format!("Series {}", i).into(), + ..Series::default() + }) + .collect(); + + let mut table = StatefulTable::default(); + table.set_items(series); + app.data.sonarr_data.series = table; + + terminal + .draw(|f| { + SonarrUi::draw(f, &mut app, f.area()); + }) + .unwrap(); + + let buffer = terminal.backend().buffer(); + prop_assert!(buffer.area().height <= viewport_height); + prop_assert!(buffer.area().width <= 120); + } + + #[test] + fn test_ui_respects_viewport_boundaries( + viewport_width in 40u16..200, + viewport_height in 10u16..100, + ) { + let backend = TestBackend::new(viewport_width, viewport_height); + let mut terminal = Terminal::new(backend).unwrap(); + let mut app = App::test_default(); + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + + let mut quality_profile_map = bimap::BiMap::new(); + quality_profile_map.insert(0, "Any".to_string()); + app.data.radarr_data.quality_profile_map = quality_profile_map; + + let movies = vec![Movie { + id: 1, + title: "Very Long Movie Title That Should Be Scrollable And Not Overflow".into(), + ..Movie::default() + }]; + + let mut table = StatefulTable::default(); + table.set_items(movies); + app.data.radarr_data.movies = table; + + terminal + .draw(|f| { + RadarrUi::draw(f, &mut app, f.area()); + }) + .unwrap(); + + let buffer = terminal.backend().buffer(); + prop_assert_eq!(buffer.area().width, viewport_width); + prop_assert_eq!(buffer.area().height, viewport_height); + } + + #[test] + fn test_centered_rect_never_exceeds_parent( + parent_width in 20u16..200, + parent_height in 10u16..100, + percent_x in 1u16..=100, + percent_y in 1u16..=100, + ) { + use crate::ui::utils::centered_rect; + + let parent = Rect { + x: 0, + y: 0, + width: parent_width, + height: parent_height, + }; + + let centered = centered_rect(percent_x, percent_y, parent); + + prop_assert!(centered.x >= parent.x); + prop_assert!(centered.y >= parent.y); + prop_assert!(centered.x + centered.width <= parent.x + parent.width); + prop_assert!(centered.y + centered.height <= parent.y + parent.height); + } + + #[test] + fn test_table_navigation_stays_in_bounds( + num_items in 1usize..100, + num_scrolls in 0usize..200, + ) { + let mut table = StatefulTable::default(); + let movies: Vec = (0..num_items) + .map(|i| Movie { + id: i as i64, + title: format!("Movie {}", i).into(), + ..Movie::default() + }) + .collect(); + + table.set_items(movies); + + for _ in 0..num_scrolls { + table.scroll_down(); + } + + let current_item = table.current_selection(); + prop_assert!(current_item.id >= 0 && (current_item.id as usize) < num_items); + + for _ in 0..num_scrolls { + table.scroll_up(); + } + + let current_item_after = table.current_selection(); + prop_assert!(current_item_after.id >= 0 && (current_item_after.id as usize) < num_items); + } + + #[test] + fn test_empty_tables_handle_navigation_gracefully( + num_scroll_attempts in 0usize..50, + ) { + let mut table = StatefulTable::::default(); + + for _ in 0..num_scroll_attempts { + table.scroll_down(); + table.scroll_up(); + } + + prop_assert!(true); + } + + #[test] + fn test_loading_state_never_panics( + is_loading in ANY, + num_items in 0usize..100, + ) { + let backend = TestBackend::new(120, 30); + let mut terminal = Terminal::new(backend).unwrap(); + let mut app = App::test_default(); + app.is_loading = is_loading; + app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + + let mut quality_profile_map = bimap::BiMap::new(); + quality_profile_map.insert(0, "Any".to_string()); + app.data.radarr_data.quality_profile_map = quality_profile_map; + + let movies: Vec = (0..num_items) + .map(|i| Movie { + id: i as i64, + title: format!("Movie {}", i).into(), + ..Movie::default() + }) + .collect(); + + let mut table = StatefulTable::default(); + table.set_items(movies); + app.data.radarr_data.movies = table; + + terminal + .draw(|f| { + RadarrUi::draw(f, &mut app, f.area()); + }) + .unwrap(); + + prop_assert!(true); + } + + #[test] + fn test_navigation_stack_maintains_route_integrity( + stack_depth in 1usize..10, + ) { + let mut app = App::test_default(); + + let blocks = [ActiveRadarrBlock::Movies, + ActiveRadarrBlock::Collections, + ActiveRadarrBlock::Downloads, + ActiveRadarrBlock::Blocklist, + ActiveRadarrBlock::RootFolders]; + + for i in 0..stack_depth { + let block = blocks[i % blocks.len()]; + app.push_navigation_stack(block.into()); + } + + let current_route = app.get_current_route(); + let expected_block = blocks[(stack_depth - 1) % blocks.len()]; + prop_assert!(matches!(current_route, crate::models::Route::Radarr(block, _) if block == expected_block)); + + for _ in 0..stack_depth { + app.pop_navigation_stack(); + } + + let final_route = app.get_current_route(); + prop_assert!(matches!(final_route, crate::models::Route::Radarr(_, _))); + } + } +} diff --git a/src/ui/ui_test_utils.rs b/src/ui/ui_test_utils.rs new file mode 100644 index 0000000..8d97539 --- /dev/null +++ b/src/ui/ui_test_utils.rs @@ -0,0 +1,160 @@ +#[cfg(test)] +#[allow(dead_code)] +pub mod test_utils { + use chrono::DateTime; + use ratatui::Frame; + use ratatui::Terminal; + use ratatui::backend::TestBackend; + use ratatui::buffer::Buffer; + use std::cell::Cell; + + use crate::app::App; + + thread_local! { + static TIMESTAMP: Cell = const { Cell::new(0) }; + } + + pub struct Utc; + + impl Utc { + pub fn now() -> DateTime { + TIMESTAMP + .with(|timestamp| { + let ts = timestamp.get(); + DateTime::::from_timestamp(if ts != 0 { ts } else { 1684618200 }, 0) + }) + .expect("a valid timestamp set") + } + } + + pub fn set_timestamp(timestamp: i64) { + TIMESTAMP.set(timestamp / 1000); + } + + pub fn create_test_backend(width: u16, height: u16) -> TestBackend { + TestBackend::new(width, height) + } + + pub fn create_test_terminal(width: u16, height: u16) -> Terminal { + let backend = create_test_backend(width, height); + Terminal::new(backend).unwrap() + } + + pub enum TerminalSize { + Small, + Medium, + Large, + } + + impl TerminalSize { + pub fn to_cartesian(&self) -> (u16, u16) { + match self { + Self::Small => (80, 30), + Self::Medium => (120, 40), + Self::Large => (165, 50), + } + } + } + + /// Renders a UI component and returns the output as a string + /// + /// # Arguments + /// * `size` - Terminal T-shirt size (Small, Medium, or Large) + /// * `render_fn` - Function that renders to the frame + /// + /// # Example + /// ```rust + /// let output = render_to_string(TerminalSize::Medium, |f| { + /// Block::default().title("Test").render(f.area(), f.buffer_mut()); + /// }); + /// ``` + pub fn render_to_string(size: TerminalSize, mut render_fn: F) -> String + where + F: FnMut(&mut Frame), + { + let (width, height) = size.to_cartesian(); + let mut terminal = create_test_terminal(width, height); + + terminal + .draw(|f| { + render_fn(f); + }) + .unwrap(); + + buffer_to_string(terminal.backend().buffer(), width, height) + } + + /// Renders a UI component with an App instance and returns the output as a string + /// + /// This is the primary helper for testing UI components that need app state. + /// + /// # Arguments + /// * `size` - Terminal T-shirt size (Small, Medium, or Large) + /// * `app` - Mutable reference to App instance + /// * `render_fn` - Function that renders to the frame with app + /// + /// # Example + /// ```rust + /// let mut app = App::test_default(); + /// app.push_navigation_stack(ActiveRadarrBlock::Movies.into()); + /// + /// let output = render_to_string_with_app(TerminalSize::Medium, &mut app, |f, app| { + /// LibraryUi::draw(f, app, f.area()); + /// }); + /// + /// insta::assert_snapshot!(output); + /// ``` + pub fn render_to_string_with_app(size: TerminalSize, app: &mut App, mut render_fn: F) -> String + where + F: FnMut(&mut Frame, &mut App), + { + let (width, height) = size.to_cartesian(); + let mut terminal = create_test_terminal(width, height); + + terminal + .draw(|f| { + render_fn(f, app); + }) + .unwrap(); + + buffer_to_string(terminal.backend().buffer(), width, height) + } + + fn buffer_to_string(buffer: &Buffer, width: u16, height: u16) -> String { + let mut result = String::new(); + + for y in 0..height { + for x in 0..width { + let cell = buffer.cell((x, y)).expect("Cell should exist"); + result.push_str(cell.symbol()); + } + if y < height - 1 { + result.push('\n'); + } + } + + result + } + + pub fn output_contains(output: &str, text: &str) -> bool { + output.contains(text) + } + + pub fn output_contains_all(output: &str, texts: &[&str]) -> bool { + texts.iter().all(|text| output.contains(text)) + } + + pub fn count_lines(output: &str) -> usize { + output.lines().count() + } + + pub fn verify_dimensions(output: &str, max_width: usize, max_height: usize) -> bool { + let lines: Vec<&str> = output.lines().collect(); + + if lines.len() > max_height { + return false; + } + + lines.iter().all(|line| line.chars().count() <= max_width) + } +} diff --git a/src/ui/ui_tests.rs b/src/ui/ui_tests.rs new file mode 100644 index 0000000..765305e --- /dev/null +++ b/src/ui/ui_tests.rs @@ -0,0 +1,85 @@ +#[cfg(test)] +mod snapshot_tests { + use crate::app::App; + use crate::handlers::populate_keymapping_table; + use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; + use crate::ui; + use crate::ui::ui_test_utils::test_utils::{TerminalSize, render_to_string_with_app}; + + #[test] + fn test_radarr_ui_renders_library_tab() { + let mut app = App::test_default_fully_populated(); + app.push_navigation_stack(ActiveRadarrBlock::default().into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_radarr_ui_renders_library_tab_with_error() { + let mut app = App::test_default_fully_populated(); + app.error = "Some error".into(); + app.push_navigation_stack(ActiveRadarrBlock::default().into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); + + insta::assert_snapshot!(output); + } + + #[test] + fn test_radarr_ui_renders_library_tab_error_popup() { + let mut app = App::test_default_fully_populated(); + populate_keymapping_table(&mut app); + app.push_navigation_stack(ActiveRadarrBlock::default().into()); + + let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + ui(f, app); + }); + + insta::assert_snapshot!(output); + } + + // TODO after adding fully populated Sonarr data + // #[test] + // fn test_sonarr_ui_renders_library_tab() { + // let mut app = App::test_default_fully_populated(); + // app.push_navigation_stack(ActiveSonarrBlock::default().into()); + // + // let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + // ui(f, app); + // }); + // + // insta::assert_snapshot!(output); + // } + // + // #[test] + // fn test_sonarr_ui_renders_library_tab_with_error() { + // let mut app = App::test_default_fully_populated(); + // app.push_navigation_stack(ActiveSonarrBlock::default().into()); + // app.error = "Some error".into(); + // + // let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + // ui(f, app); + // }); + // + // insta::assert_snapshot!(output); + // } + // + // #[test] + // fn test_sonarr_ui_renders_library_tab_error_popup() { + // let mut app = App::test_default_fully_populated(); + // populate_keymapping_table(&mut app); + // app.push_navigation_stack(ActiveSonarrBlock::default().into()); + // + // let output = render_to_string_with_app(TerminalSize::Large, &mut app, |f, app| { + // ui(f, app); + // }); + // + // insta::assert_snapshot!(output); + // } +} diff --git a/src/ui/utils.rs b/src/ui/utils.rs index 88f3514..e56ece7 100644 --- a/src/ui/utils.rs +++ b/src/ui/utils.rs @@ -1,5 +1,5 @@ -use crate::ui::styles::ManagarrStyle; use crate::ui::THEME; +use crate::ui::styles::ManagarrStyle; use ratatui::layout::{Alignment, Constraint, Layout, Rect}; use ratatui::style::{Style, Stylize}; use ratatui::symbols; diff --git a/src/ui/widgets/input_box.rs b/src/ui/widgets/input_box.rs index da32978..918e93c 100644 --- a/src/ui/widgets/input_box.rs +++ b/src/ui/widgets/input_box.rs @@ -1,10 +1,10 @@ use derive_setters::Setters; +use ratatui::Frame; use ratatui::buffer::Buffer; use ratatui::layout::{Constraint, Layout, Position, Rect}; use ratatui::prelude::Text; use ratatui::style::{Style, Styled, Stylize}; use ratatui::widgets::{Block, Paragraph, Widget, WidgetRef}; -use ratatui::Frame; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{borderless_block, layout_block}; diff --git a/src/ui/widgets/managarr_table.rs b/src/ui/widgets/managarr_table.rs index 169fdcd..7aecb9f 100644 --- a/src/ui/widgets/managarr_table.rs +++ b/src/ui/widgets/managarr_table.rs @@ -2,18 +2,18 @@ use super::input_box_popup::InputBoxPopup; use super::message::Message; use super::popup::Size; use crate::models::stateful_table::StatefulTable; +use crate::ui::HIGHLIGHT_SYMBOL; use crate::ui::styles::ManagarrStyle; use crate::ui::utils::{borderless_block, centered_rect, title_block_centered}; use crate::ui::widgets::loading_block::LoadingBlock; use crate::ui::widgets::popup::Popup; use crate::ui::widgets::selectable_list::SelectableList; -use crate::ui::HIGHLIGHT_SYMBOL; use derive_setters::Setters; +use ratatui::Frame; use ratatui::buffer::Buffer; use ratatui::layout::{Constraint, Layout, Position, Rect}; use ratatui::prelude::{Style, Stylize, Text}; use ratatui::widgets::{Block, ListItem, Row, StatefulWidget, Table, Widget, WidgetRef}; -use ratatui::Frame; use std::fmt::Debug; use std::sync::atomic::Ordering; @@ -122,7 +122,9 @@ where }; let loading_block = LoadingBlock::new(self.is_loading, self.block.clone()); - if let Some(content) = self.content { + if let Some(content) = self.content + && !self.is_loading + { let (table_contents, table_state) = if content.filtered_items.is_some() { ( content.filtered_items.as_ref().unwrap(), @@ -193,17 +195,16 @@ where } fn parse_headers(&self) -> Vec> { - if let Some(ref content) = self.content { - if let Some(ref sort_list) = content.sort { - if !self.is_sorting { - let mut new_headers = self.table_headers.clone(); - let idx = sort_list.state.selected().unwrap_or(0); - let direction = if content.sort_asc { " ▲" } else { " ▼" }; - new_headers[idx].push_str(direction); + if let Some(ref content) = self.content + && let Some(ref sort_list) = content.sort + && !self.is_sorting + { + let mut new_headers = self.table_headers.clone(); + let idx = sort_list.state.selected().unwrap_or(0); + let direction = if content.sort_asc { " ▲" } else { " ▼" }; + new_headers[idx].push_str(direction); - return new_headers.into_iter().map(Text::from).collect(); - } - } + return new_headers.into_iter().map(Text::from).collect(); } self diff --git a/src/utils.rs b/src/utils.rs index 9e4170e..c157755 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,11 +5,11 @@ use std::process; use std::sync::Arc; use std::time::Duration; -use anyhow::anyhow; use anyhow::Result; +use anyhow::{Context, anyhow}; use colored::Colorize; use indicatif::{ProgressBar, ProgressStyle}; -use log::{error, LevelFilter}; +use log::{LevelFilter, error}; use log4rs::append::file::FileAppender; use log4rs::config::{Appender, Root}; use log4rs::encode::pattern::PatternEncoder; @@ -18,7 +18,7 @@ use reqwest::{Certificate, Client}; use tokio::sync::Mutex; use tokio_util::sync::CancellationToken; -use crate::app::{log_and_print_error, App, AppConfig}; +use crate::app::{App, AppConfig, log_and_print_error}; use crate::cli::{self, Command}; use crate::network::Network; use crate::ui::theme::ThemeDefinitionsWrapper; @@ -79,16 +79,15 @@ pub fn convert_runtime(runtime: i64) -> (i64, i64) { (hours, minutes) } -pub async fn tail_logs(no_color: bool) { - let re = Regex::new(r"^(?P\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\s+<(?P[^\s>]+)>\s+\[(?P[A-Z]+)\]\s+(?P[^:]+):(?P\d+)\s+-\s+(?P.*)$").unwrap(); +pub async fn tail_logs(no_color: bool) -> Result<()> { + let re = Regex::new(r"^(?P\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\s+<(?P[^\s>]+)>\s+\[(?P[A-Z]+)]\s+(?P[^:]+):(?P\d+)\s+-\s+(?P.*)$").unwrap(); let file_path = get_log_path(); let file = File::open(&file_path).expect("Cannot open file"); let mut reader = BufReader::new(file); - if let Err(e) = reader.seek(SeekFrom::End(0)) { - eprintln!("Unable to tail log file: {e:?}"); - process::exit(1); - }; + reader + .seek(SeekFrom::End(0)) + .with_context(|| "Unable to tail log file")?; let mut lines = reader.lines(); @@ -104,8 +103,7 @@ pub async fn tail_logs(no_color: bool) { } } }) - .await - .unwrap(); + .await? } fn colorize_log_line(line: &str, re: &Regex) -> String { @@ -176,7 +174,7 @@ pub(super) fn build_network_client(config: &AppConfig) -> Client { if let Some(radarr_configs) = &config.radarr { for radarr_config in radarr_configs { - if let Some(ref cert_path) = &radarr_config.ssl_cert_path { + if let Some(cert_path) = &radarr_config.ssl_cert_path { let cert = create_cert(cert_path, "Radarr"); client_builder = client_builder.add_root_certificate(cert); } @@ -185,7 +183,7 @@ pub(super) fn build_network_client(config: &AppConfig) -> Client { if let Some(sonarr_configs) = &config.sonarr { for sonarr_config in sonarr_configs { - if let Some(ref cert_path) = &sonarr_config.ssl_cert_path { + if let Some(cert_path) = &sonarr_config.ssl_cert_path { let cert = create_cert(cert_path, "Sonarr"); client_builder = client_builder.add_root_certificate(cert); } @@ -311,11 +309,13 @@ pub fn select_cli_configuration( } else { match command { Command::Radarr(_) => { - let default_radarr_config = config.radarr.as_ref().unwrap()[0].clone(); + let default_radarr_config = + config.radarr.as_ref().expect("Radarr config must exist")[0].clone(); app.server_tabs.select_tab_by_config(&default_radarr_config); } Command::Sonarr(_) => { - let default_sonarr_config = config.sonarr.as_ref().unwrap()[0].clone(); + let default_sonarr_config = + config.sonarr.as_ref().expect("Sonarr config must exist")[0].clone(); app.server_tabs.select_tab_by_config(&default_sonarr_config); } _ => (),