Compare commits
127 Commits
v0.4.2
..
c4e8d64710
| Author | SHA1 | Date | |
|---|---|---|---|
| c4e8d64710 | |||
| ca4319001c | |||
| ebc58b831d | |||
| b1572c903c | |||
| 5b73924e2a | |||
| 97ce258a8d | |||
| fedec79a95 | |||
| 8e74709b9c | |||
| be09e1d932 | |||
| d95417d075 | |||
| 2e3e511e3b | |||
| 8555052cc4 | |||
| 80bc6793c7 | |||
| 049a0c5d49 | |||
| ae9cb77e6d | |||
| 126ed5ed72 | |||
| 63ae64cebd | |||
| 0b29351366 | |||
| 4ea39f74fe | |||
| 76fcf5e67f | |||
| 11457736e6 | |||
| e2a6af1cbd | |||
| 20ea15009d | |||
| 00ab0f27f7 | |||
| 1f4870d082 | |||
| e96af7410e | |||
| 345bb8ce03 | |||
| dbcfc77ad4 | |||
| e653532212 | |||
| 8e7e31f64d | |||
| bff3795cc6 | |||
| 8782f1353d | |||
| f08f255a46 | |||
| 02870043ec | |||
| 154e491922 | |||
| ef5e702255 | |||
| cb4cd93bcd | |||
| ee034c9caf | |||
| c133a4ecd2 | |||
| f09a2efa5e | |||
| 49983f4173 | |||
| 0f9894e1be | |||
| 8c0dffec31 | |||
| 0085d944ea | |||
| 89cf0e66a6 | |||
| baef436f78 | |||
| cf00d7992e | |||
| f25829f3c1 | |||
| 8c783bc405 | |||
| 0048d71b74 | |||
| c633347ecc | |||
| ecd6a0ec32 | |||
| 30507d9d01 | |||
| 6245a794d5 | |||
| 5c822e4890 | |||
| cab06fe43f | |||
| b4ff5f3351 | |||
| 0834802481 | |||
| 3afd74dcbf | |||
| b1a0bdfbb6 | |||
| 6d38bc5e1d | |||
| 5ba1ba15c9 | |||
| db05d2abfb | |||
| 1840c4e39a | |||
| c5a3f424d6 | |||
| 04aa6b81b5 | |||
| 5ff3b9b996 | |||
| 228e4a61a4 | |||
| df38ea5413 | |||
| 709f6ca6ca | |||
| b012fc29e4 | |||
| bdad723aef | |||
| f97d46cec3 | |||
| 7381eaef57 | |||
| 72c922b311 | |||
| fd14a8152c | |||
| 5cb60c317d | |||
| 847de75713 | |||
| 58723cf3e8 | |||
| c613168bfb | |||
| 6f83de77f2 | |||
| 3f6ef3beb4 | |||
| 14e50c1465 | |||
| 0aa9fdca14 | |||
| dc50820abc | |||
| 81afce78ad | |||
| 8a0b912601 | |||
| 85105a953e | |||
| 40f3452d08 | |||
| a287a5c903 | |||
| f30e5270d8 | |||
| 104bcd7bb2 | |||
| fd6fcfc98f | |||
| f87e02cd7c | |||
| 9b63b10118 | |||
| 111485e7c4 | |||
| 0167753cfe | |||
| 73131cc518 | |||
| 25576757bb | |||
| 105c8f3a82 | |||
| 5164d81492 | |||
| 319e5f1ac2 | |||
| b24c2fbeb1 | |||
| bc5053c39c | |||
| f06a031c93 | |||
| 8d450dea5a | |||
| c4ace8c53f | |||
| 78f104f558 | |||
| e8a6f740b9 | |||
| 6f3c6ec840 | |||
| 47a3ef1d8b | |||
| 367e9bf33b | |||
| f122b02424 | |||
| 3a09c17f0a | |||
| 6773abb04e | |||
| b757d66d7a | |||
| 81cb7a750c | |||
| 3be59108a9 | |||
| fac9c45aee | |||
| 184bd2b510 | |||
| fda69178b9 | |||
| 652bbcd5d4 | |||
| fd35106df8 | |||
| 5ead5bc3d6 | |||
| 3ce0003315 | |||
| ee94059a15 | |||
| 844742053d |
@@ -0,0 +1,4 @@
|
|||||||
|
--artifact-server-path=./.act/artifacts
|
||||||
|
--cache-server-path=./.act/cache
|
||||||
|
--container-options --privileged
|
||||||
|
--env ACT=true
|
||||||
@@ -76,15 +76,15 @@ jobs:
|
|||||||
RUSTDOCFLAGS: --cfg docsrs
|
RUSTDOCFLAGS: --cfg docsrs
|
||||||
msrv:
|
msrv:
|
||||||
# check that we can build using the minimal rust version that is specified by this crate
|
# check that we can build using the minimal rust version that is specified by this crate
|
||||||
name: 1.82.0 / check
|
name: 1.89.0 / check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install 1.82.0
|
- name: Install 1.89.0
|
||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: 1.82.0
|
toolchain: 1.89.0
|
||||||
|
|
||||||
- name: cargo +1.82.0 check
|
- name: cargo +1.89.0 check
|
||||||
run: cargo check
|
run: cargo check
|
||||||
|
|||||||
+373
-185
@@ -8,9 +8,9 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
bump_type:
|
bump_type:
|
||||||
description: "Specify the type of version bump"
|
description: 'Specify the type of version bump'
|
||||||
required: true
|
required: true
|
||||||
default: "patch"
|
default: 'patch'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
- patch
|
- patch
|
||||||
@@ -23,6 +23,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Configure SSH for Git
|
- name: Configure SSH for Git
|
||||||
|
if: env.ACT != 'true'
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
echo "${{ secrets.RELEASE_BOT_SSH_KEY }}" > ~/.ssh/id_ed25519
|
echo "${{ secrets.RELEASE_BOT_SSH_KEY }}" > ~/.ssh/id_ed25519
|
||||||
@@ -30,15 +31,22 @@ jobs:
|
|||||||
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
if: env.ACT != 'true'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ssh-key: ${{ secrets.RELEASE_BOT_SSH_KEY }}
|
ssh-key: ${{ secrets.RELEASE_BOT_SSH_KEY }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
if: env.ACT == 'true'
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.10"
|
python-version: '3.10'
|
||||||
|
|
||||||
- name: Install Commitizen
|
- name: Install Commitizen
|
||||||
run: |
|
run: |
|
||||||
@@ -62,12 +70,6 @@ jobs:
|
|||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
- name: Update the Cargo.lock
|
|
||||||
run: |
|
|
||||||
cargo update
|
|
||||||
git add Cargo.lock
|
|
||||||
git commit -m "chore: Bump the version in Cargo.lock"
|
|
||||||
|
|
||||||
- name: Get the new version tag
|
- name: Get the new version tag
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
@@ -84,25 +86,154 @@ jobs:
|
|||||||
echo "Previous tag: $PREV_TAG"
|
echo "Previous tag: $PREV_TAG"
|
||||||
echo "prev_version=$PREV_TAG" >> $GITHUB_ENV
|
echo "prev_version=$PREV_TAG" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Bump Cargo.toml version
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
env:
|
||||||
|
VERSION: ${{ env.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
: "${VERSION:?env.version is empty}"
|
||||||
|
|
||||||
|
# Ignore Act's local artifact dir noise
|
||||||
|
echo artifacts/ >> .git/info/exclude || true
|
||||||
|
|
||||||
|
# Edit the version line right after name="managarr"
|
||||||
|
sed -E -i '
|
||||||
|
/^[[:space:]]*name[[:space:]]*=[[:space:]]*"managarr"[[:space:]]*$/ {
|
||||||
|
n
|
||||||
|
s|^[[:space:]]*version[[:space:]]*=[[:space:]]*"[^"]*"|version = "'"$VERSION"'"|
|
||||||
|
}
|
||||||
|
' Cargo.toml
|
||||||
|
|
||||||
|
cargo update || true
|
||||||
|
|
||||||
|
# Git config that helps in containers (Act)
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||||
|
|
||||||
|
# Debug: show what changed
|
||||||
|
git status --porcelain
|
||||||
|
git diff --name-only -- Cargo.toml Cargo.lock || true
|
||||||
|
|
||||||
|
# Only commit if one of these files actually changed
|
||||||
|
if ! git diff --quiet -- Cargo.toml Cargo.lock; then
|
||||||
|
# Stage only modifications of already tracked files (won't pick up artifacts/)
|
||||||
|
git add -u -- Cargo.toml Cargo.lock
|
||||||
|
git commit -m "chore: bump Cargo.toml to $VERSION"
|
||||||
|
else
|
||||||
|
echo "No changes to commit (already at $VERSION)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Bump validate_theme_derive/Cargo.toml version
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ github.workspace }}/proc_macros/validate_theme_derive
|
||||||
|
env:
|
||||||
|
VERSION: ${{ env.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
: "${VERSION:?env.version is empty}"
|
||||||
|
|
||||||
|
# Ignore Act's local artifact dir noise
|
||||||
|
echo artifacts/ >> .git/info/exclude || true
|
||||||
|
|
||||||
|
# Edit the version line right after name="managarr"
|
||||||
|
sed -E -i '
|
||||||
|
/^[[:space:]]*name[[:space:]]*=[[:space:]]*"managarr"[[:space:]]*$/ {
|
||||||
|
n
|
||||||
|
s|^[[:space:]]*version[[:space:]]*=[[:space:]]*"[^"]*"|version = "'"$VERSION"'"|
|
||||||
|
}
|
||||||
|
' Cargo.toml
|
||||||
|
|
||||||
|
cargo update || true
|
||||||
|
|
||||||
|
# Git config that helps in containers (Act)
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||||
|
|
||||||
|
# Debug: show what changed
|
||||||
|
git status --porcelain
|
||||||
|
git diff --name-only -- Cargo.toml || true
|
||||||
|
|
||||||
|
# Only commit if one of these files actually changed
|
||||||
|
if ! git diff --quiet -- Cargo.toml; then
|
||||||
|
# Stage only modifications of already tracked files (won't pick up artifacts/)
|
||||||
|
git add -u -- Cargo.toml
|
||||||
|
git commit -m "chore: bump validate_theme_derive Cargo.toml to $VERSION"
|
||||||
|
else
|
||||||
|
echo "No changes to commit (already at $VERSION)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Bump enum_display_style_derive/Cargo.toml version
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ github.workspace }}/proc_macros/enum_display_style_derive
|
||||||
|
env:
|
||||||
|
VERSION: ${{ env.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
: "${VERSION:?env.version is empty}"
|
||||||
|
|
||||||
|
# Ignore Act's local artifact dir noise
|
||||||
|
echo artifacts/ >> .git/info/exclude || true
|
||||||
|
|
||||||
|
# Edit the version line right after name="managarr"
|
||||||
|
sed -E -i '
|
||||||
|
/^[[:space:]]*name[[:space:]]*=[[:space:]]*"managarr"[[:space:]]*$/ {
|
||||||
|
n
|
||||||
|
s|^[[:space:]]*version[[:space:]]*=[[:space:]]*"[^"]*"|version = "'"$VERSION"'"|
|
||||||
|
}
|
||||||
|
' Cargo.toml
|
||||||
|
|
||||||
|
cargo update || true
|
||||||
|
|
||||||
|
# Git config that helps in containers (Act)
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||||
|
|
||||||
|
# Debug: show what changed
|
||||||
|
git status --porcelain
|
||||||
|
git diff --name-only -- Cargo.toml || true
|
||||||
|
|
||||||
|
# Only commit if one of these files actually changed
|
||||||
|
if ! git diff --quiet -- Cargo.toml; then
|
||||||
|
# Stage only modifications of already tracked files (won't pick up artifacts/)
|
||||||
|
git add -u -- Cargo.toml
|
||||||
|
git commit -m "chore: bump enum_display_style_derive Cargo.toml to $VERSION"
|
||||||
|
else
|
||||||
|
echo "No changes to commit (already at $VERSION)"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Generate changelog for the version bump
|
- name: Generate changelog for the version bump
|
||||||
id: changelog
|
id: changelog
|
||||||
run: |
|
run: |
|
||||||
changelog=$(conventional-changelog -p angular -i CHANGELOG.md -s --from ${{ env.prev_version }} --to ${{ env.version }})
|
conventional-changelog -p angular -i CHANGELOG.md --from ${{ env.prev_version }} --to v${{ env.version }} > artifacts/changelog.md
|
||||||
echo "$changelog" > artifacts/changelog.md
|
|
||||||
echo "changelog_body=$(cat artifacts/changelog.md)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Push changes
|
- name: Push changes
|
||||||
|
if: env.ACT != 'true'
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
git push origin --follow-tags
|
git push origin --follow-tags
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
|
||||||
|
- name: Upload the changed Cargo files (Act)
|
||||||
|
if: env.ACT == 'true'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bumped-cargo-files
|
||||||
|
path: |
|
||||||
|
Cargo.toml
|
||||||
|
Cargo.lock
|
||||||
|
proc_macros/validate_theme_derive/Cargo.toml
|
||||||
|
proc_macros/enum_display_style_derive/Cargo.toml
|
||||||
|
|
||||||
build-release-artifacts:
|
build-release-artifacts:
|
||||||
name: build-release
|
name: build-release
|
||||||
needs: [bump-version]
|
needs: [bump-version]
|
||||||
@@ -130,7 +261,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check if actor is repository owner
|
- name: Check if actor is repository owner
|
||||||
if: ${{ github.actor != github.repository_owner }}
|
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
|
||||||
run: |
|
run: |
|
||||||
echo "You are not authorized to run this workflow."
|
echo "You are not authorized to run this workflow."
|
||||||
exit 1
|
exit 1
|
||||||
@@ -141,10 +272,18 @@ jobs:
|
|||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
- name: Ensure repository is up-to-date
|
- name: Ensure repository is up-to-date
|
||||||
|
if: env.ACT != 'true'
|
||||||
run: |
|
run: |
|
||||||
git fetch --all
|
git fetch --all
|
||||||
git pull
|
git pull
|
||||||
|
|
||||||
|
- name: Get bumped Cargo files (Act)
|
||||||
|
if: env.ACT == 'true'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bumped-cargo-files
|
||||||
|
path: ${{ github.workspace }}
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
name: Cache Cargo registry
|
name: Cache Cargo registry
|
||||||
with:
|
with:
|
||||||
@@ -236,28 +375,36 @@ jobs:
|
|||||||
cp target/${{ matrix.job.target }}/release/${{ env.RELEASE_NAME }}.sha256 artifacts/
|
cp target/${{ matrix.job.target }}/release/${{ env.RELEASE_NAME }}.sha256 artifacts/
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts-${{ env.RELEASE_NAME }}
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
publish-github-release:
|
publish-github-release:
|
||||||
name: publish-github-release
|
name: publish-github-release
|
||||||
needs: [build-release-artifacts]
|
needs: [build-release-artifacts]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: Check if actor is repository owner
|
||||||
|
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
|
||||||
|
run: |
|
||||||
|
echo "You are not authorized to run this workflow."
|
||||||
|
exit 1
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Ensure repository is up-to-date
|
- name: Ensure repository is up-to-date
|
||||||
|
if: env.ACT != 'true'
|
||||||
run: |
|
run: |
|
||||||
git fetch --all
|
git fetch --all
|
||||||
git pull
|
git pull
|
||||||
@@ -266,10 +413,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
release_version="$(cat ./artifacts/release-version)"
|
release_version="$(cat ./artifacts/release-version)"
|
||||||
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||||
changelog_body="$(cat ./artifacts/changelog.md)"
|
|
||||||
echo "changelog_body=$(cat artifacts/changelog.md)" >> $GITHUB_ENV
|
- name: Validate release environment variables
|
||||||
|
run: |
|
||||||
|
echo "Release version: ${{ env.RELEASE_VERSION }}"
|
||||||
|
echo "Changelog body: $(cat artifacts/changelog.md)"
|
||||||
|
|
||||||
- name: Create a GitHub Release
|
- name: Create a GitHub Release
|
||||||
|
if: env.ACT != 'true'
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -300,201 +451,238 @@ jobs:
|
|||||||
artifacts/managarr-armv7-musl.tar.gz
|
artifacts/managarr-armv7-musl.tar.gz
|
||||||
artifacts/managarr-armv7-musl.sha256
|
artifacts/managarr-armv7-musl.sha256
|
||||||
tag_name: v${{ env.RELEASE_VERSION }}
|
tag_name: v${{ env.RELEASE_VERSION }}
|
||||||
name: "v${{ env.RELEASE_VERSION }}"
|
name: 'v${{ env.RELEASE_VERSION }}'
|
||||||
body: ${{ env.changelog_body }}
|
body_path: artifacts/changelog.md
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
|
||||||
path: artifacts
|
path: artifacts
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
# publish-chocolatey-package:
|
publish-chocolatey-package:
|
||||||
# needs: [publish-github-release]
|
needs: [publish-github-release]
|
||||||
# name: Publish Chocolatey Package
|
name: Publish Chocolatey Package
|
||||||
# runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
# steps:
|
steps:
|
||||||
# - name: Checkout repository
|
- name: Check if actor is repository owner
|
||||||
# uses: actions/checkout@v4
|
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
|
||||||
# with:
|
run: |
|
||||||
# fetch-depth: 1
|
echo "You are not authorized to run this workflow."
|
||||||
|
exit 1
|
||||||
|
|
||||||
# - name: Get release artifacts
|
- name: Checkout repository
|
||||||
# uses: actions/download-artifact@v3
|
uses: actions/checkout@v4
|
||||||
# with:
|
with:
|
||||||
# name: artifacts
|
fetch-depth: 1
|
||||||
# path: artifacts
|
|
||||||
|
|
||||||
# - name: Set release assets and version
|
- name: Get release artifacts
|
||||||
# shell: pwsh
|
uses: actions/download-artifact@v4
|
||||||
# run: |
|
with:
|
||||||
# # Read the first column from the SHA256 file
|
path: artifacts
|
||||||
# $windows_sha = Get-Content ./artifacts/managarr-windows.sha256 | ForEach-Object { $_.Split(' ')[0] }
|
merge-multiple: true
|
||||||
# Add-Content -Path $env:GITHUB_ENV -Value "WINDOWS_SHA=$windows_sha"
|
|
||||||
|
|
||||||
# # Read the release version from the release-version file
|
- name: Set release assets and version
|
||||||
# $release_version = Get-Content ./artifacts/release-version
|
shell: pwsh
|
||||||
# Add-Content -Path $env:GITHUB_ENV -Value "RELEASE_VERSION=$release_version"
|
run: |
|
||||||
|
# Read the first column from the SHA256 file
|
||||||
|
$windows_sha = Get-Content ./artifacts/managarr-windows.sha256 | ForEach-Object { $_.Split(' ')[0] }
|
||||||
|
Add-Content -Path $env:GITHUB_ENV -Value "WINDOWS_SHA=$windows_sha"
|
||||||
|
|
||||||
# - name: Validate release environment variables
|
# Read the release version from the release-version file
|
||||||
# run: |
|
$release_version = Get-Content ./artifacts/release-version
|
||||||
# echo "Release SHA windows: ${{ env.WINDOWS_SHA }}"
|
Add-Content -Path $env:GITHUB_ENV -Value "RELEASE_VERSION=$release_version"
|
||||||
# echo "Release version: ${{ env.RELEASE_VERSION }}"
|
|
||||||
|
|
||||||
# - name: Package and Publish package to Chocolatey
|
- name: Validate release environment variables
|
||||||
# run: |
|
run: |
|
||||||
# mkdir ./deployment/chocolatey/tools
|
echo "Release SHA windows: ${{ env.WINDOWS_SHA }}"
|
||||||
# # Run packaging script
|
echo "Release version: ${{ env.RELEASE_VERSION }}"
|
||||||
# python "./deployment/chocolatey/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/chocolatey/managarr.nuspec.template" "./deployment/chocolatey/managarr.nuspec" ${{ env.WINDOWS_SHA }}
|
|
||||||
# python "./deployment/chocolatey/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/chocolatey/chocolateyinstall.ps1.template" "./deployment/chocolatey/tools/chocolateyinstall.ps1" ${{ env.WINDOWS_SHA }}
|
|
||||||
|
|
||||||
# # Publish to Chocolatey
|
- name: Package and Publish package to Chocolatey
|
||||||
# cd ./deployment/chocolatey
|
if: env.ACT != 'true'
|
||||||
# choco pack
|
run: |
|
||||||
# echo y | choco install managarr -dv -s .
|
mkdir ./deployment/chocolatey/tools
|
||||||
# $version = managarr --version
|
# Run packaging script
|
||||||
# $version = $version -replace " ", "."
|
python "./deployment/chocolatey/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/chocolatey/managarr.nuspec.template" "./deployment/chocolatey/managarr.nuspec" ${{ env.WINDOWS_SHA }}
|
||||||
# choco push $version.nupkg -s https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }};
|
python "./deployment/chocolatey/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/chocolatey/chocolateyinstall.ps1.template" "./deployment/chocolatey/tools/chocolateyinstall.ps1" ${{ env.WINDOWS_SHA }}
|
||||||
|
|
||||||
# publish-homebrew-formula:
|
# Publish to Chocolatey
|
||||||
# needs: [publish-github-release]
|
cd ./deployment/chocolatey
|
||||||
# name: Update Homebrew formulas
|
choco pack
|
||||||
# runs-on: ubuntu-latest
|
echo y | choco install managarr -dv -s .
|
||||||
# steps:
|
$version = managarr --version
|
||||||
# - name: Checkout repository
|
$version = $version -replace " ", "."
|
||||||
# uses: actions/checkout@v4
|
choco push $version.nupkg -s https://push.chocolatey.org/ --api-key ${{ secrets.CHOCOLATEY_API_KEY }};
|
||||||
# with:
|
|
||||||
# fetch-depth: 1
|
|
||||||
|
|
||||||
# - name: Get release artifacts
|
publish-homebrew-formula:
|
||||||
# uses: actions/download-artifact@v3
|
needs: [publish-github-release]
|
||||||
# with:
|
name: Update Homebrew formulas
|
||||||
# name: artifacts
|
runs-on: ubuntu-latest
|
||||||
# path: artifacts
|
steps:
|
||||||
|
- name: Check if actor is repository owner
|
||||||
|
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
|
||||||
|
run: |
|
||||||
|
echo "You are not authorized to run this workflow."
|
||||||
|
exit 1
|
||||||
|
|
||||||
# - name: Set release assets and version
|
- name: Checkout repository
|
||||||
# shell: bash
|
uses: actions/checkout@v4
|
||||||
# run: |
|
with:
|
||||||
# # Set environment variables
|
fetch-depth: 1
|
||||||
# macos_sha="$(cat ./artifacts/managarr-macos.sha256 | awk '{print $1}')"
|
|
||||||
# echo "MACOS_SHA=$macos_sha" >> $GITHUB_ENV
|
|
||||||
# macos_sha_arm="$(cat ./artifacts/managarr-macos-arm64.sha256 | awk '{print $1}')"
|
|
||||||
# echo "MACOS_SHA_ARM=$macos_sha_arm" >> $GITHUB_ENV
|
|
||||||
# linux_sha="$(cat ./artifacts/managarr-linux-musl.sha256 | awk '{print $1}')"
|
|
||||||
# echo "LINUX_SHA=$linux_sha" >> $GITHUB_ENV
|
|
||||||
# release_version="$(cat ./artifacts/release-version)"
|
|
||||||
# echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# - name: Validate release environment variables
|
- name: Get release artifacts
|
||||||
# run: |
|
uses: actions/download-artifact@v4
|
||||||
# echo "Release SHA macos: ${{ env.MACOS_SHA }}"
|
with:
|
||||||
# echo "Release SHA macos-arm: ${{ env.MACOS_SHA_ARM }}"
|
path: artifacts
|
||||||
# echo "Release SHA linux musl: ${{ env.LINUX_SHA }}"
|
merge-multiple: true
|
||||||
# echo "Release version: ${{ env.RELEASE_VERSION }}"
|
|
||||||
|
|
||||||
# - name: Execute Homebrew packaging script
|
- name: Set release assets and version
|
||||||
# run: |
|
shell: bash
|
||||||
# # run packaging script
|
run: |
|
||||||
# python "./deployment/homebrew/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/homebrew/managarr.rb.template" "./managarr.rb" ${{ env.MACOS_SHA }} ${{ env.MACOS_SHA_ARM }} ${{ env.LINUX_SHA }}
|
# Set environment variables
|
||||||
|
macos_sha="$(cat ./artifacts/managarr-macos.sha256 | awk '{print $1}')"
|
||||||
|
echo "MACOS_SHA=$macos_sha" >> $GITHUB_ENV
|
||||||
|
macos_sha_arm="$(cat ./artifacts/managarr-macos-arm64.sha256 | awk '{print $1}')"
|
||||||
|
echo "MACOS_SHA_ARM=$macos_sha_arm" >> $GITHUB_ENV
|
||||||
|
linux_sha="$(cat ./artifacts/managarr-linux-musl.sha256 | awk '{print $1}')"
|
||||||
|
echo "LINUX_SHA=$linux_sha" >> $GITHUB_ENV
|
||||||
|
release_version="$(cat ./artifacts/release-version)"
|
||||||
|
echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV
|
||||||
|
|
||||||
# - name: Push changes to Homebrew tap
|
- name: Validate release environment variables
|
||||||
# env:
|
run: |
|
||||||
# TOKEN: ${{ secrets.MANAGARR_GITHUB_TOKEN }}
|
echo "Release SHA macos: ${{ env.MACOS_SHA }}"
|
||||||
# run: |
|
echo "Release SHA macos-arm: ${{ env.MACOS_SHA_ARM }}"
|
||||||
# # push to Git
|
echo "Release SHA linux musl: ${{ env.LINUX_SHA }}"
|
||||||
# git config --global user.name "Dark-Alex-17"
|
echo "Release version: ${{ env.RELEASE_VERSION }}"
|
||||||
# git config --global user.email "alex.j.tusa@gmail.com"
|
|
||||||
# git clone https://Dark-Alex-17:${{ secrets.MANAGARR_GITHUB_TOKEN }}@github.com/Dark-Alex-17/homebrew-managarr.git
|
|
||||||
# rm homebrew-managarr/Formula/managarr.rb
|
|
||||||
# cp managarr.rb homebrew-managarr/Formula
|
|
||||||
# cd homebrew-managarr
|
|
||||||
# git add .
|
|
||||||
# git diff-index --quiet HEAD || git commit -am "Update formula for Managarr release ${{ env.RELEASE_VERSION }}"
|
|
||||||
# git push https://$TOKEN@github.com/Dark-Alex-17/homebrew-managarr.git
|
|
||||||
|
|
||||||
# publish-docker-image:
|
- name: Execute Homebrew packaging script
|
||||||
# needs: [publish-github-release]
|
if: env.ACT != 'true'
|
||||||
# name: Publishing Docker image to Docker Hub
|
run: |
|
||||||
# runs-on: ubuntu-latest
|
# run packaging script
|
||||||
# steps:
|
python "./deployment/homebrew/packager.py" ${{ env.RELEASE_VERSION }} "./deployment/homebrew/managarr.rb.template" "./managarr.rb" ${{ env.MACOS_SHA }} ${{ env.MACOS_SHA_ARM }} ${{ env.LINUX_SHA }}
|
||||||
# - name: Checkout repository
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# with:
|
|
||||||
# fetch-depth: 1
|
|
||||||
|
|
||||||
# - name: Get release artifacts
|
- name: Push changes to Homebrew tap
|
||||||
# uses: actions/download-artifact@v3
|
if: env.ACT != 'true'
|
||||||
# with:
|
env:
|
||||||
# name: artifacts
|
TOKEN: ${{ secrets.MANAGARR_GITHUB_TOKEN }}
|
||||||
# path: artifacts
|
run: |
|
||||||
|
# push to Git
|
||||||
|
git config --global user.name "Dark-Alex-17"
|
||||||
|
git config --global user.email "alex.j.tusa@gmail.com"
|
||||||
|
git clone https://Dark-Alex-17:${{ secrets.MANAGARR_GITHUB_TOKEN }}@github.com/Dark-Alex-17/homebrew-managarr.git
|
||||||
|
rm homebrew-managarr/Formula/managarr.rb
|
||||||
|
cp managarr.rb homebrew-managarr/Formula
|
||||||
|
cd homebrew-managarr
|
||||||
|
git add .
|
||||||
|
git diff-index --quiet HEAD || git commit -am "Update formula for Managarr release ${{ env.RELEASE_VERSION }}"
|
||||||
|
git push https://$TOKEN@github.com/Dark-Alex-17/homebrew-managarr.git
|
||||||
|
|
||||||
# - name: Set version variable
|
publish-docker-image:
|
||||||
# run: |
|
needs: [publish-github-release]
|
||||||
# version="$(cat artifacts/release-version)"
|
name: Publishing Docker image to Docker Hub
|
||||||
# echo "version=$version" >> $GITHUB_ENV
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if actor is repository owner
|
||||||
|
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
|
||||||
|
run: |
|
||||||
|
echo "You are not authorized to run this workflow."
|
||||||
|
exit 1
|
||||||
|
|
||||||
# - name: Validate release environment variables
|
- name: Checkout repository
|
||||||
# run: |
|
uses: actions/checkout@v4
|
||||||
# echo "Release version: ${{ env.version }}"
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
# - name: Set up QEMU
|
- name: Get release artifacts
|
||||||
# uses: docker/setup-qemu-action@v3
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
# - name: Set up Docker Buildx
|
- name: Ensure repository is up-to-date
|
||||||
# uses: docker/setup-buildx-action@v3
|
if: env.ACT != 'true'
|
||||||
|
run: |
|
||||||
|
git fetch --all
|
||||||
|
git pull
|
||||||
|
|
||||||
# - name: Login to Docker Hub
|
- name: Set version variable
|
||||||
# uses: docker/login-action@v3
|
run: |
|
||||||
# with:
|
version="$(cat artifacts/release-version)"
|
||||||
# username: ${{ secrets.DOCKER_USERNAME }}
|
echo "version=$version" >> $GITHUB_ENV
|
||||||
# password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
# - name: Push to Docker Hub
|
- name: Validate release environment variables
|
||||||
# uses: docker/build-push-action@v5
|
run: |
|
||||||
# with:
|
echo "Release version: ${{ env.version }}"
|
||||||
# context: .
|
|
||||||
# file: Dockerfile
|
|
||||||
# platforms: linux/amd64,linux/arm64
|
|
||||||
# push: true
|
|
||||||
# tags: darkalex17/managarr:latest, darkalex17/managarr:${{ env.version }}
|
|
||||||
|
|
||||||
# publish-crate:
|
- name: Set up QEMU
|
||||||
# needs: publish-github-release
|
uses: docker/setup-qemu-action@v3
|
||||||
# name: Publish Crate
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - name: Check if actor is repository owner
|
|
||||||
# if: ${{ github.actor != github.repository_owner }}
|
|
||||||
# run: |
|
|
||||||
# echo "You are not authorized to run this workflow."
|
|
||||||
# exit 1
|
|
||||||
|
|
||||||
# - name: Checkout
|
- name: Set up Docker Buildx
|
||||||
# uses: actions/checkout@v4
|
uses: docker/setup-buildx-action@v3
|
||||||
# with:
|
|
||||||
# fetch-depth: 0
|
|
||||||
|
|
||||||
# - name: Ensure repository is up-to-date
|
- name: Login to Docker Hub
|
||||||
# run: |
|
if: env.ACT != 'true'
|
||||||
# git fetch --all
|
uses: docker/login-action@v3
|
||||||
# git pull
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
# - uses: actions/cache@v3
|
- name: Push to Docker Hub
|
||||||
# name: Cache Cargo registry
|
uses: docker/build-push-action@v5
|
||||||
# with:
|
with:
|
||||||
# path: ~/.cargo/registry
|
context: .
|
||||||
# key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
|
file: Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ env.ACT != 'true' }}
|
||||||
|
tags: darkalex17/managarr:latest, darkalex17/managarr:${{ env.version }}
|
||||||
|
|
||||||
# - uses: actions/cache@v3
|
publish-crate:
|
||||||
# with:
|
needs: publish-github-release
|
||||||
# path: ~/.cargo/bin
|
name: Publish Crate
|
||||||
# key: ${{ runner.os }}-cargo-bin-${{ hashFiles('.github/workflows/release.yml') }}
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if actor is repository owner
|
||||||
|
if: ${{ github.actor != github.repository_owner && env.ACT != 'true' }}
|
||||||
|
run: |
|
||||||
|
echo "You are not authorized to run this workflow."
|
||||||
|
exit 1
|
||||||
|
|
||||||
# - name: Install Rust stable
|
- name: Checkout
|
||||||
# uses: dtolnay/rust-toolchain@stable
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
# - uses: katyo/publish-crates@v2
|
- name: Get bumped Cargo files (Act)
|
||||||
# with:
|
if: env.ACT == 'true'
|
||||||
# registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bumped-cargo-files
|
||||||
|
path: ${{ github.workspace }}
|
||||||
|
|
||||||
|
- name: Ensure repository is up-to-date
|
||||||
|
if: env.ACT != 'true'
|
||||||
|
run: |
|
||||||
|
git fetch --all
|
||||||
|
git pull
|
||||||
|
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
name: Cache Cargo registry
|
||||||
|
with:
|
||||||
|
path: ~/.cargo/registry
|
||||||
|
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
|
||||||
|
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.cargo/bin
|
||||||
|
key: ${{ runner.os }}-cargo-bin-${{ hashFiles('.github/workflows/release.yml') }}
|
||||||
|
|
||||||
|
- name: Install Rust stable
|
||||||
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
- uses: katyo/publish-crates@v2
|
||||||
|
if: env.ACT != 'true'
|
||||||
|
with:
|
||||||
|
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
|||||||
+40
-39
@@ -48,51 +48,51 @@ jobs:
|
|||||||
- name: cargo test --locked
|
- name: cargo test --locked
|
||||||
run: cargo test --locked --all-features --all-targets
|
run: cargo test --locked --all-features --all-targets
|
||||||
|
|
||||||
minimal-versions:
|
# minimal-versions:
|
||||||
# This action chooses the oldest version of the dependencies permitted by Cargo.toml to ensure
|
# # This action chooses the oldest version of the dependencies permitted by Cargo.toml to ensure
|
||||||
# that this crate is compatible with the minimal version that this crate and its dependencies
|
# # that this crate is compatible with the minimal version that this crate and its dependencies
|
||||||
# require. This will pickup issues where this create relies on functionality that was introduced
|
# # require. This will pickup issues where this create relies on functionality that was introduced
|
||||||
# later than the actual version specified (e.g., when we choose just a major version, but a
|
# # later than the actual version specified (e.g., when we choose just a major version, but a
|
||||||
# method was added after this version).
|
# # method was added after this version).
|
||||||
#
|
# #
|
||||||
# This particular check can be difficult to get to succeed as often transitive dependencies may
|
# # This particular check can be difficult to get to succeed as often transitive dependencies may
|
||||||
# be incorrectly specified (e.g., a dependency specifies 1.0 but really requires 1.1.5). There
|
# # be incorrectly specified (e.g., a dependency specifies 1.0 but really requires 1.1.5). There
|
||||||
# is an alternative flag available -Zdirect-minimal-versions that uses the minimal versions for
|
# # is an alternative flag available -Zdirect-minimal-versions that uses the minimal versions for
|
||||||
# direct dependencies of this crate, while selecting the maximal versions for the transitive
|
# # direct dependencies of this crate, while selecting the maximal versions for the transitive
|
||||||
# dependencies. Alternatively, you can add a line in your Cargo.toml to artificially increase
|
# # dependencies. Alternatively, you can add a line in your Cargo.toml to artificially increase
|
||||||
# the minimal dependency, which you do with e.g.:
|
# # the minimal dependency, which you do with e.g.:
|
||||||
# ```toml
|
# # ```toml
|
||||||
# # for minimal-versions
|
# # # for minimal-versions
|
||||||
# [target.'cfg(any())'.dependencies]
|
# # [target.'cfg(any())'.dependencies]
|
||||||
# openssl = { version = "0.10.55", optional = true } # needed to allow foo to build with -Zminimal-versions
|
# # openssl = { version = "0.10.55", optional = true } # needed to allow foo to build with -Zminimal-versions
|
||||||
# ```
|
# # ```
|
||||||
# The optional = true is necessary in case that dependency isn't otherwise transitively required
|
# # The optional = true is necessary in case that dependency isn't otherwise transitively required
|
||||||
# by your library, and the target bit is so that this dependency edge never actually affects
|
# # by your library, and the target bit is so that this dependency edge never actually affects
|
||||||
# Cargo build order. See also
|
# # Cargo build order. See also
|
||||||
# https://github.com/jonhoo/fantoccini/blob/fde336472b712bc7ebf5b4e772023a7ba71b2262/Cargo.toml#L47-L49.
|
# # https://github.com/jonhoo/fantoccini/blob/fde336472b712bc7ebf5b4e772023a7ba71b2262/Cargo.toml#L47-L49.
|
||||||
# This action is run on ubuntu with the stable toolchain, as it is not expected to fail
|
# # This action is run on ubuntu with the stable toolchain, as it is not expected to fail
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
name: ubuntu / stable / minimal-versions
|
# name: ubuntu / stable / minimal-versions
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust stable
|
# - name: Install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
# uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
- name: Install nightly for -Zdirect-minimal-versions
|
# - name: Install nightly for -Zdirect-minimal-versions
|
||||||
uses: dtolnay/rust-toolchain@nightly
|
# uses: dtolnay/rust-toolchain@nightly
|
||||||
|
|
||||||
- name: rustup default stable
|
# - name: rustup default stable
|
||||||
run: rustup default stable
|
# run: rustup default stable
|
||||||
|
|
||||||
- name: cargo update -Zdirect-minimal-versions
|
# - name: cargo update -Zdirect-minimal-versions
|
||||||
run: cargo +nightly update -Zdirect-minimal-versions
|
# run: cargo +nightly update -Zdirect-minimal-versions
|
||||||
|
|
||||||
- name: cargo test
|
# - name: cargo test
|
||||||
run: cargo test --locked --all-features --all-targets
|
# run: cargo test --locked --all-features --all-targets
|
||||||
|
|
||||||
- name: Cache Cargo dependencies
|
# - name: Cache Cargo dependencies
|
||||||
uses: Swatinem/rust-cache@v2
|
# uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
os-check:
|
os-check:
|
||||||
# run cargo test on mac and windows
|
# run cargo test on mac and windows
|
||||||
@@ -175,6 +175,7 @@ jobs:
|
|||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: Upload to codecov.io
|
- name: Upload to codecov.io
|
||||||
|
if: env.ACT != 'true'
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v4
|
||||||
with:
|
with:
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
/.idea/
|
/.idea/
|
||||||
/.scannerwork/
|
/.scannerwork/
|
||||||
|
/.act/
|
||||||
|
|||||||
@@ -5,6 +5,93 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## v0.6.1 (2025-09-02)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- Fixed UI bugs introduced as part of the hotkey refactor
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- Updated crate to publish properly with the procedural macros
|
||||||
|
|
||||||
|
## v0.6.0 (2025-08-29)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- Support for custom headers to be added to every request to each server to support alternative authentication mechanisms [#47]
|
||||||
|
- Refactor all keybinding tips into a dynamically changing menu that can be invoked via '?' [#32]
|
||||||
|
- Display total disk usage for series in the Library view to mirror Radarr functionality [#44]
|
||||||
|
- Pagination support for jumping 20 items at a time in all table views [#45]
|
||||||
|
- Support toggling Movie monitoring directly from the library view [#43]
|
||||||
|
- Support toggling Movie monitoring from the CLI
|
||||||
|
- Support toggling Series monitoring directly from the Sonarr library view [#43]
|
||||||
|
- Support toggling Series monitoring from the CLI
|
||||||
|
- Fixed the Radarr downloads tab to display more than 10 downloads at a time and added a new --count flag to the CLI for specifying the number of downloads to return
|
||||||
|
- Fetch more than 10 downloads when listing Sonarr downloads, and add a --count flag to the CLI to specify how many downloads to fetch
|
||||||
|
- Support alternative keymappings for all keys, featuring hjkl movements
|
||||||
|
- Added the Eldritch theme and updated documentation
|
||||||
|
- Write built in themes to the themes file on first run so users can define custom themes
|
||||||
|
- Created a theme validation macro to verify theme configurations before allowing the TUI to start
|
||||||
|
- Initial support for custom user-defined themes
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- Marked Radarr studios as nullable to prevent crashes
|
||||||
|
- Fixed a bug where the Sonarr API was returning empty values for seeders when searching for season releases
|
||||||
|
- Improve fault tolerance for tag associations in Radarr and Sonarr
|
||||||
|
- Upgraded to the most recent version of Tokio to mitigate CWE-664
|
||||||
|
- Updated all dependencies and updated openssl to the most recent version to mitigate CWE-416
|
||||||
|
- Updated the name of the should_ignore_quit_key to ignore_special_keys_for_textbox_input to give a better idea of what the flag is used for; also added alt keybinding for backspace
|
||||||
|
- Marked videoCodecs as Option to resolve #38
|
||||||
|
- Marked the `Season.statistics` field as `Option` so that a panic does not happen for outdated Sonarr data. This resolves #35
|
||||||
|
- When adding a film from the Collection Details modal, the render order was wrong: Radarr Library -> Collection Table -> Add Movie Prompt (missing the Collection details prompt too). Correct order is: Collection Table -> Collection Details Modal -> Add Movie Modal
|
||||||
|
- Fixed a bug that was rendering encompassing blocks after other widgets were rendered, thus overwriting the custom styles on each previously rendered widget
|
||||||
|
- change the name of the theme configuration file to 'themes'
|
||||||
|
- Ensure key events are only processed on key press to avoid duplicates
|
||||||
|
- Updated ring dependency to mitigate CWE-770
|
||||||
|
- Modified the Sonarr DownloadRecord so that the episode_id is optional to prevent crashes for weird downloads
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- Network module is now broken out into similar directory structures for each servarr to mimic the rest of the project to make it easier to develop and maintain
|
||||||
|
- Refactored the IndexerTestResut model into the general Servarr models
|
||||||
|
- Renamed 'ctrl-*' keyboard shortcuts to 'C-*' to simplify and shrink the on-screen help
|
||||||
|
- Formatted files using rustfmt
|
||||||
|
- Reformatted code to make the format checks pass
|
||||||
|
- Created a derive macro for defining the display style of Enum models and removed the use of the EnumDisplayStyle trait
|
||||||
|
- Expanded the serde_enum_from macro to further reduce code duplication
|
||||||
|
|
||||||
|
## v0.5.1 (2025-03-01)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- CLI Support for multiple Servarr instances
|
||||||
|
- Support for multiple servarr definitions - no tests [skip ci]
|
||||||
|
- Support for loading Servarr API tokens from a file
|
||||||
|
- Tweaked the implementation for environment variables in the config a bit
|
||||||
|
- var interpolation
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- Updated openssl to 0.10.70 to mitigate CVE-2025-24898
|
||||||
|
- Addressed rustfmt complaints
|
||||||
|
- Corrected typo in the managarr.nuspec.template
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- Addressed Cargo fmt complaints
|
||||||
|
- Added a debug line for logging to output the config used when starting Managarr
|
||||||
|
- Updated the 2018 idiom lint to the 2021_compatibility lint
|
||||||
|
- Removed unnecessary clones in the networking module to speed up network request handling
|
||||||
|
- Corrected some clone instead of copy behaviors in the command line handlers
|
||||||
|
- Removed unnecessary clone from stateful table
|
||||||
|
- Removed unnecessary clone call from extract_and_add_tag_ids_vec method
|
||||||
|
- Reduced the number of clones necessary when building modal structs
|
||||||
|
- Refactored a handful of Option calls to use take instead
|
||||||
|
- Renamed KeyEventHandler::with to KeyEventHandler::new to keep with Rust best practices and conventions
|
||||||
|
|
||||||
## v0.4.2 (2024-12-21)
|
## v0.4.2 (2024-12-21)
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
|
|||||||
+38
-1
@@ -1,6 +1,23 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
|
Contributors are very welcome! **No contribution is too small and all contributions are valued.**
|
||||||
|
|
||||||
|
## License and Attribution
|
||||||
|
|
||||||
|
#### _If you plan on contributing to the base project, no attribution is needed!_ Feel free to proceed to the [next steps](CONTRIBUTING.md#Rust).
|
||||||
|
|
||||||
|
Otherwise, below are key points to understand from the [Managarr License, Version 1.0](LICENSE):
|
||||||
|
1. **Non-Commercial Use**:
|
||||||
|
- Managarr is licensed solely for non-commercial purposes. Any commercial use of Managarr (e.g., selling or offering as a paid service) requires separate permission.
|
||||||
|
|
||||||
|
2. **Attribution when Forking and Redistributing Without Contributing back to Main Project**:
|
||||||
|
- **If you fork the project and distribute it separately** (e.g., publish or _publicly_ host it independently from the original project), you are required to provide attribution.
|
||||||
|
- You may credit the original author by using any of the following phrasing:
|
||||||
|
- "Thanks to Alexander J. Clarke (Dark-Alex-17) for creating the original Managarr project!"
|
||||||
|
- "Forked from the Managarr project, created by Alexander J. Clarke (Dark-Alex-17)"
|
||||||
|
- "This software is based on the original Managarr project by Alexander J. Clarke (Dark-Alex-17)"
|
||||||
|
- "Inspired by Alexander J. Clarke (Dark-Alex-17)'s Managarr project"
|
||||||
|
- If changes are made to the base Managarr project, please note those modifications and provide the new attribution accordingly.
|
||||||
|
|
||||||
## Rust
|
## Rust
|
||||||
You'll need to have the stable Rust toolchain installed in order to develop Managarr.
|
You'll need to have the stable Rust toolchain installed in order to develop Managarr.
|
||||||
|
|
||||||
@@ -46,12 +63,32 @@ cz commit
|
|||||||
## Setup workspace
|
## Setup workspace
|
||||||
|
|
||||||
1. Clone this repo
|
1. Clone this repo
|
||||||
2. Run `cargo test` to setup hooks
|
2. Run `cargo test` to set up hooks
|
||||||
3. Make changes
|
3. Make changes
|
||||||
4. Run the application using `make run` or `cargo run`
|
4. Run the application using `make run` or `cargo run`
|
||||||
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.
|
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.
|
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
|
7. Create a PR
|
||||||
|
|
||||||
|
### CI/CD Testing with Act
|
||||||
|
If you also are planning on testing out your changes before pushing them with [Act](https://github.com/nektos/act), you will need to set up `act`,
|
||||||
|
`docker`, and configure your local system to run different architectures:
|
||||||
|
|
||||||
|
1. Install `docker` by following the instructions on the [official Docker installation page](https://docs.docker.com/get-docker/).
|
||||||
|
2. Install `act` by following the instructions on the [official Act installation page](https://nektosact.com/installation/index.html).
|
||||||
|
3. Install `binfmt` on your system once so that `act` can run the correct architecture for the CI/CD workflows.
|
||||||
|
You can do this by running:
|
||||||
|
```shell
|
||||||
|
sudo docker run --rm --privileged tonistiigi/binfmt --install all
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, you can run workflows locally without having to commit and see if the GitHub action passes or fails.
|
||||||
|
|
||||||
|
**For example**: To test the [release.yml](.github/workflows/release.yml) workflow locally, you can run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
act -W .github/workflows/release.yml --input_type bump=minor
|
||||||
|
```
|
||||||
|
|
||||||
## Questions? Reach out to me!
|
## Questions? Reach out to me!
|
||||||
If you encounter any questions while developing Managarr, please don't hesitate to reach out to me at alex.j.tusa@gmail.com. I'm happy to help contributors, new and experienced in any way I can!
|
If you encounter any questions while developing Managarr, please don't hesitate to reach out to me at alex.j.tusa@gmail.com. I'm happy to help contributors, new and experienced in any way I can!
|
||||||
|
|||||||
Generated
+875
-489
File diff suppressed because it is too large
Load Diff
+23
-8
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "managarr"
|
name = "managarr"
|
||||||
version = "0.4.2"
|
version = "0.6.1"
|
||||||
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
||||||
description = "A TUI and CLI to manage your Servarrs"
|
description = "A TUI and CLI to manage your Servarrs"
|
||||||
keywords = ["managarr", "ratatui", "dashboard", "servarr", "tui"]
|
keywords = ["managarr", "ratatui", "dashboard", "servarr", "tui"]
|
||||||
@@ -10,9 +10,15 @@ homepage = "https://github.com/Dark-Alex-17/managarr"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.82.0"
|
rust-version = "1.89.0"
|
||||||
exclude = [".github", "CONTRIBUTING.md", "*.log", "tags"]
|
exclude = [".github", "CONTRIBUTING.md", "*.log", "tags"]
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"proc_macros/enum_display_style_derive",
|
||||||
|
"proc_macros/validate_theme_derive",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.68"
|
anyhow = "1.0.68"
|
||||||
backtrace = "0.3.74"
|
backtrace = "0.3.74"
|
||||||
@@ -34,18 +40,23 @@ serde_json = "1.0.91"
|
|||||||
serde = { version = "1.0.214", features = ["derive"] }
|
serde = { version = "1.0.214", features = ["derive"] }
|
||||||
strum = { version = "0.26.3", features = ["derive"] }
|
strum = { version = "0.26.3", features = ["derive"] }
|
||||||
strum_macros = "0.26.4"
|
strum_macros = "0.26.4"
|
||||||
tokio = { version = "1.36.0", features = ["full"] }
|
tokio = { version = "1.44.2", features = ["full"] }
|
||||||
tokio-util = "0.7.8"
|
tokio-util = "0.7.8"
|
||||||
ratatui = { version = "0.29.0", features = [
|
ratatui = { version = "0.29.0", features = [
|
||||||
"all-widgets",
|
"all-widgets",
|
||||||
"unstable-widget-ref",
|
"unstable-widget-ref",
|
||||||
] }
|
] }
|
||||||
urlencoding = "2.1.2"
|
urlencoding = "2.1.2"
|
||||||
clap = { version = "4.5.20", features = ["derive", "cargo", "env"] }
|
clap = { version = "4.5.20", features = [
|
||||||
|
"derive",
|
||||||
|
"cargo",
|
||||||
|
"env",
|
||||||
|
"wrap_help",
|
||||||
|
] }
|
||||||
clap_complete = "4.5.33"
|
clap_complete = "4.5.33"
|
||||||
itertools = "0.13.0"
|
itertools = "0.14.0"
|
||||||
ctrlc = "3.4.5"
|
ctrlc = "3.4.5"
|
||||||
colored = "2.1.0"
|
colored = "3.0.0"
|
||||||
async-trait = "0.1.83"
|
async-trait = "0.1.83"
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
managarr-tree-widget = "0.24.0"
|
managarr-tree-widget = "0.24.0"
|
||||||
@@ -53,14 +64,18 @@ indicatif = "0.17.9"
|
|||||||
derive_setters = "0.1.6"
|
derive_setters = "0.1.6"
|
||||||
deunicode = "1.6.0"
|
deunicode = "1.6.0"
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
openssl = { version = "0.10.68", features = ["vendored"] }
|
openssl = { version = "0.10.70", features = ["vendored"] }
|
||||||
|
veil = "0.2.0"
|
||||||
|
validate_theme_derive = "0.1.0"
|
||||||
|
enum_display_style_derive = "0.1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = "2.0.16"
|
assert_cmd = "2.0.16"
|
||||||
mockall = "0.13.0"
|
mockall = "0.13.0"
|
||||||
mockito = "1.0.0"
|
mockito = "1.0.0"
|
||||||
pretty_assertions = "1.3.0"
|
pretty_assertions = "1.3.0"
|
||||||
rstest = "0.23.0"
|
rstest = "0.25.0"
|
||||||
|
serial_test = "3.2.0"
|
||||||
|
|
||||||
[dev-dependencies.cargo-husky]
|
[dev-dependencies.cargo-husky]
|
||||||
version = "1"
|
version = "1"
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM rust:1.82 AS builder
|
FROM rust:1.89 AS builder
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
# Download and compile Rust dependencies in an empty project and cache as a separate Docker layer
|
# Download and compile Rust dependencies in an empty project and cache as a separate Docker layer
|
||||||
@@ -6,6 +6,7 @@ RUN USER=root cargo new --bin managarr-temp
|
|||||||
|
|
||||||
WORKDIR /usr/src/managarr-temp
|
WORKDIR /usr/src/managarr-temp
|
||||||
COPY Cargo.* .
|
COPY Cargo.* .
|
||||||
|
COPY proc_macros ./proc_macros
|
||||||
RUN cargo build --release
|
RUN cargo build --release
|
||||||
# remove src from empty project
|
# remove src from empty project
|
||||||
RUN rm -r src
|
RUN rm -r src
|
||||||
|
|||||||
@@ -1,16 +1,53 @@
|
|||||||
MIT License
|
Managarr License
|
||||||
|
Version 1.0, 2025
|
||||||
|
|
||||||
Copyright (c) 2023 Alexander J. Clarke
|
Copyright (c) 2025 Alexander J. Clarke (Dark-Alex-17)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to use,
|
||||||
in the Software without restriction, including without limitation the rights
|
copy, modify, merge, publish, and distribute the Software solely for
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
non-commercial purposes, subject to the following conditions:
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. Attribution:
|
||||||
copies or substantial portions of the Software.
|
- The above copyright notice, this permission notice, and a prominent notice stating
|
||||||
|
that the Software is part of the "Managarr" project shall be included in all copies or
|
||||||
|
substantial portions of the Software **when the Software is forked and redistributed separately** from the original project.
|
||||||
|
- If you fork the software and **distribute it separately** without merging it back into the original base project (the Managarr repository), you must provide attribution to the original author.
|
||||||
|
You may use any of the following forms of attribution:
|
||||||
|
- "Thanks to Alexander J. Clarke (Dark-Alex-17) for creating the original Managarr project!"
|
||||||
|
- "Forked from the Managarr project, created by Alexander J. Clarke (Dark-Alex-17)"
|
||||||
|
- "This software is based on the original Managarr project by Alexander J. Clarke (Dark-Alex-17)"
|
||||||
|
- "Inspired by Alexander J. Clarke (Dark-Alex-17)'s Managarr project"
|
||||||
|
- If you modify the software, the attribution must also note that changes were made and describe those modifications, if feasible.
|
||||||
|
|
||||||
|
2. Non-Commercial Use Only:
|
||||||
|
The use of this Software for commercial purposes, including but not limited
|
||||||
|
to sale, licensing, or use in any product or service for monetary
|
||||||
|
compensation, is strictly prohibited without prior written permission from
|
||||||
|
Alexander J. Clarke (Dark-Alex-17).
|
||||||
|
|
||||||
|
For avoidance of doubt:
|
||||||
|
- **Allowed:** Private use, educational purposes, research, or any usage
|
||||||
|
that does not directly generate revenue.
|
||||||
|
- **Prohibited:** Selling, sublicensing, or incorporating the Software into
|
||||||
|
commercial products or services.
|
||||||
|
|
||||||
|
3. Modifications and Derivatives:
|
||||||
|
- Any modifications or derivative works based on this Software must clearly
|
||||||
|
document all changes made and prominently credit the original "Managarr"
|
||||||
|
project as described in section 1.
|
||||||
|
- Derivative works must retain this license, the original copyright notice,
|
||||||
|
and all terms and conditions described herein. This applies to the entire
|
||||||
|
derivative work, even if combined with other software.
|
||||||
|
|
||||||
|
4. Warranty Disclaimer:
|
||||||
|
This Software is provided "as is," without warranty of any kind, express
|
||||||
|
or implied, including but not limited to the warranties of merchantability,
|
||||||
|
fitness for a particular purpose, and noninfringement. In no event shall the
|
||||||
|
authors or copyright holders be liable for any claim, damages, or other
|
||||||
|
liability, whether in an action of contract, tort, or otherwise, arising
|
||||||
|
from, out of, or in connection with the Software or the use or other
|
||||||
|
dealings in the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ default: run
|
|||||||
.PHONY: test test-cov build run lint lint-fix fmt analyze sonar release delete-tag
|
.PHONY: test test-cov build run lint lint-fix fmt analyze sonar release delete-tag
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@cargo test
|
@cargo test --all
|
||||||
|
|
||||||
## Run all tests with coverage - `cargo install cargo-tarpaulin`
|
## Run all tests with coverage - `cargo install cargo-tarpaulin`
|
||||||
test-cov:
|
test-cov:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# managarr - A TUI and CLI to manage your Servarrs
|
# managarr - A TUI and CLI to manage your Servarrs
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
[](https://crates.io/crates/managarr)
|
[](https://crates.io/crates/managarr)
|
||||||
@@ -10,6 +10,8 @@
|
|||||||

|

|
||||||
[](https://github.com/Dark-Alex-17/managarr/releases)
|
[](https://github.com/Dark-Alex-17/managarr/releases)
|
||||||

|

|
||||||
|
[](https://matrix.to/#/#managarr:matrix.org)
|
||||||
|
|
||||||
|
|
||||||
Managarr is a TUI and CLI to help you manage your HTPC (Home Theater PC). Built with 🤎 in Rust!
|
Managarr is a TUI and CLI to help you manage your HTPC (Home Theater PC). Built with 🤎 in Rust!
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ Managarr is a TUI and CLI to help you manage your HTPC (Home Theater PC). Built
|
|||||||
- [ ]  [Bazarr](https://www.bazarr.media/)
|
- [ ]  [Bazarr](https://www.bazarr.media/)
|
||||||
- [ ]  [Tautulli](https://tautulli.com/)
|
- [ ]  [Tautulli](https://tautulli.com/)
|
||||||
|
|
||||||
## Try Before You Buy
|
## Try Out the Demo
|
||||||
To try out Managarr before linking it to your HTPC, you can use the purpose built [managarr-demo](https://github.com/Dark-Alex-17/managarr-demo) repository.
|
To try out Managarr before linking it to your HTPC, you can use the purpose built [managarr-demo](https://github.com/Dark-Alex-17/managarr-demo) repository.
|
||||||
Simply run the following command to start a demo:
|
Simply run the following command to start a demo:
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ Please note that you will need to create and popular your configuration file fir
|
|||||||
**Note:** If you run into errors using relative file paths when mounting the volume with the configuration file, try using an absolute path.
|
**Note:** If you run into errors using relative file paths when mounting the volume with the configuration file, try using an absolute path.
|
||||||
|
|
||||||
### Homebrew (Mac and Linux)
|
### Homebrew (Mac and Linux)
|
||||||
To install Managarr from Homebrew, install the Managarr tap and then you'll be able to install Managarr:
|
To install Managarr from Homebrew, install the Managarr tap. Then you'll be able to install Managarr:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
brew tap Dark-Alex-17/managarr
|
brew tap Dark-Alex-17/managarr
|
||||||
@@ -76,6 +78,16 @@ To upgrade to a newer version of Managarr:
|
|||||||
brew upgrade managarr
|
brew upgrade managarr
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Nix (Externally Maintained)
|
||||||
|
To install Managarr on NixOS, you can use the following command:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
nix-env --install managarr
|
||||||
|
|
||||||
|
# Alternatively, for non-NixOS users, you can spawn a temporary shell with Managarr available like so:
|
||||||
|
nix-shell -p managarr
|
||||||
|
```
|
||||||
|
|
||||||
### Chocolatey (Windows)
|
### Chocolatey (Windows)
|
||||||
The Managarr Chocolatey package is located [here](https://community.chocolatey.org/packages/managarr). Please note that validation
|
The Managarr Chocolatey package is located [here](https://community.chocolatey.org/packages/managarr). Please note that validation
|
||||||
of Chocolatey packages take quite some time, and thus the package may not be available immediately after a new release.
|
of Chocolatey packages take quite some time, and thus the package may not be available immediately after a new release.
|
||||||
@@ -84,7 +96,7 @@ of Chocolatey packages take quite some time, and thus the package may not be ava
|
|||||||
choco install managarr
|
choco install managarr
|
||||||
|
|
||||||
# Some newer releases may require a version number, so you can specify it like so:
|
# Some newer releases may require a version number, so you can specify it like so:
|
||||||
choco install managarr --version=0.4.1
|
choco install managarr --version=0.5.0
|
||||||
```
|
```
|
||||||
|
|
||||||
To upgrade to the latest and greatest version of Managarr:
|
To upgrade to the latest and greatest version of Managarr:
|
||||||
@@ -92,7 +104,7 @@ To upgrade to the latest and greatest version of Managarr:
|
|||||||
choco upgrade managarr
|
choco upgrade managarr
|
||||||
|
|
||||||
# To upgrade to a specific version:
|
# To upgrade to a specific version:
|
||||||
choco upgrade managarr --version=0.4.2
|
choco upgrade managarr --version=0.5.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Manual
|
### Manual
|
||||||
@@ -107,16 +119,16 @@ Binaries are available on the [releases](https://github.com/Dark-Alex-17/managar
|
|||||||
#### Windows Instructions
|
#### Windows Instructions
|
||||||
To use a binary from the releases page on Windows, do the following:
|
To use a binary from the releases page on Windows, do the following:
|
||||||
|
|
||||||
1. Download the latest binary [binary](https://github.com/Dark-Alex-17/managarr/releases) for your OS.
|
1. Download the latest [binary](https://github.com/Dark-Alex-17/managarr/releases) for your OS.
|
||||||
2. Use 7-Zip or TarTool to unpack the Tar file.
|
2. Use 7-Zip or TarTool to unpack the Tar file.
|
||||||
3. Run the executable `managarr.exe`!
|
3. Run the executable `managarr.exe`!
|
||||||
|
|
||||||
#### Linux/MacOS Instructions
|
#### Linux/MacOS Instructions
|
||||||
To use a binary from the releases page on Linux/MacOS, do the following:
|
To use a binary from the releases page on Linux/MacOS, do the following:
|
||||||
|
|
||||||
1. Download the latest binary [binary](https://github.com/Dark-Alex-17/managarr/releases) for your OS.
|
1. Download the latest [binary](https://github.com/Dark-Alex-17/managarr/releases) for your OS.
|
||||||
2. `cd` to the directory where you downloaded the binary.
|
2. `cd` to the directory where you downloaded the binary.
|
||||||
3. Extract the binary with `tar -C /usr/local/bin -xzf managarr-<arch>.tar.gz` (NB: This may require `sudo`)
|
3. Extract the binary with `tar -C /usr/local/bin -xzf managarr-<arch>.tar.gz` (Note: This may require `sudo`)
|
||||||
4. Now you can run `managarr`!
|
4. Now you can run `managarr`!
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@@ -154,21 +166,21 @@ Key:
|
|||||||
|
|
||||||
| TUI | CLI | Feature |
|
| TUI | CLI | Feature |
|
||||||
|-----|-----|--------------------------------------------------------------------------------------------------------------------|
|
|-----|-----|--------------------------------------------------------------------------------------------------------------------|
|
||||||
| ✅ | ✅ | View your library, downloads, blocklist, episodes |
|
| ✅ | ✅ | View your library, downloads, blocklist, episodes |
|
||||||
| ✅ | ✅ | View details of a specific series, or episode including description, history, downloaded file info, or the credits |
|
| ✅ | ✅ | View details of a specific series, or episode including description, history, downloaded file info, or the credits |
|
||||||
| 🚫 | ✅ | View your host and security configs from the CLI to programmatically fetch the API token, among other settings |
|
| 🚫 | ✅ | View your host and security configs from the CLI to programmatically fetch the API token, among other settings |
|
||||||
| ✅ | ✅ | Search your library |
|
| ✅ | ✅ | Search your library |
|
||||||
| ✅ | ✅ | Add series to your library |
|
| ✅ | ✅ | Add series to your library |
|
||||||
| ✅ | ✅ | Delete series, downloads, indexers, root folders, and episode files |
|
| ✅ | ✅ | Delete series, downloads, indexers, root folders, and episode files |
|
||||||
| ✅ | ✅ | Trigger automatic searches for series, seasons, or episodes |
|
| ✅ | ✅ | Trigger automatic searches for series, seasons, or episodes |
|
||||||
| ✅ | ✅ | Trigger refresh and disk scan for series and downloads |
|
| ✅ | ✅ | Trigger refresh and disk scan for series and downloads |
|
||||||
| ✅ | ✅ | Manually search for series, seasons, or episodes |
|
| ✅ | ✅ | Manually search for series, seasons, or episodes |
|
||||||
| ✅ | ✅ | Edit your series and indexers |
|
| ✅ | ✅ | Edit your series and indexers |
|
||||||
| ✅ | ✅ | Manage your tags |
|
| ✅ | ✅ | Manage your tags |
|
||||||
| ✅ | ✅ | Manage your root folders |
|
| ✅ | ✅ | Manage your root folders |
|
||||||
| ✅ | ✅ | Manage your blocklist |
|
| ✅ | ✅ | Manage your blocklist |
|
||||||
| ✅ | ✅ | View and browse logs, tasks, events queues, and updates |
|
| ✅ | ✅ | View and browse logs, tasks, events queues, and updates |
|
||||||
| ✅ | ✅ | Manually trigger scheduled tasks |
|
| ✅ | ✅ | Manually trigger scheduled tasks |
|
||||||
|
|
||||||
### Readarr
|
### Readarr
|
||||||
|
|
||||||
@@ -194,6 +206,19 @@ Key:
|
|||||||
|
|
||||||
- [ ] Support for Tautulli
|
- [ ] Support for Tautulli
|
||||||
|
|
||||||
|
### Themes
|
||||||
|
Managarr ships with a few themes out of the box. Here's a few examples:
|
||||||
|
|
||||||
|
#### Default
|
||||||
|

|
||||||
|
#### Dracula
|
||||||
|

|
||||||
|
#### Watermelon Dark
|
||||||
|

|
||||||
|
|
||||||
|
You can also create your own custom themes as well. To learn more about what themes are built-in to Managarr and how
|
||||||
|
to create your own custom themes, check out the [Themes README](themes/README.md).
|
||||||
|
|
||||||
### The Managarr CLI
|
### The Managarr CLI
|
||||||
Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs.
|
Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs.
|
||||||
|
|
||||||
@@ -206,7 +231,7 @@ To see all available commands, simply run `managarr --help`:
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ managarr --help
|
$ managarr --help
|
||||||
managarr 0.4.0
|
managarr 0.5.1
|
||||||
Alex Clarke <alex.j.tusa@gmail.com>
|
Alex Clarke <alex.j.tusa@gmail.com>
|
||||||
|
|
||||||
A TUI and CLI to manage your Servarrs
|
A TUI and CLI to manage your Servarrs
|
||||||
@@ -221,10 +246,15 @@ Commands:
|
|||||||
help Print this message or the help of the given subcommand(s)
|
help Print this message or the help of the given subcommand(s)
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--disable-spinner Disable the spinner (can sometimes make parsing output challenging) [env: MANAGARR_DISABLE_SPINNER=]
|
--disable-spinner Disable the spinner (can sometimes make parsing output challenging) [env: MANAGARR_DISABLE_SPINNER=]
|
||||||
--config <CONFIG> The Managarr configuration file to use [env: MANAGARR_CONFIG_FILE=]
|
--config-file <CONFIG_FILE> The Managarr configuration file to use [env: MANAGARR_CONFIG_FILE=]
|
||||||
-h, --help Print help
|
--themes-file <THEMES_FILE> The Managarr themes file to use [env: MANAGARR_THEMES_FILE=]
|
||||||
-V, --version Print version
|
--theme <THEME> The name of the Managarr theme to use [env: MANAGARR_THEME=]
|
||||||
|
--servarr-name <SERVARR_NAME> For multi-instance configurations, you need to specify the name of the instance configuration that you want to use.
|
||||||
|
This is useful when you have multiple instances of the same Servarr defined in your config file.
|
||||||
|
By default, if left empty, the first configured Servarr instance listed in the config file will be used.
|
||||||
|
-h, --help Print help
|
||||||
|
-V, --version Print version
|
||||||
```
|
```
|
||||||
|
|
||||||
All subcommands also have detailed help menus to show you how to use them. For example, to see all available commands for Sonarr, you would run:
|
All subcommands also have detailed help menus to show you how to use them. For example, to see all available commands for Sonarr, you would run:
|
||||||
@@ -295,44 +325,99 @@ where you may have more than one instance of a given Servarr running. Thus, you
|
|||||||
config file using the `--config` flag:
|
config file using the `--config` flag:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
managarr --config /path/to/config.yml
|
managarr --config-file /path/to/config.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example Configuration:
|
### Example Configuration:
|
||||||
```yaml
|
```yaml
|
||||||
|
theme: default
|
||||||
radarr:
|
radarr:
|
||||||
host: 192.168.0.78
|
- host: 192.168.0.78
|
||||||
port: 7878
|
port: 7878
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
ssl_cert_path: /path/to/radarr.crt # Required to enable SSL
|
ssl_cert_path: /path/to/radarr.crt # Required to enable SSL
|
||||||
sonarr:
|
sonarr:
|
||||||
uri: http://htpc.local/sonarr # Example of using the 'uri' key instead of 'host' and 'port'
|
- uri: http://htpc.local/sonarr # Example of using the 'uri' key instead of 'host' and 'port'
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
|
|
||||||
|
- name: Anime Sonarr # An example of a custom name for a secondary Sonarr instance
|
||||||
|
host: 192.168.0.89
|
||||||
|
port: 8989
|
||||||
|
api_token: someApiToken1234567890
|
||||||
readarr:
|
readarr:
|
||||||
host: 192.168.0.87
|
- host: 192.168.0.87
|
||||||
port: 8787
|
port: 8787
|
||||||
api_token: someApiToken1234567890
|
api_token_file: /root/.config/readarr_api_token # Example of loading the API token from a file instead of hardcoding it in the configuration file
|
||||||
lidarr:
|
lidarr:
|
||||||
host: 192.168.0.86
|
- host: 192.168.0.86
|
||||||
port: 8686
|
port: 8686
|
||||||
api_token: someApiToken1234567890
|
api_token: ${MY_LIDARR_API_TOKEN} # Example of configuring using environment variables
|
||||||
whisparr:
|
whisparr:
|
||||||
host: 192.168.0.69
|
- host: 192.168.0.69
|
||||||
port: 6969
|
port: 6969
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
ssl_cert_path: /path/to/whisparr.crt
|
ssl_cert_path: /path/to/whisparr.crt
|
||||||
|
custom_headers: # Example of adding custom headers to all requests to the Servarr instance
|
||||||
|
traefik-auth-bypass-key: someBypassKey1234567890
|
||||||
|
SOME-OTHER-CUSTOM-HEADER: ${MY_CUSTOM_HEADER_VALUE}
|
||||||
bazarr:
|
bazarr:
|
||||||
host: 192.168.0.67
|
- host: 192.168.0.67
|
||||||
port: 6767
|
port: 6767
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
prowlarr:
|
prowlarr:
|
||||||
host: 192.168.0.96
|
- host: 192.168.0.96
|
||||||
port: 9696
|
port: 9696
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
tautulli:
|
tautulli:
|
||||||
host: 192.168.0.81
|
- host: 192.168.0.81
|
||||||
port: 8181
|
port: 8181
|
||||||
api_token: someApiToken1234567890
|
api_token: someApiToken1234567890
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Multi-Instance Configuration:
|
||||||
|
```yaml
|
||||||
|
theme: default
|
||||||
|
radarr:
|
||||||
|
- host: 192.168.0.78 # No name specified, so this instance's name will default to 'Radarr 1'
|
||||||
|
port: 7878
|
||||||
|
api_token: someApiToken1234567890
|
||||||
|
ssl_cert_path: /path/to/radarr.crt
|
||||||
|
|
||||||
|
- name: International Movies
|
||||||
|
host: 192.168.0.79
|
||||||
|
port: 7878
|
||||||
|
api_token: someApiToken1234567890
|
||||||
|
sonarr:
|
||||||
|
- name: Anime
|
||||||
|
weight: 1 # This instance will be the first tab in the TUI
|
||||||
|
uri: http://htpc.local/sonarr
|
||||||
|
api_token: someApiToken1234567890
|
||||||
|
|
||||||
|
- name: TV Shows
|
||||||
|
weight: 2 # This instance will be the second tab in the TUI
|
||||||
|
host: 192.168.0.89
|
||||||
|
port: 8989
|
||||||
|
api_token: someApiToken1234567890
|
||||||
|
```
|
||||||
|
|
||||||
|
In this configuration, you can see that we have multiple instances of Radarr and Sonarr configured. The `weight` key is
|
||||||
|
used to specify the order in which the tabs will appear in the TUI. The lower the weight, the further to the left the
|
||||||
|
tab will appear. If no weight is specified, then tabs will be ordered in the order they appear in the configuration
|
||||||
|
file.
|
||||||
|
|
||||||
|
When no `name` is specified for a Servarr instance, the name will default to the name of the Servarr with a number
|
||||||
|
appended to it. For example, if you have two Radarr instances and neither has a name, they will be named `Radarr 1` and
|
||||||
|
`Radarr 2`, respectively.
|
||||||
|
|
||||||
|
In this example configuration, the tabs in the TUI would appear as follows:
|
||||||
|
|
||||||
|
`Anime | TV Shows | Radarr 1 | International Movies`
|
||||||
|
|
||||||
|
### Specify Which Servarr Instance to Use in the CLI
|
||||||
|
If you have multiple instances of the same Servarr running, you can specify which instance you want to use by using the `--servarr-name` flag:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
managarr --servarr-name "International Movies"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
coverage:
|
coverage:
|
||||||
range: "80..100"
|
range: "80..100"
|
||||||
|
status:
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
threshold: 0
|
||||||
|
target: 80%
|
||||||
|
patch:
|
||||||
|
default:
|
||||||
|
threshold: 0
|
||||||
|
target: 80%
|
||||||
|
|
||||||
ignore:
|
ignore:
|
||||||
- "**/*_tests.rs"
|
- "**/*_tests.rs"
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ This is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Refe
|
|||||||
<tags>cli cross-platform terminal servarr tui sonarr radarr rust</tags>
|
<tags>cli cross-platform terminal servarr tui sonarr radarr rust</tags>
|
||||||
<summary>A TUI and CLI for managing *arr servers.</summary>
|
<summary>A TUI and CLI for managing *arr servers.</summary>
|
||||||
<description>
|
<description>
|
||||||
A TUI and CLI for managing *arr servers. Build with love in Rust!
|
A TUI and CLI for managing *arr servers. Built with love in Rust!
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
To use, run `managarr` in a terminal.
|
To use, run `managarr` in a terminal.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Documentation: https://docs.brew.sh/Formula-Cookbook
|
# Documentation: https://docs.brew.sh/Formula-Cookbook
|
||||||
# https://rubydoc.brew.sh/Formula
|
# https://rubydoc.brew.sh/Formula
|
||||||
class Managarr < Formula
|
class Managarr < Formula
|
||||||
desc "A fast and simple dashboard for Kubernetes written in Rust"
|
desc "Managarr is a TUI and CLI to help you manage your HTPC (Home Theater PC)"
|
||||||
homepage "https://github.com/Dark-Alex-17/managarr"
|
homepage "https://github.com/Dark-Alex-17/managarr"
|
||||||
if OS.mac? and Hardware::CPU.arm?
|
if OS.mac? and Hardware::CPU.arm?
|
||||||
url "https://github.com/Dark-Alex-17/managarr/releases/download/v$version/managarr-macos-arm64.tar.gz"
|
url "https://github.com/Dark-Alex-17/managarr/releases/download/v$version/managarr-macos-arm64.tar.gz"
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "enum_display_style_derive"
|
||||||
|
version = "0.6.1"
|
||||||
|
edition = "2024"
|
||||||
|
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
||||||
|
description = "A proc-macro to derive a `Display` and `FromStr` implementation for enums with a `style` attribute."
|
||||||
|
license = "MIT"
|
||||||
|
documentation = "https://github.com/Dark-Alex-17/managarr"
|
||||||
|
repository = "https://github.com/Dark-Alex-17/managarr"
|
||||||
|
homepage = "https://github.com/Dark-Alex-17/managarr"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.39"
|
||||||
|
syn = "2.0.99"
|
||||||
|
darling = "0.20.10"
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
mod macro_models;
|
||||||
|
|
||||||
|
use crate::macro_models::DisplayStyleArgs;
|
||||||
|
use darling::FromVariant;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{Data, DeriveInput, parse_macro_input};
|
||||||
|
|
||||||
|
/// Derive macro for generating a `to_display_str` method for an enum.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Using default values for the display style:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use enum_display_style_derive::EnumDisplayStyle;
|
||||||
|
///
|
||||||
|
/// #[derive(EnumDisplayStyle)]
|
||||||
|
/// enum Weekend {
|
||||||
|
/// Saturday,
|
||||||
|
/// Sunday,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(Weekend::Saturday.to_display_str(), "Saturday");
|
||||||
|
/// assert_eq!(Weekend::Sunday.to_display_str(), "Sunday");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Using custom values for the display style:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use enum_display_style_derive::EnumDisplayStyle;
|
||||||
|
///
|
||||||
|
/// #[derive(EnumDisplayStyle)]
|
||||||
|
/// enum MonitorStatus {
|
||||||
|
/// #[display_style(name = "Monitor Transactions")]
|
||||||
|
/// Active,
|
||||||
|
/// #[display_style(name = "Don't Monitor Transactions")]
|
||||||
|
/// None,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(MonitorStatus::Active.to_display_str(), "Monitor Transactions");
|
||||||
|
/// assert_eq!(MonitorStatus::None.to_display_str(), "Don't Monitor Transactions");
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(EnumDisplayStyle, attributes(display_style))]
|
||||||
|
pub fn enum_display_style_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
let enum_name = &input.ident;
|
||||||
|
|
||||||
|
let mut match_arms = Vec::new();
|
||||||
|
|
||||||
|
if let Data::Enum(data_enum) = &input.data {
|
||||||
|
let variants = &data_enum.variants;
|
||||||
|
|
||||||
|
for variant in variants {
|
||||||
|
let variant_ident = &variant.ident;
|
||||||
|
let variant_display_name = DisplayStyleArgs::from_variant(variant)
|
||||||
|
.unwrap()
|
||||||
|
.name
|
||||||
|
.unwrap_or_else(|| variant_ident.to_string());
|
||||||
|
|
||||||
|
match_arms.push(quote! {
|
||||||
|
#enum_name::#variant_ident => #variant_display_name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl<'a> #enum_name {
|
||||||
|
pub fn to_display_str(self) -> &'a str {
|
||||||
|
match self {
|
||||||
|
#(#match_arms)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
use darling::FromVariant;
|
||||||
|
|
||||||
|
#[derive(Debug, FromVariant)]
|
||||||
|
#[darling(attributes(display_style))]
|
||||||
|
pub struct DisplayStyleArgs {
|
||||||
|
pub name: Option<String>,
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "validate_theme_derive"
|
||||||
|
version = "0.6.1"
|
||||||
|
edition = "2024"
|
||||||
|
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
||||||
|
description = "A proc-macro to validate a theme."
|
||||||
|
license = "MIT"
|
||||||
|
documentation = "https://github.com/Dark-Alex-17/managarr"
|
||||||
|
repository = "https://github.com/Dark-Alex-17/managarr"
|
||||||
|
homepage = "https://github.com/Dark-Alex-17/managarr"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.39"
|
||||||
|
syn = "2.0.99"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
log = "0.4.17"
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{Data, DeriveInput, Fields, parse_macro_input};
|
||||||
|
|
||||||
|
/// Derive macro for generating a `validate` method for a Theme struct.
|
||||||
|
/// The `validate` method ensures that all values with the `validate` attribute are not `None`.
|
||||||
|
/// Otherwise, an error message it output to both the log file and stdout and the program exits.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Valid themes pass through the program transitively without any messages being output.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use validate_theme_derive::ValidateTheme;
|
||||||
|
///
|
||||||
|
/// #[derive(ValidateTheme, Default)]
|
||||||
|
/// struct Theme {
|
||||||
|
/// pub name: String,
|
||||||
|
/// #[validate]
|
||||||
|
/// pub good: Option<Style>,
|
||||||
|
/// #[validate]
|
||||||
|
/// pub bad: Option<Style>,
|
||||||
|
/// pub ugly: Option<Style>,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// struct Style {
|
||||||
|
/// color: String,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let theme = Theme {
|
||||||
|
/// good: Some(Style { color: "Green".to_owned() }),
|
||||||
|
/// bad: Some(Style { color: "Red".to_owned() }),
|
||||||
|
/// ..Theme::default()
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // Since only `good` and `bad` have the `validate` attribute, the `validate` method will only check those fields.
|
||||||
|
/// theme.validate();
|
||||||
|
/// // Since both `good` and `bad` have values, the program will not exit and no message is output.
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Invalid themes will output an error message to both the log file and stdout and the program will exit.
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// use validate_theme_derive::ValidateTheme;
|
||||||
|
///
|
||||||
|
/// #[derive(ValidateTheme, Default)]
|
||||||
|
/// struct Theme {
|
||||||
|
/// pub name: String,
|
||||||
|
/// #[validate]
|
||||||
|
/// pub good: Option<Style>,
|
||||||
|
/// #[validate]
|
||||||
|
/// pub bad: Option<Style>,
|
||||||
|
/// pub ugly: Option<Style>,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// struct Style {
|
||||||
|
/// color: String,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let theme = Theme {
|
||||||
|
/// bad: Some(Style { color: "Red".to_owned() }),
|
||||||
|
/// ..Theme::default()
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // Since `good` has the `validate` attribute and since `good` is `None`, the `validate` method will output an error message and exit the program.
|
||||||
|
/// theme.validate();
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(ValidateTheme, attributes(validate))]
|
||||||
|
pub fn derive_validate_theme(input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
let struct_name = &input.ident;
|
||||||
|
|
||||||
|
let mut validation_checks = Vec::new();
|
||||||
|
|
||||||
|
if let Data::Struct(data_struct) = &input.data
|
||||||
|
&& let Fields::Named(fields) = &data_struct.fields
|
||||||
|
{
|
||||||
|
for field in &fields.named {
|
||||||
|
let field_name = &field.ident;
|
||||||
|
|
||||||
|
let has_validate_attr = field
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.any(|attr| attr.path().is_ident("validate"));
|
||||||
|
|
||||||
|
if has_validate_attr {
|
||||||
|
validation_checks.push(quote! {
|
||||||
|
if self.#field_name.is_none() {
|
||||||
|
log::error!("{} is missing a color value.", stringify!(#field_name));
|
||||||
|
eprintln!("{} is missing a color value.", stringify!(#field_name));
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl #struct_name {
|
||||||
|
pub fn validate(&self) {
|
||||||
|
#(#validation_checks)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 340 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 241 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 220 KiB |
+337
-72
@@ -1,13 +1,13 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::models::Route;
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
use rstest::rstest;
|
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||||
|
use serde_json::Value;
|
||||||
|
use serial_test::serial;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES};
|
use crate::app::{interpolate_env_vars, App, AppConfig, Data, ServarrConfig};
|
||||||
use crate::app::{App, AppConfig, Data, ServarrConfig};
|
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData};
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData};
|
||||||
use crate::models::{HorizontallyScrollableText, TabRoute};
|
use crate::models::{HorizontallyScrollableText, TabRoute};
|
||||||
@@ -15,37 +15,53 @@ mod tests {
|
|||||||
use crate::network::NetworkEvent;
|
use crate::network::NetworkEvent;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
#[rstest]
|
#[test]
|
||||||
fn test_app_new(
|
fn test_app_new() {
|
||||||
#[values(ActiveRadarrBlock::default(), ActiveSonarrBlock::default())] servarr: impl Into<Route>
|
let radarr_config_1 = ServarrConfig {
|
||||||
+ Copy,
|
name: Some("Radarr Test".to_owned()),
|
||||||
) {
|
..ServarrConfig::default()
|
||||||
let (title, config) = match servarr.into() {
|
|
||||||
Route::Radarr(_, _) => (
|
|
||||||
"Radarr",
|
|
||||||
AppConfig {
|
|
||||||
radarr: Some(ServarrConfig::default()),
|
|
||||||
..AppConfig::default()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Route::Sonarr(_, _) => (
|
|
||||||
"Sonarr",
|
|
||||||
AppConfig {
|
|
||||||
sonarr: Some(ServarrConfig::default()),
|
|
||||||
..AppConfig::default()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
};
|
||||||
let tab_route = |title: &'static str| TabRoute {
|
let radarr_config_2 = ServarrConfig {
|
||||||
title,
|
weight: Some(3),
|
||||||
route: servarr.into(),
|
..ServarrConfig::default()
|
||||||
help: format!(
|
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
|
||||||
),
|
|
||||||
contextual_help: None,
|
|
||||||
};
|
};
|
||||||
|
let sonarr_config_1 = ServarrConfig {
|
||||||
|
name: Some("Sonarr Test".to_owned()),
|
||||||
|
weight: Some(1),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
};
|
||||||
|
let sonarr_config_2 = ServarrConfig::default();
|
||||||
|
let config = AppConfig {
|
||||||
|
theme: None,
|
||||||
|
radarr: Some(vec![radarr_config_1.clone(), radarr_config_2.clone()]),
|
||||||
|
sonarr: Some(vec![sonarr_config_1.clone(), sonarr_config_2.clone()]),
|
||||||
|
};
|
||||||
|
let expected_tab_routes = vec![
|
||||||
|
TabRoute {
|
||||||
|
title: "Sonarr Test".to_owned(),
|
||||||
|
route: ActiveSonarrBlock::default().into(),
|
||||||
|
contextual_help: None,
|
||||||
|
config: Some(sonarr_config_1),
|
||||||
|
},
|
||||||
|
TabRoute {
|
||||||
|
title: "Radarr 1".to_owned(),
|
||||||
|
route: ActiveRadarrBlock::default().into(),
|
||||||
|
contextual_help: None,
|
||||||
|
config: Some(radarr_config_2),
|
||||||
|
},
|
||||||
|
TabRoute {
|
||||||
|
title: "Radarr Test".to_owned(),
|
||||||
|
route: ActiveRadarrBlock::default().into(),
|
||||||
|
contextual_help: None,
|
||||||
|
config: Some(radarr_config_1),
|
||||||
|
},
|
||||||
|
TabRoute {
|
||||||
|
title: "Sonarr 1".to_owned(),
|
||||||
|
route: ActiveSonarrBlock::default().into(),
|
||||||
|
contextual_help: None,
|
||||||
|
config: Some(sonarr_config_2),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
let app = App::new(
|
let app = App::new(
|
||||||
mpsc::channel::<NetworkEvent>(500).0,
|
mpsc::channel::<NetworkEvent>(500).0,
|
||||||
@@ -54,20 +70,20 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert!(app.navigation_stack.is_empty());
|
assert!(app.navigation_stack.is_empty());
|
||||||
assert_eq!(app.get_current_route(), servarr.into());
|
assert_eq!(app.get_current_route(), ActiveSonarrBlock::default().into());
|
||||||
assert!(app.network_tx.is_some());
|
assert!(app.network_tx.is_some());
|
||||||
assert!(!app.cancellation_token.is_cancelled());
|
assert!(!app.cancellation_token.is_cancelled());
|
||||||
assert!(app.is_first_render);
|
assert!(app.is_first_render);
|
||||||
assert_eq!(app.error, HorizontallyScrollableText::default());
|
assert_eq!(app.error, HorizontallyScrollableText::default());
|
||||||
assert_eq!(app.server_tabs.index, 0);
|
assert_eq!(app.server_tabs.index, 0);
|
||||||
assert_eq!(app.server_tabs.tabs, vec![tab_route(title)]);
|
assert_eq!(app.server_tabs.tabs, expected_tab_routes);
|
||||||
assert_eq!(app.tick_until_poll, 400);
|
assert_eq!(app.tick_until_poll, 400);
|
||||||
assert_eq!(app.ticks_until_scroll, 4);
|
assert_eq!(app.ticks_until_scroll, 4);
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
assert!(!app.is_loading);
|
assert!(!app.is_loading);
|
||||||
assert!(!app.is_routing);
|
assert!(!app.is_routing);
|
||||||
assert!(!app.should_refresh);
|
assert!(!app.should_refresh);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app.cli_mode);
|
assert!(!app.cli_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,42 +97,19 @@ mod tests {
|
|||||||
assert!(app.is_first_render);
|
assert!(app.is_first_render);
|
||||||
assert_eq!(app.error, HorizontallyScrollableText::default());
|
assert_eq!(app.error, HorizontallyScrollableText::default());
|
||||||
assert_eq!(app.server_tabs.index, 0);
|
assert_eq!(app.server_tabs.index, 0);
|
||||||
assert_eq!(
|
|
||||||
app.server_tabs.tabs,
|
|
||||||
vec![
|
|
||||||
TabRoute {
|
|
||||||
title: "Radarr",
|
|
||||||
route: ActiveRadarrBlock::Movies.into(),
|
|
||||||
help: format!(
|
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
|
||||||
),
|
|
||||||
contextual_help: None,
|
|
||||||
},
|
|
||||||
TabRoute {
|
|
||||||
title: "Sonarr",
|
|
||||||
route: ActiveSonarrBlock::Series.into(),
|
|
||||||
help: format!(
|
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
|
||||||
),
|
|
||||||
contextual_help: None,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
assert_eq!(app.tick_until_poll, 400);
|
assert_eq!(app.tick_until_poll, 400);
|
||||||
assert_eq!(app.ticks_until_scroll, 4);
|
assert_eq!(app.ticks_until_scroll, 4);
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
assert!(!app.is_loading);
|
assert!(!app.is_loading);
|
||||||
assert!(!app.is_routing);
|
assert!(!app.is_routing);
|
||||||
assert!(!app.should_refresh);
|
assert!(!app.should_refresh);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app.cli_mode);
|
assert!(!app.cli_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_navigation_stack_methods() {
|
fn test_navigation_stack_methods() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let default_route = app.server_tabs.tabs.first().unwrap().route;
|
let default_route = app.server_tabs.tabs.first().unwrap().route;
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), default_route);
|
assert_eq!(app.get_current_route(), default_route);
|
||||||
@@ -153,7 +146,7 @@ mod tests {
|
|||||||
let mut app = App {
|
let mut app = App {
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
should_refresh: false,
|
should_refresh: false,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
app.cancellation_token.cancel();
|
app.cancellation_token.cancel();
|
||||||
|
|
||||||
@@ -171,7 +164,7 @@ mod tests {
|
|||||||
fn test_reset_tick_count() {
|
fn test_reset_tick_count() {
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
tick_count: 2,
|
tick_count: 2,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app.reset_tick_count();
|
app.reset_tick_count();
|
||||||
@@ -198,7 +191,7 @@ mod tests {
|
|||||||
error: "Test error".to_owned().into(),
|
error: "Test error".to_owned().into(),
|
||||||
is_first_render: false,
|
is_first_render: false,
|
||||||
data,
|
data,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app.reset();
|
app.reset();
|
||||||
@@ -212,7 +205,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_handle_error() {
|
fn test_handle_error() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let test_string = "Testing";
|
let test_string = "Testing";
|
||||||
|
|
||||||
app.handle_error(anyhow!(test_string));
|
app.handle_error(anyhow!(test_string));
|
||||||
@@ -231,7 +224,7 @@ mod tests {
|
|||||||
let mut app = App {
|
let mut app = App {
|
||||||
tick_until_poll: 2,
|
tick_until_poll: 2,
|
||||||
network_tx: Some(sync_network_tx),
|
network_tx: Some(sync_network_tx),
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
@@ -255,7 +248,7 @@ mod tests {
|
|||||||
tick_until_poll: 2,
|
tick_until_poll: 2,
|
||||||
network_tx: Some(sync_network_tx),
|
network_tx: Some(sync_network_tx),
|
||||||
is_first_render: true,
|
is_first_render: true,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
@@ -276,7 +269,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
@@ -309,7 +302,7 @@ mod tests {
|
|||||||
tick_until_poll: 2,
|
tick_until_poll: 2,
|
||||||
tick_count: 2,
|
tick_count: 2,
|
||||||
is_routing: true,
|
is_routing: true,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app.on_tick().await;
|
app.on_tick().await;
|
||||||
@@ -322,7 +315,7 @@ mod tests {
|
|||||||
tick_until_poll: 2,
|
tick_until_poll: 2,
|
||||||
tick_count: 2,
|
tick_count: 2,
|
||||||
should_refresh: true,
|
should_refresh: true,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app.on_tick().await;
|
app.on_tick().await;
|
||||||
@@ -341,10 +334,282 @@ mod tests {
|
|||||||
fn test_servarr_config_default() {
|
fn test_servarr_config_default() {
|
||||||
let servarr_config = ServarrConfig::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.host, Some("localhost".to_string()));
|
||||||
assert_eq!(servarr_config.port, None);
|
assert_eq!(servarr_config.port, None);
|
||||||
assert_eq!(servarr_config.uri, None);
|
assert_eq!(servarr_config.uri, None);
|
||||||
assert!(servarr_config.api_token.is_empty());
|
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.ssl_cert_path, None);
|
||||||
|
assert_eq!(servarr_config.custom_headers, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_header_map_basic() {
|
||||||
|
let mut header_map = HeaderMap::new();
|
||||||
|
header_map.insert(
|
||||||
|
HeaderName::from_static("x-api-key"),
|
||||||
|
HeaderValue::from_static("abc123"),
|
||||||
|
);
|
||||||
|
header_map.insert(
|
||||||
|
HeaderName::from_static("header-1"),
|
||||||
|
HeaderValue::from_static("test"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let config = ServarrConfig {
|
||||||
|
custom_headers: Some(header_map),
|
||||||
|
..ServarrConfig::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let v: Value = serde_json::to_value(&config).expect("serialize ok");
|
||||||
|
let custom = v.get("custom_headers").unwrap();
|
||||||
|
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!(obj.get("X-Api-Key").is_none());
|
||||||
|
assert!(obj.get("HEADER-1").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_header_map_none_is_null() {
|
||||||
|
let config = ServarrConfig::default();
|
||||||
|
let v: Value = serde_json::to_value(&config).expect("serialize ok");
|
||||||
|
assert!(v.get("custom_headers").unwrap().is_null());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_deserialize_optional_env_var_is_present() {
|
||||||
|
unsafe { std::env::set_var("TEST_VAR_DESERIALIZE_OPTION", "localhost") };
|
||||||
|
let yaml_data = r#"
|
||||||
|
host: ${TEST_VAR_DESERIALIZE_OPTION}
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.host, Some("localhost".to_string()));
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_deserialize_optional_env_var_does_not_overwrite_non_env_value() {
|
||||||
|
unsafe { std::env::set_var("TEST_VAR_DESERIALIZE_OPTION_NO_OVERWRITE", "localhost") };
|
||||||
|
let yaml_data = r#"
|
||||||
|
host: www.example.com
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.host, Some("www.example.com".to_string()));
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION_NO_OVERWRITE") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_optional_env_var_empty() {
|
||||||
|
let yaml_data = r#"
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.port, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_deserialize_optional_env_var_header_map_is_present() {
|
||||||
|
unsafe { std::env::set_var("TEST_VAR_DESERIALIZE_HEADER_OPTION", "localhost") };
|
||||||
|
let expected_custom_headers = {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert("X-Api-Host", "localhost".parse().unwrap());
|
||||||
|
headers.insert("api-token", "test123".parse().unwrap());
|
||||||
|
headers
|
||||||
|
};
|
||||||
|
let yaml_data = r#"
|
||||||
|
custom_headers:
|
||||||
|
X-Api-Host: ${TEST_VAR_DESERIALIZE_HEADER_OPTION}
|
||||||
|
api-token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.custom_headers, Some(expected_custom_headers));
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_HEADER_OPTION") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_deserialize_optional_env_var_header_map_does_not_overwrite_non_env_value() {
|
||||||
|
unsafe {
|
||||||
|
std::env::set_var(
|
||||||
|
"TEST_VAR_DESERIALIZE_HEADER_OPTION_NO_OVERWRITE",
|
||||||
|
"localhost",
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let expected_custom_headers = {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert("X-Api-Host", "www.example.com".parse().unwrap());
|
||||||
|
headers.insert("api-token", "test123".parse().unwrap());
|
||||||
|
headers
|
||||||
|
};
|
||||||
|
let yaml_data = r#"
|
||||||
|
custom_headers:
|
||||||
|
X-Api-Host: www.example.com
|
||||||
|
api-token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.custom_headers, Some(expected_custom_headers));
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_HEADER_OPTION_NO_OVERWRITE") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_optional_env_var_header_map_empty() {
|
||||||
|
let yaml_data = r#"
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.custom_headers, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_deserialize_optional_u16_env_var_is_present() {
|
||||||
|
unsafe { std::env::set_var("TEST_VAR_DESERIALIZE_OPTION_U16", "1") };
|
||||||
|
let yaml_data = r#"
|
||||||
|
port: ${TEST_VAR_DESERIALIZE_OPTION_U16}
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.port, Some(1));
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION_U16") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_deserialize_optional_u16_env_var_does_not_overwrite_non_env_value() {
|
||||||
|
unsafe { std::env::set_var("TEST_VAR_DESERIALIZE_OPTION_U16_UNUSED", "1") };
|
||||||
|
let yaml_data = r#"
|
||||||
|
port: 1234
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.port, Some(1234));
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_DESERIALIZE_OPTION_U16_UNUSED") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_optional_u16_env_var_invalid_number() {
|
||||||
|
let yaml_data = r#"
|
||||||
|
port: "hi"
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
let result: Result<ServarrConfig, _> = serde_yaml::from_str(yaml_data);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
let err = result.unwrap_err().to_string();
|
||||||
|
assert!(err.contains("invalid digit found in string"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_optional_u16_env_var_empty() {
|
||||||
|
let yaml_data = r#"
|
||||||
|
api_token: "test123"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config: ServarrConfig = serde_yaml::from_str(yaml_data).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(config.port, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_interpolate_env_vars() {
|
||||||
|
unsafe { std::env::set_var("TEST_VAR_INTERPOLATION", "testing") };
|
||||||
|
|
||||||
|
let var = interpolate_env_vars("${TEST_VAR_INTERPOLATION}");
|
||||||
|
|
||||||
|
assert_str_eq!(var, "testing");
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_INTERPOLATION") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_interpolate_env_vars_defaults_to_original_string_if_not_in_yaml_interpolation_format() {
|
||||||
|
let var = interpolate_env_vars("TEST_VAR_INTERPOLATION_NON_YAML");
|
||||||
|
|
||||||
|
assert_str_eq!(var, "TEST_VAR_INTERPOLATION_NON_YAML");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[serial]
|
||||||
|
fn test_interpolate_env_vars_scrubs_all_unnecessary_characters() {
|
||||||
|
unsafe {
|
||||||
|
std::env::set_var(
|
||||||
|
"TEST_VAR_INTERPOLATION_UNNECESSARY_CHARACTERS",
|
||||||
|
r#"""
|
||||||
|
`"'https://dontdo:this@testing.com/query?test=%20query#results'"` {([\|$!])}
|
||||||
|
"""#,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let var = interpolate_env_vars("${TEST_VAR_INTERPOLATION_UNNECESSARY_CHARACTERS}");
|
||||||
|
|
||||||
|
assert_str_eq!(
|
||||||
|
var,
|
||||||
|
"https://dontdo:this@testing.com/query?test=%20query#results"
|
||||||
|
);
|
||||||
|
unsafe { std::env::remove_var("TEST_VAR_INTERPOLATION_UNNECESSARY_CHARACTERS") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_interpolate_env_vars_scrubs_all_unnecessary_characters_from_non_environment_variable() {
|
||||||
|
let var = interpolate_env_vars("https://dontdo:this@testing.com/query?test=%20query#results");
|
||||||
|
|
||||||
|
assert_str_eq!(
|
||||||
|
var,
|
||||||
|
"https://dontdo:this@testing.com/query?test=%20query#results"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_servarr_config_redacted_debug() {
|
||||||
|
let name = "Servarr".to_owned();
|
||||||
|
let host = "localhost".to_owned();
|
||||||
|
let port = 1234;
|
||||||
|
let uri = "http://localhost:1234".to_owned();
|
||||||
|
let weight = 100;
|
||||||
|
let api_token = "thisisatest".to_owned();
|
||||||
|
let api_token_file = "/root/.config/api_token".to_owned();
|
||||||
|
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 servarr_config = ServarrConfig {
|
||||||
|
name: Some(name),
|
||||||
|
host: Some(host),
|
||||||
|
port: Some(port),
|
||||||
|
uri: Some(uri),
|
||||||
|
weight: Some(weight),
|
||||||
|
api_token: Some(api_token),
|
||||||
|
api_token_file: Some(api_token_file),
|
||||||
|
ssl_cert_path: Some(ssl_cert_path),
|
||||||
|
custom_headers: Some(custom_headers),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_str_eq!(format!("{servarr_config:?}"), expected_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,41 @@
|
|||||||
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
#[path = "context_clues_tests.rs"]
|
#[path = "context_clues_tests.rs"]
|
||||||
mod context_clues_tests;
|
mod context_clues_tests;
|
||||||
|
|
||||||
pub(in crate::app) type ContextClue = (KeyBinding, &'static str);
|
pub type ContextClue = (KeyBinding, &'static str);
|
||||||
|
|
||||||
pub fn build_context_clue_string(context_clues: &[(KeyBinding, &str)]) -> String {
|
pub trait ContextClueProvider {
|
||||||
context_clues
|
fn get_context_clues(_app: &mut App<'_>) -> Option<&'static [ContextClue]>;
|
||||||
.iter()
|
|
||||||
.map(|(key_binding, desc)| format!("{} {desc}", key_binding.key))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join(" | ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static SERVARR_CONTEXT_CLUES: [ContextClue; 3] = [
|
pub struct ServarrContextClueProvider;
|
||||||
|
|
||||||
|
impl ContextClueProvider for ServarrContextClueProvider {
|
||||||
|
fn get_context_clues(app: &mut App<'_>) -> Option<&'static [ContextClue]> {
|
||||||
|
match app.get_current_route() {
|
||||||
|
Route::Radarr(_, _) => RadarrContextClueProvider::get_context_clues(app),
|
||||||
|
Route::Sonarr(_, _) => SonarrContextClueProvider::get_context_clues(app),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static SERVARR_CONTEXT_CLUES: [ContextClue; 10] = [
|
||||||
|
(DEFAULT_KEYBINDINGS.up, "scroll up"),
|
||||||
|
(DEFAULT_KEYBINDINGS.down, "scroll down"),
|
||||||
|
(DEFAULT_KEYBINDINGS.left, "previous tab"),
|
||||||
|
(DEFAULT_KEYBINDINGS.right, "next tab"),
|
||||||
|
(DEFAULT_KEYBINDINGS.pg_up, DEFAULT_KEYBINDINGS.pg_up.desc),
|
||||||
|
(
|
||||||
|
DEFAULT_KEYBINDINGS.pg_down,
|
||||||
|
DEFAULT_KEYBINDINGS.pg_down.desc,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.next_servarr,
|
DEFAULT_KEYBINDINGS.next_servarr,
|
||||||
DEFAULT_KEYBINDINGS.next_servarr.desc,
|
DEFAULT_KEYBINDINGS.next_servarr.desc,
|
||||||
@@ -24,6 +45,7 @@ pub static SERVARR_CONTEXT_CLUES: [ContextClue; 3] = [
|
|||||||
DEFAULT_KEYBINDINGS.previous_servarr.desc,
|
DEFAULT_KEYBINDINGS.previous_servarr.desc,
|
||||||
),
|
),
|
||||||
(DEFAULT_KEYBINDINGS.quit, DEFAULT_KEYBINDINGS.quit.desc),
|
(DEFAULT_KEYBINDINGS.quit, DEFAULT_KEYBINDINGS.quit.desc),
|
||||||
|
(DEFAULT_KEYBINDINGS.help, DEFAULT_KEYBINDINGS.help.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static BARE_POPUP_CONTEXT_CLUES: [ContextClue; 1] =
|
pub static BARE_POPUP_CONTEXT_CLUES: [ContextClue; 1] =
|
||||||
|
|||||||
@@ -3,24 +3,15 @@ mod test {
|
|||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
|
||||||
use crate::app::context_clues::{
|
use crate::app::context_clues::{
|
||||||
BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES,
|
ContextClueProvider, ServarrContextClueProvider, BARE_POPUP_CONTEXT_CLUES,
|
||||||
DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES,
|
BLOCKLIST_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES,
|
||||||
SERVARR_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
INDEXERS_CONTEXT_CLUES, ROOT_FOLDERS_CONTEXT_CLUES, SERVARR_CONTEXT_CLUES,
|
||||||
|
SYSTEM_CONTEXT_CLUES,
|
||||||
};
|
};
|
||||||
use crate::app::{context_clues::build_context_clue_string, key_binding::DEFAULT_KEYBINDINGS};
|
use crate::app::{key_binding::DEFAULT_KEYBINDINGS, App};
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
#[test]
|
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
||||||
fn test_build_context_clue_string() {
|
use crate::models::servarr_data::ActiveKeybindingBlock;
|
||||||
let test_context_clues_array = [
|
|
||||||
(DEFAULT_KEYBINDINGS.add, "add"),
|
|
||||||
(DEFAULT_KEYBINDINGS.delete, "delete"),
|
|
||||||
];
|
|
||||||
|
|
||||||
assert_str_eq!(
|
|
||||||
build_context_clue_string(&test_context_clues_array),
|
|
||||||
"<a> add | <del> delete"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_servarr_context_clues() {
|
fn test_servarr_context_clues() {
|
||||||
@@ -28,6 +19,36 @@ mod test {
|
|||||||
|
|
||||||
let (key_binding, description) = servarr_context_clues_iter.next().unwrap();
|
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_eq!(*key_binding, DEFAULT_KEYBINDINGS.next_servarr);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.next_servarr.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.next_servarr.desc);
|
||||||
|
|
||||||
@@ -40,6 +61,11 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.quit);
|
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.quit);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.quit.desc);
|
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_eq!(servarr_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,4 +235,42 @@ mod test {
|
|||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.refresh.desc);
|
||||||
assert_eq!(system_context_clues_iter.next(), None);
|
assert_eq!(system_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_servarr_context_clue_provider_delegates_to_radarr_provider() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into());
|
||||||
|
|
||||||
|
let context_clues = ServarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
&crate::app::radarr::radarr_context_clues::SYSTEM_TASKS_CONTEXT_CLUES,
|
||||||
|
context_clues.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_servarr_context_clue_provider_delegates_to_sonarr_provider() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveSonarrBlock::SystemTasks.into());
|
||||||
|
|
||||||
|
let context_clues = ServarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
&crate::app::sonarr::sonarr_context_clues::SYSTEM_TASKS_CONTEXT_CLUES,
|
||||||
|
context_clues.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_servarr_context_clue_provider_unsupported_route_returns_none() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveKeybindingBlock::Help.into());
|
||||||
|
|
||||||
|
let context_clues = ServarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_none());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-1
@@ -14,6 +14,8 @@ generate_keybindings! {
|
|||||||
down,
|
down,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
|
pg_down,
|
||||||
|
pg_up,
|
||||||
backspace,
|
backspace,
|
||||||
next_servarr,
|
next_servarr,
|
||||||
previous_servarr,
|
previous_servarr,
|
||||||
@@ -21,6 +23,7 @@ generate_keybindings! {
|
|||||||
search,
|
search,
|
||||||
auto_search,
|
auto_search,
|
||||||
settings,
|
settings,
|
||||||
|
help,
|
||||||
filter,
|
filter,
|
||||||
sort,
|
sort,
|
||||||
edit,
|
edit,
|
||||||
@@ -44,128 +47,203 @@ generate_keybindings! {
|
|||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||||
pub struct KeyBinding {
|
pub struct KeyBinding {
|
||||||
pub key: Key,
|
pub key: Key,
|
||||||
|
pub alt: Option<Key>,
|
||||||
pub desc: &'static str,
|
pub desc: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings {
|
pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings {
|
||||||
add: KeyBinding {
|
add: KeyBinding {
|
||||||
key: Key::Char('a'),
|
key: Key::Char('a'),
|
||||||
|
alt: None,
|
||||||
desc: "add",
|
desc: "add",
|
||||||
},
|
},
|
||||||
up: KeyBinding {
|
up: KeyBinding {
|
||||||
key: Key::Up,
|
key: Key::Up,
|
||||||
|
alt: Some(Key::Char('k')),
|
||||||
desc: "up",
|
desc: "up",
|
||||||
},
|
},
|
||||||
down: KeyBinding {
|
down: KeyBinding {
|
||||||
key: Key::Down,
|
key: Key::Down,
|
||||||
|
alt: Some(Key::Char('j')),
|
||||||
desc: "down",
|
desc: "down",
|
||||||
},
|
},
|
||||||
left: KeyBinding {
|
left: KeyBinding {
|
||||||
key: Key::Left,
|
key: Key::Left,
|
||||||
|
alt: Some(Key::Char('h')),
|
||||||
desc: "left",
|
desc: "left",
|
||||||
},
|
},
|
||||||
right: KeyBinding {
|
right: KeyBinding {
|
||||||
key: Key::Right,
|
key: Key::Right,
|
||||||
|
alt: Some(Key::Char('l')),
|
||||||
desc: "right",
|
desc: "right",
|
||||||
},
|
},
|
||||||
|
pg_down: KeyBinding {
|
||||||
|
key: Key::PgDown,
|
||||||
|
alt: Some(Key::Ctrl('d')),
|
||||||
|
desc: "page down",
|
||||||
|
},
|
||||||
|
pg_up: KeyBinding {
|
||||||
|
key: Key::PgUp,
|
||||||
|
alt: Some(Key::Ctrl('u')),
|
||||||
|
desc: "page up",
|
||||||
|
},
|
||||||
backspace: KeyBinding {
|
backspace: KeyBinding {
|
||||||
key: Key::Backspace,
|
key: Key::Backspace,
|
||||||
|
alt: Some(Key::Ctrl('h')),
|
||||||
desc: "backspace",
|
desc: "backspace",
|
||||||
},
|
},
|
||||||
next_servarr: KeyBinding {
|
next_servarr: KeyBinding {
|
||||||
key: Key::Tab,
|
key: Key::Tab,
|
||||||
|
alt: None,
|
||||||
desc: "next servarr",
|
desc: "next servarr",
|
||||||
},
|
},
|
||||||
previous_servarr: KeyBinding {
|
previous_servarr: KeyBinding {
|
||||||
key: Key::BackTab,
|
key: Key::BackTab,
|
||||||
|
alt: None,
|
||||||
desc: "previous servarr",
|
desc: "previous servarr",
|
||||||
},
|
},
|
||||||
clear: KeyBinding {
|
clear: KeyBinding {
|
||||||
key: Key::Char('c'),
|
key: Key::Char('c'),
|
||||||
|
alt: None,
|
||||||
desc: "clear",
|
desc: "clear",
|
||||||
},
|
},
|
||||||
auto_search: KeyBinding {
|
auto_search: KeyBinding {
|
||||||
key: Key::Char('S'),
|
key: Key::Char('S'),
|
||||||
|
alt: None,
|
||||||
desc: "auto search",
|
desc: "auto search",
|
||||||
},
|
},
|
||||||
search: KeyBinding {
|
search: KeyBinding {
|
||||||
key: Key::Char('s'),
|
key: Key::Char('s'),
|
||||||
|
alt: None,
|
||||||
desc: "search",
|
desc: "search",
|
||||||
},
|
},
|
||||||
settings: KeyBinding {
|
settings: KeyBinding {
|
||||||
key: Key::Char('S'),
|
key: Key::Char('S'),
|
||||||
|
alt: None,
|
||||||
desc: "settings",
|
desc: "settings",
|
||||||
},
|
},
|
||||||
|
help: KeyBinding {
|
||||||
|
key: Key::Char('?'),
|
||||||
|
alt: None,
|
||||||
|
desc: "show/hide keybindings",
|
||||||
|
},
|
||||||
filter: KeyBinding {
|
filter: KeyBinding {
|
||||||
key: Key::Char('f'),
|
key: Key::Char('f'),
|
||||||
|
alt: None,
|
||||||
desc: "filter",
|
desc: "filter",
|
||||||
},
|
},
|
||||||
sort: KeyBinding {
|
sort: KeyBinding {
|
||||||
key: Key::Char('o'),
|
key: Key::Char('o'),
|
||||||
|
alt: None,
|
||||||
desc: "sort",
|
desc: "sort",
|
||||||
},
|
},
|
||||||
edit: KeyBinding {
|
edit: KeyBinding {
|
||||||
key: Key::Char('e'),
|
key: Key::Char('e'),
|
||||||
|
alt: None,
|
||||||
desc: "edit",
|
desc: "edit",
|
||||||
},
|
},
|
||||||
events: KeyBinding {
|
events: KeyBinding {
|
||||||
key: Key::Char('e'),
|
key: Key::Char('e'),
|
||||||
|
alt: None,
|
||||||
desc: "events",
|
desc: "events",
|
||||||
},
|
},
|
||||||
logs: KeyBinding {
|
logs: KeyBinding {
|
||||||
key: Key::Char('l'),
|
key: Key::Char('L'),
|
||||||
|
alt: None,
|
||||||
desc: "logs",
|
desc: "logs",
|
||||||
},
|
},
|
||||||
tasks: KeyBinding {
|
tasks: KeyBinding {
|
||||||
key: Key::Char('t'),
|
key: Key::Char('t'),
|
||||||
|
alt: None,
|
||||||
desc: "tasks",
|
desc: "tasks",
|
||||||
},
|
},
|
||||||
test: KeyBinding {
|
test: KeyBinding {
|
||||||
key: Key::Char('t'),
|
key: Key::Char('t'),
|
||||||
|
alt: None,
|
||||||
desc: "test",
|
desc: "test",
|
||||||
},
|
},
|
||||||
test_all: KeyBinding {
|
test_all: KeyBinding {
|
||||||
key: Key::Char('T'),
|
key: Key::Char('T'),
|
||||||
|
alt: None,
|
||||||
desc: "test all",
|
desc: "test all",
|
||||||
},
|
},
|
||||||
toggle_monitoring: KeyBinding {
|
toggle_monitoring: KeyBinding {
|
||||||
key: Key::Char('m'),
|
key: Key::Char('m'),
|
||||||
|
alt: None,
|
||||||
desc: "toggle monitoring",
|
desc: "toggle monitoring",
|
||||||
},
|
},
|
||||||
refresh: KeyBinding {
|
refresh: KeyBinding {
|
||||||
key: Key::Ctrl('r'),
|
key: Key::Ctrl('r'),
|
||||||
|
alt: None,
|
||||||
desc: "refresh",
|
desc: "refresh",
|
||||||
},
|
},
|
||||||
update: KeyBinding {
|
update: KeyBinding {
|
||||||
key: Key::Char('u'),
|
key: Key::Char('u'),
|
||||||
|
alt: None,
|
||||||
desc: "update",
|
desc: "update",
|
||||||
},
|
},
|
||||||
home: KeyBinding {
|
home: KeyBinding {
|
||||||
key: Key::Home,
|
key: Key::Home,
|
||||||
|
alt: None,
|
||||||
desc: "home",
|
desc: "home",
|
||||||
},
|
},
|
||||||
end: KeyBinding {
|
end: KeyBinding {
|
||||||
key: Key::End,
|
key: Key::End,
|
||||||
|
alt: None,
|
||||||
desc: "end",
|
desc: "end",
|
||||||
},
|
},
|
||||||
delete: KeyBinding {
|
delete: KeyBinding {
|
||||||
key: Key::Delete,
|
key: Key::Delete,
|
||||||
|
alt: None,
|
||||||
desc: "delete",
|
desc: "delete",
|
||||||
},
|
},
|
||||||
submit: KeyBinding {
|
submit: KeyBinding {
|
||||||
key: Key::Enter,
|
key: Key::Enter,
|
||||||
|
alt: None,
|
||||||
desc: "submit",
|
desc: "submit",
|
||||||
},
|
},
|
||||||
confirm: KeyBinding {
|
confirm: KeyBinding {
|
||||||
key: Key::Ctrl('s'),
|
key: Key::Ctrl('s'),
|
||||||
|
alt: None,
|
||||||
desc: "submit",
|
desc: "submit",
|
||||||
},
|
},
|
||||||
quit: KeyBinding {
|
quit: KeyBinding {
|
||||||
key: Key::Char('q'),
|
key: Key::Char('q'),
|
||||||
|
alt: None,
|
||||||
desc: "quit",
|
desc: "quit",
|
||||||
},
|
},
|
||||||
esc: KeyBinding {
|
esc: KeyBinding {
|
||||||
key: Key::Esc,
|
key: Key::Esc,
|
||||||
|
alt: None,
|
||||||
desc: "close",
|
desc: "close",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! matches_key {
|
||||||
|
($binding:ident, $key:expr) => {
|
||||||
|
$crate::app::key_binding::DEFAULT_KEYBINDINGS.$binding.key == $key
|
||||||
|
|| ($crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.is_some()
|
||||||
|
&& $crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.unwrap()
|
||||||
|
== $key)
|
||||||
|
};
|
||||||
|
($binding:ident, $key:expr, $ignore_special_keys:expr) => {
|
||||||
|
$crate::app::key_binding::DEFAULT_KEYBINDINGS.$binding.key == $key
|
||||||
|
|| !$ignore_special_keys
|
||||||
|
&& ($crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.is_some()
|
||||||
|
&& $crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.unwrap()
|
||||||
|
== $key)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,44 +5,88 @@ mod test {
|
|||||||
|
|
||||||
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
use crate::matches_key;
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case(DEFAULT_KEYBINDINGS.add, Key::Char('a'), "add")]
|
#[case(DEFAULT_KEYBINDINGS.add, Key::Char('a'), None, "add")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.up, Key::Up, "up")]
|
#[case(DEFAULT_KEYBINDINGS.up, Key::Up, Some(Key::Char('k')), "up")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.down, Key::Down, "down")]
|
#[case(DEFAULT_KEYBINDINGS.down, Key::Down, Some(Key::Char('j')), "down")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.left, Key::Left, "left")]
|
#[case(DEFAULT_KEYBINDINGS.left, Key::Left, Some(Key::Char('h')), "left")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.right, Key::Right, "right")]
|
#[case(DEFAULT_KEYBINDINGS.right, Key::Right, Some(Key::Char('l')), "right")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.backspace, Key::Backspace, "backspace")]
|
#[case(DEFAULT_KEYBINDINGS.pg_down, Key::PgDown, Some(Key::Ctrl('d')), "page down")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.next_servarr, Key::Tab, "next servarr")]
|
#[case(DEFAULT_KEYBINDINGS.pg_up, Key::PgUp, Some(Key::Ctrl('u')), "page up")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.previous_servarr, Key::BackTab, "previous servarr")]
|
#[case(DEFAULT_KEYBINDINGS.backspace, Key::Backspace, Some(Key::Ctrl('h')), "backspace")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.clear, Key::Char('c'), "clear")]
|
#[case(DEFAULT_KEYBINDINGS.next_servarr, Key::Tab, None, "next servarr")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.auto_search, Key::Char('S'), "auto search")]
|
#[case(DEFAULT_KEYBINDINGS.previous_servarr, Key::BackTab, None, "previous servarr")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.search, Key::Char('s'), "search")]
|
#[case(DEFAULT_KEYBINDINGS.clear, Key::Char('c'), None, "clear")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.settings, Key::Char('S'), "settings")]
|
#[case(DEFAULT_KEYBINDINGS.auto_search, Key::Char('S'), None, "auto search")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.filter, Key::Char('f'), "filter")]
|
#[case(DEFAULT_KEYBINDINGS.search, Key::Char('s'), None, "search")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.sort, Key::Char('o'), "sort")]
|
#[case(DEFAULT_KEYBINDINGS.settings, Key::Char('S'), None, "settings")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.edit, Key::Char('e'), "edit")]
|
#[case(DEFAULT_KEYBINDINGS.help, Key::Char('?'), None, "show/hide keybindings")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.events, Key::Char('e'), "events")]
|
#[case(DEFAULT_KEYBINDINGS.filter, Key::Char('f'), None, "filter")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.logs, Key::Char('l'), "logs")]
|
#[case(DEFAULT_KEYBINDINGS.sort, Key::Char('o'), None, "sort")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.tasks, Key::Char('t'), "tasks")]
|
#[case(DEFAULT_KEYBINDINGS.edit, Key::Char('e'), None, "edit")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.test, Key::Char('t'), "test")]
|
#[case(DEFAULT_KEYBINDINGS.events, Key::Char('e'), None, "events")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.test_all, Key::Char('T'), "test all")]
|
#[case(DEFAULT_KEYBINDINGS.logs, Key::Char('L'), None, "logs")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.toggle_monitoring, Key::Char('m'), "toggle monitoring")]
|
#[case(DEFAULT_KEYBINDINGS.tasks, Key::Char('t'), None, "tasks")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.refresh, Key::Ctrl('r'), "refresh")]
|
#[case(DEFAULT_KEYBINDINGS.test, Key::Char('t'), None, "test")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.update, Key::Char('u'), "update")]
|
#[case(DEFAULT_KEYBINDINGS.test_all, Key::Char('T'), None, "test all")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.home, Key::Home, "home")]
|
#[case(DEFAULT_KEYBINDINGS.toggle_monitoring, Key::Char('m'), None, "toggle monitoring")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.end, Key::End, "end")]
|
#[case(DEFAULT_KEYBINDINGS.refresh, Key::Ctrl('r'), None, "refresh")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.delete, Key::Delete, "delete")]
|
#[case(DEFAULT_KEYBINDINGS.update, Key::Char('u'), None, "update")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.submit, Key::Enter, "submit")]
|
#[case(DEFAULT_KEYBINDINGS.home, Key::Home, None, "home")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.confirm, Key::Ctrl('s'), "submit")]
|
#[case(DEFAULT_KEYBINDINGS.end, Key::End, None, "end")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.quit, Key::Char('q'), "quit")]
|
#[case(DEFAULT_KEYBINDINGS.delete, Key::Delete, None, "delete")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.esc, Key::Esc, "close")]
|
#[case(DEFAULT_KEYBINDINGS.submit, Key::Enter, None, "submit")]
|
||||||
|
#[case(DEFAULT_KEYBINDINGS.confirm, Key::Ctrl('s'), None, "submit")]
|
||||||
|
#[case(DEFAULT_KEYBINDINGS.quit, Key::Char('q'), None, "quit")]
|
||||||
|
#[case(DEFAULT_KEYBINDINGS.esc, Key::Esc, None, "close")]
|
||||||
fn test_default_key_bindings_and_descriptions(
|
fn test_default_key_bindings_and_descriptions(
|
||||||
#[case] key_binding: KeyBinding,
|
#[case] key_binding: KeyBinding,
|
||||||
#[case] expected_key: Key,
|
#[case] expected_key: Key,
|
||||||
|
#[case] expected_alt_key: Option<Key>,
|
||||||
#[case] expected_desc: &str,
|
#[case] expected_desc: &str,
|
||||||
) {
|
) {
|
||||||
assert_eq!(key_binding.key, expected_key);
|
assert_eq!(key_binding.key, expected_key);
|
||||||
|
assert_eq!(key_binding.alt, expected_alt_key);
|
||||||
assert_str_eq!(key_binding.desc, expected_desc);
|
assert_str_eq!(key_binding.desc, expected_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro() {
|
||||||
|
let key = Key::Char('t');
|
||||||
|
|
||||||
|
assert!(matches_key!(test, key));
|
||||||
|
assert!(!matches_key!(test, Key::Char('T')));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro_with_alt_keybinding() {
|
||||||
|
let alt_key = Key::Char('k');
|
||||||
|
let key = Key::Up;
|
||||||
|
|
||||||
|
assert!(matches_key!(up, key));
|
||||||
|
assert!(matches_key!(up, alt_key));
|
||||||
|
assert!(!matches_key!(up, Key::Char('t')));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro_with_alt_keybinding_uses_alt_key_when_ignore_special_keys_is_false() {
|
||||||
|
let alt_key = Key::Char('k');
|
||||||
|
let key = Key::Up;
|
||||||
|
|
||||||
|
assert!(matches_key!(up, key, false));
|
||||||
|
assert!(matches_key!(up, alt_key, false));
|
||||||
|
assert!(!matches_key!(up, Key::Char('t'), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro_with_alt_keybinding_ignores_alt_key_when_ignore_special_keys_is_true() {
|
||||||
|
let alt_key = Key::Char('k');
|
||||||
|
let key = Key::Up;
|
||||||
|
|
||||||
|
assert!(matches_key!(up, key, true));
|
||||||
|
assert!(!matches_key!(up, alt_key, true));
|
||||||
|
assert!(!matches_key!(up, Key::Char('t'), true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+261
-64
@@ -1,16 +1,22 @@
|
|||||||
use std::process;
|
use anyhow::{anyhow, Error, Result};
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use itertools::Itertools;
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
|
use regex::Regex;
|
||||||
|
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::{fs, process};
|
||||||
use tokio::sync::mpsc::Sender;
|
use tokio::sync::mpsc::Sender;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
use veil::Redact;
|
||||||
|
|
||||||
use crate::app::context_clues::{build_context_clue_string, SERVARR_CONTEXT_CLUES};
|
|
||||||
use crate::cli::Command;
|
use crate::cli::Command;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, RadarrData};
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SonarrData};
|
||||||
|
use crate::models::servarr_models::KeybindingItem;
|
||||||
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{HorizontallyScrollableText, Route, TabRoute, TabState};
|
use crate::models::{HorizontallyScrollableText, Route, TabRoute, TabState};
|
||||||
use crate::network::NetworkEvent;
|
use crate::network::NetworkEvent;
|
||||||
|
|
||||||
@@ -29,6 +35,7 @@ pub struct App<'a> {
|
|||||||
pub cancellation_token: CancellationToken,
|
pub cancellation_token: CancellationToken,
|
||||||
pub is_first_render: bool,
|
pub is_first_render: bool,
|
||||||
pub server_tabs: TabState,
|
pub server_tabs: TabState,
|
||||||
|
pub keymapping_table: Option<StatefulTable<KeybindingItem>>,
|
||||||
pub error: HorizontallyScrollableText,
|
pub error: HorizontallyScrollableText,
|
||||||
pub tick_until_poll: u64,
|
pub tick_until_poll: u64,
|
||||||
pub ticks_until_scroll: u64,
|
pub ticks_until_scroll: u64,
|
||||||
@@ -36,13 +43,12 @@ pub struct App<'a> {
|
|||||||
pub is_routing: bool,
|
pub is_routing: bool,
|
||||||
pub is_loading: bool,
|
pub is_loading: bool,
|
||||||
pub should_refresh: bool,
|
pub should_refresh: bool,
|
||||||
pub should_ignore_quit_key: bool,
|
pub ignore_special_keys_for_textbox_input: bool,
|
||||||
pub cli_mode: bool,
|
pub cli_mode: bool,
|
||||||
pub config: AppConfig,
|
|
||||||
pub data: Data<'a>,
|
pub data: Data<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> App<'a> {
|
impl App<'_> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
network_tx: Sender<NetworkEvent>,
|
network_tx: Sender<NetworkEvent>,
|
||||||
config: AppConfig,
|
config: AppConfig,
|
||||||
@@ -50,35 +56,71 @@ impl<'a> App<'a> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let mut server_tabs = Vec::new();
|
let mut server_tabs = Vec::new();
|
||||||
|
|
||||||
if config.radarr.is_some() {
|
if let Some(radarr_configs) = config.radarr {
|
||||||
server_tabs.push(TabRoute {
|
let mut idx = 0;
|
||||||
title: "Radarr",
|
for radarr_config in radarr_configs {
|
||||||
route: ActiveRadarrBlock::Movies.into(),
|
let name = if let Some(name) = radarr_config.name.clone() {
|
||||||
help: format!(
|
name
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
} else {
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
idx += 1;
|
||||||
),
|
format!("Radarr {idx}")
|
||||||
contextual_help: None,
|
};
|
||||||
});
|
|
||||||
|
server_tabs.push(TabRoute {
|
||||||
|
title: name,
|
||||||
|
route: ActiveRadarrBlock::Movies.into(),
|
||||||
|
contextual_help: None,
|
||||||
|
config: Some(radarr_config),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.sonarr.is_some() {
|
if let Some(sonarr_configs) = config.sonarr {
|
||||||
server_tabs.push(TabRoute {
|
let mut idx = 0;
|
||||||
title: "Sonarr",
|
|
||||||
route: ActiveSonarrBlock::Series.into(),
|
for sonarr_config in sonarr_configs {
|
||||||
help: format!(
|
let name = if let Some(name) = sonarr_config.name.clone() {
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
name
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
} else {
|
||||||
),
|
idx += 1;
|
||||||
contextual_help: None,
|
format!("Sonarr {idx}")
|
||||||
});
|
};
|
||||||
|
|
||||||
|
server_tabs.push(TabRoute {
|
||||||
|
title: name,
|
||||||
|
route: ActiveSonarrBlock::Series.into(),
|
||||||
|
contextual_help: None,
|
||||||
|
config: Some(sonarr_config),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let weight_sorted_tabs = server_tabs
|
||||||
|
.into_iter()
|
||||||
|
.sorted_by(|tab1, tab2| {
|
||||||
|
Ord::cmp(
|
||||||
|
tab1
|
||||||
|
.config
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.weight
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&1000),
|
||||||
|
tab2
|
||||||
|
.config
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.weight
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&1000),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
App {
|
App {
|
||||||
network_tx: Some(network_tx),
|
network_tx: Some(network_tx),
|
||||||
config,
|
|
||||||
cancellation_token,
|
cancellation_token,
|
||||||
server_tabs: TabState::new(server_tabs),
|
server_tabs: TabState::new(weight_sorted_tabs),
|
||||||
..App::default()
|
..App::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,48 +207,52 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Default for App<'a> {
|
impl Default for App<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
App {
|
App {
|
||||||
navigation_stack: Vec::new(),
|
navigation_stack: Vec::new(),
|
||||||
network_tx: None,
|
network_tx: None,
|
||||||
cancellation_token: CancellationToken::new(),
|
cancellation_token: CancellationToken::new(),
|
||||||
|
keymapping_table: None,
|
||||||
error: HorizontallyScrollableText::default(),
|
error: HorizontallyScrollableText::default(),
|
||||||
is_first_render: true,
|
is_first_render: true,
|
||||||
server_tabs: TabState::new(vec![
|
server_tabs: TabState::new(Vec::new()),
|
||||||
TabRoute {
|
|
||||||
title: "Radarr",
|
|
||||||
route: ActiveRadarrBlock::Movies.into(),
|
|
||||||
help: format!(
|
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
|
||||||
),
|
|
||||||
contextual_help: None,
|
|
||||||
},
|
|
||||||
TabRoute {
|
|
||||||
title: "Sonarr",
|
|
||||||
route: ActiveSonarrBlock::Series.into(),
|
|
||||||
help: format!(
|
|
||||||
"<↑↓> scroll | ←→ change tab | {} ",
|
|
||||||
build_context_clue_string(&SERVARR_CONTEXT_CLUES)
|
|
||||||
),
|
|
||||||
contextual_help: None,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
tick_until_poll: 400,
|
tick_until_poll: 400,
|
||||||
ticks_until_scroll: 4,
|
ticks_until_scroll: 4,
|
||||||
tick_count: 0,
|
tick_count: 0,
|
||||||
is_loading: false,
|
is_loading: false,
|
||||||
is_routing: false,
|
is_routing: false,
|
||||||
should_refresh: false,
|
should_refresh: false,
|
||||||
should_ignore_quit_key: false,
|
ignore_special_keys_for_textbox_input: false,
|
||||||
cli_mode: false,
|
cli_mode: false,
|
||||||
config: AppConfig::default(),
|
|
||||||
data: Data::default(),
|
data: Data::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl App<'_> {
|
||||||
|
pub fn test_default() -> Self {
|
||||||
|
App {
|
||||||
|
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)]
|
#[derive(Default)]
|
||||||
pub struct Data<'a> {
|
pub struct Data<'a> {
|
||||||
pub radarr_data: RadarrData<'a>,
|
pub radarr_data: RadarrData<'a>,
|
||||||
@@ -215,8 +261,9 @@ pub struct Data<'a> {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Default, Clone)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
pub radarr: Option<ServarrConfig>,
|
pub theme: Option<String>,
|
||||||
pub sonarr: Option<ServarrConfig>,
|
pub radarr: Option<Vec<ServarrConfig>>,
|
||||||
|
pub sonarr: Option<Vec<ServarrConfig>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppConfig {
|
impl AppConfig {
|
||||||
@@ -228,20 +275,19 @@ impl AppConfig {
|
|||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(radarr_config) = &self.radarr {
|
if let Some(radarr_configs) = &self.radarr {
|
||||||
radarr_config.validate();
|
radarr_configs.iter().for_each(|config| config.validate());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sonarr_config) = &self.sonarr {
|
if let Some(sonarr_configs) = &self.sonarr {
|
||||||
sonarr_config.validate();
|
sonarr_configs.iter().for_each(|config| config.validate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_config_present_for_cli(&self, command: &Command) {
|
pub fn verify_config_present_for_cli(&self, command: &Command) {
|
||||||
let msg = |servarr: &str| {
|
let msg = |servarr: &str| {
|
||||||
log_and_print_error(format!(
|
log_and_print_error(format!(
|
||||||
"{} configuration missing; Unable to run any {} commands.",
|
"{servarr} configuration missing; Unable to run any {servarr} commands."
|
||||||
servarr, servarr
|
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
match command {
|
match command {
|
||||||
@@ -256,15 +302,47 @@ impl AppConfig {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn post_process_initialization(&mut self) {
|
||||||
|
if let Some(radarr_configs) = self.radarr.as_mut() {
|
||||||
|
for radarr_config in radarr_configs {
|
||||||
|
radarr_config.post_process_initialization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(sonarr_configs) = self.sonarr.as_mut() {
|
||||||
|
for sonarr_config in sonarr_configs {
|
||||||
|
sonarr_config.post_process_initialization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Redact, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
pub struct ServarrConfig {
|
pub struct ServarrConfig {
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
|
pub name: Option<String>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
pub host: Option<String>,
|
pub host: Option<String>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_u16_env_var")]
|
||||||
pub port: Option<u16>,
|
pub port: Option<u16>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
pub uri: Option<String>,
|
pub uri: Option<String>,
|
||||||
pub api_token: String,
|
#[serde(default, deserialize_with = "deserialize_u16_env_var")]
|
||||||
|
pub weight: Option<u16>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
|
#[redact]
|
||||||
|
pub api_token: Option<String>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
|
pub api_token_file: Option<String>,
|
||||||
|
#[serde(default, deserialize_with = "deserialize_optional_env_var")]
|
||||||
pub ssl_cert_path: Option<String>,
|
pub ssl_cert_path: Option<String>,
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
deserialize_with = "deserialize_optional_env_var_header_map",
|
||||||
|
serialize_with = "serialize_header_map"
|
||||||
|
)]
|
||||||
|
pub custom_headers: Option<HeaderMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServarrConfig {
|
impl ServarrConfig {
|
||||||
@@ -273,22 +351,141 @@ impl ServarrConfig {
|
|||||||
log_and_print_error("'host' or 'uri' is required for configuration".to_owned());
|
log_and_print_error("'host' or 'uri' is required for configuration".to_owned());
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.api_token_file.is_none() && self.api_token.is_none() {
|
||||||
|
log_and_print_error(
|
||||||
|
"'api_token' or 'api_token_path' is required for configuration".to_owned(),
|
||||||
|
);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn post_process_initialization(&mut self) {
|
||||||
|
if let Some(api_token_file) = self.api_token_file.as_ref() {
|
||||||
|
if !PathBuf::from(api_token_file).exists() {
|
||||||
|
log_and_print_error(format!(
|
||||||
|
"The specified {api_token_file} API token file does not exist"
|
||||||
|
));
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let api_token = fs::read_to_string(api_token_file)
|
||||||
|
.map_err(|e| anyhow!(e))
|
||||||
|
.unwrap();
|
||||||
|
self.api_token = Some(api_token.trim().to_owned());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ServarrConfig {
|
impl Default for ServarrConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ServarrConfig {
|
ServarrConfig {
|
||||||
|
name: None,
|
||||||
host: Some("localhost".to_string()),
|
host: Some("localhost".to_string()),
|
||||||
port: None,
|
port: None,
|
||||||
uri: None,
|
uri: None,
|
||||||
api_token: "".to_string(),
|
weight: None,
|
||||||
|
api_token: Some(String::new()),
|
||||||
|
api_token_file: None,
|
||||||
ssl_cert_path: None,
|
ssl_cert_path: None,
|
||||||
|
custom_headers: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_and_print_error(error: String) {
|
pub fn log_and_print_error(error: String) {
|
||||||
error!("{}", error);
|
error!("{error}");
|
||||||
eprintln!("error: {}", error.red());
|
eprintln!("error: {}", error.red());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serialize_header_map<S>(headers: &Option<HeaderMap>, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
if let Some(headers) = headers {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
for (name, value) in headers.iter() {
|
||||||
|
let name_str = name.as_str().to_string();
|
||||||
|
let value_str = value
|
||||||
|
.to_str()
|
||||||
|
.map_err(serde::ser::Error::custom)?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
map.insert(name_str, value_str);
|
||||||
|
}
|
||||||
|
map.serialize(serializer)
|
||||||
|
} else {
|
||||||
|
serializer.serialize_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_optional_env_var<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s: Option<String> = Option::deserialize(deserializer)?;
|
||||||
|
match s {
|
||||||
|
Some(value) => {
|
||||||
|
let interpolated = interpolate_env_vars(&value);
|
||||||
|
Ok(Some(interpolated))
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_optional_env_var_header_map<'de, D>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<Option<HeaderMap>, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let opt: Option<HashMap<String, String>> = Option::deserialize(deserializer)?;
|
||||||
|
match opt {
|
||||||
|
Some(map) => {
|
||||||
|
let mut header_map = HeaderMap::new();
|
||||||
|
for (k, v) in map.iter() {
|
||||||
|
let name = HeaderName::from_bytes(k.as_bytes()).map_err(serde::de::Error::custom)?;
|
||||||
|
let value_str = interpolate_env_vars(v);
|
||||||
|
let value = HeaderValue::from_str(&value_str).map_err(serde::de::Error::custom)?;
|
||||||
|
header_map.insert(name, value);
|
||||||
|
}
|
||||||
|
Ok(Some(header_map))
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u16_env_var<'de, D>(deserializer: D) -> Result<Option<u16>, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s: Option<String> = Option::deserialize(deserializer)?;
|
||||||
|
match s {
|
||||||
|
Some(value) => {
|
||||||
|
let interpolated = interpolate_env_vars(&value);
|
||||||
|
interpolated
|
||||||
|
.parse::<u16>()
|
||||||
|
.map(Some)
|
||||||
|
.map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrubbing_regex.replace_all(&result, "").to_string()
|
||||||
|
})
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|||||||
+8
-17
@@ -8,7 +8,7 @@ pub mod radarr_context_clues;
|
|||||||
#[path = "radarr_tests.rs"]
|
#[path = "radarr_tests.rs"]
|
||||||
mod radarr_tests;
|
mod radarr_tests;
|
||||||
|
|
||||||
impl<'a> App<'a> {
|
impl App<'_> {
|
||||||
pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) {
|
pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) {
|
||||||
match active_radarr_block {
|
match active_radarr_block {
|
||||||
ActiveRadarrBlock::Blocklist => {
|
ActiveRadarrBlock::Blocklist => {
|
||||||
@@ -40,7 +40,7 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
ActiveRadarrBlock::Downloads => {
|
ActiveRadarrBlock::Downloads => {
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
.dispatch_network_event(RadarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::RootFolders => {
|
ActiveRadarrBlock::RootFolders => {
|
||||||
@@ -59,7 +59,7 @@ impl<'a> App<'a> {
|
|||||||
.dispatch_network_event(RadarrEvent::GetMovies.into())
|
.dispatch_network_event(RadarrEvent::GetMovies.into())
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
.dispatch_network_event(RadarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::Indexers => {
|
ActiveRadarrBlock::Indexers => {
|
||||||
@@ -157,12 +157,9 @@ impl<'a> App<'a> {
|
|||||||
async fn check_for_radarr_prompt_action(&mut self) {
|
async fn check_for_radarr_prompt_action(&mut self) {
|
||||||
if self.data.radarr_data.prompt_confirm {
|
if self.data.radarr_data.prompt_confirm {
|
||||||
self.data.radarr_data.prompt_confirm = false;
|
self.data.radarr_data.prompt_confirm = false;
|
||||||
if let Some(radarr_event) = &self.data.radarr_data.prompt_confirm_action {
|
if let Some(radarr_event) = self.data.radarr_data.prompt_confirm_action.take() {
|
||||||
self
|
self.dispatch_network_event(radarr_event.into()).await;
|
||||||
.dispatch_network_event(radarr_event.clone().into())
|
|
||||||
.await;
|
|
||||||
self.should_refresh = true;
|
self.should_refresh = true;
|
||||||
self.data.radarr_data.prompt_confirm_action = None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +201,7 @@ impl<'a> App<'a> {
|
|||||||
.dispatch_network_event(RadarrEvent::GetRootFolders.into())
|
.dispatch_network_event(RadarrEvent::GetRootFolders.into())
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
.dispatch_network_event(RadarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetDiskSpace.into())
|
.dispatch_network_event(RadarrEvent::GetDiskSpace.into())
|
||||||
@@ -231,7 +228,7 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn extract_movie_id(&self) -> i64 {
|
async fn extract_movie_id(&self) -> i64 {
|
||||||
self.data.radarr_data.movies.current_selection().clone().id
|
self.data.radarr_data.movies.current_selection().id
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn extract_movie_search_query(&self) -> String {
|
async fn extract_movie_search_query(&self) -> String {
|
||||||
@@ -246,12 +243,6 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn extract_radarr_indexer_id(&self) -> i64 {
|
async fn extract_radarr_indexer_id(&self) -> i64 {
|
||||||
self
|
self.data.radarr_data.indexers.current_selection().id
|
||||||
.data
|
|
||||||
.radarr_data
|
|
||||||
.indexers
|
|
||||||
.current_selection()
|
|
||||||
.clone()
|
|
||||||
.id
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
use crate::app::context_clues::ContextClue;
|
use crate::app::context_clues::{
|
||||||
|
ContextClue, ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES,
|
||||||
|
};
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::{
|
||||||
|
ActiveRadarrBlock, ADD_MOVIE_BLOCKS, EDIT_COLLECTION_BLOCKS, EDIT_INDEXER_BLOCKS,
|
||||||
|
EDIT_MOVIE_BLOCKS, INDEXER_SETTINGS_BLOCKS, MOVIE_DETAILS_BLOCKS,
|
||||||
|
};
|
||||||
|
use crate::models::Route;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "radarr_context_clues_tests.rs"]
|
#[path = "radarr_context_clues_tests.rs"]
|
||||||
mod radarr_context_clues_tests;
|
mod radarr_context_clues_tests;
|
||||||
|
|
||||||
pub static LIBRARY_CONTEXT_CLUES: [ContextClue; 10] = [
|
pub static LIBRARY_CONTEXT_CLUES: [ContextClue; 11] = [
|
||||||
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
||||||
(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc),
|
(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc),
|
||||||
|
(
|
||||||
|
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
||||||
|
DEFAULT_KEYBINDINGS.toggle_monitoring.desc,
|
||||||
|
),
|
||||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||||
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
||||||
@@ -49,7 +61,7 @@ pub static MOVIE_DETAILS_CONTEXT_CLUES: [ContextClue; 5] = [
|
|||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static MANUAL_MOVIE_SEARCH_CONTEXT_CLUES: [ContextClue; 6] = [
|
pub static MANUAL_MOVIE_SEARCH_CONTEXT_CLUES: [ContextClue; 7] = [
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
@@ -61,12 +73,10 @@ pub static MANUAL_MOVIE_SEARCH_CONTEXT_CLUES: [ContextClue; 6] = [
|
|||||||
DEFAULT_KEYBINDINGS.auto_search,
|
DEFAULT_KEYBINDINGS.auto_search,
|
||||||
DEFAULT_KEYBINDINGS.auto_search.desc,
|
DEFAULT_KEYBINDINGS.auto_search.desc,
|
||||||
),
|
),
|
||||||
|
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static MANUAL_MOVIE_SEARCH_CONTEXTUAL_CONTEXT_CLUES: [ContextClue; 1] =
|
|
||||||
[(DEFAULT_KEYBINDINGS.submit, "details")];
|
|
||||||
|
|
||||||
pub static ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES: [ContextClue; 2] = [
|
pub static ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES: [ContextClue; 2] = [
|
||||||
(DEFAULT_KEYBINDINGS.submit, "details"),
|
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, "edit search"),
|
(DEFAULT_KEYBINDINGS.esc, "edit search"),
|
||||||
@@ -82,3 +92,54 @@ pub static COLLECTION_DETAILS_CONTEXT_CLUES: [ContextClue; 3] = [
|
|||||||
(DEFAULT_KEYBINDINGS.edit, "edit collection"),
|
(DEFAULT_KEYBINDINGS.edit, "edit collection"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub(in crate::app) struct RadarrContextClueProvider;
|
||||||
|
|
||||||
|
impl ContextClueProvider for RadarrContextClueProvider {
|
||||||
|
fn get_context_clues(app: &mut App<'_>) -> Option<&'static [ContextClue]> {
|
||||||
|
let Route::Radarr(active_radarr_block, context_option) = app.get_current_route() else {
|
||||||
|
panic!("RadarrContextClueProvider::get_context_clues called with non-Radarr route");
|
||||||
|
};
|
||||||
|
match active_radarr_block {
|
||||||
|
_ if MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block) => app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.movie_info_tabs
|
||||||
|
.get_active_route_contextual_help(),
|
||||||
|
ActiveRadarrBlock::TestAllIndexers
|
||||||
|
| ActiveRadarrBlock::AddMovieSearchInput
|
||||||
|
| ActiveRadarrBlock::AddMovieEmptySearchResults
|
||||||
|
| ActiveRadarrBlock::SystemLogs
|
||||||
|
| ActiveRadarrBlock::SystemUpdates => Some(&BARE_POPUP_CONTEXT_CLUES),
|
||||||
|
_ if context_option.unwrap_or(active_radarr_block)
|
||||||
|
== ActiveRadarrBlock::ViewMovieOverview =>
|
||||||
|
{
|
||||||
|
Some(&BARE_POPUP_CONTEXT_CLUES)
|
||||||
|
}
|
||||||
|
ActiveRadarrBlock::SystemTasks => Some(&SYSTEM_TASKS_CONTEXT_CLUES),
|
||||||
|
_ if EDIT_COLLECTION_BLOCKS.contains(&active_radarr_block)
|
||||||
|
|| EDIT_INDEXER_BLOCKS.contains(&active_radarr_block)
|
||||||
|
|| INDEXER_SETTINGS_BLOCKS.contains(&active_radarr_block)
|
||||||
|
|| EDIT_MOVIE_BLOCKS.contains(&active_radarr_block) =>
|
||||||
|
{
|
||||||
|
Some(&CONFIRMATION_PROMPT_CONTEXT_CLUES)
|
||||||
|
}
|
||||||
|
ActiveRadarrBlock::AddMoviePrompt
|
||||||
|
| ActiveRadarrBlock::AddMovieSelectMonitor
|
||||||
|
| ActiveRadarrBlock::AddMovieSelectMinimumAvailability
|
||||||
|
| ActiveRadarrBlock::AddMovieSelectQualityProfile
|
||||||
|
| ActiveRadarrBlock::AddMovieSelectRootFolder
|
||||||
|
| ActiveRadarrBlock::AddMovieTagsInput
|
||||||
|
| ActiveRadarrBlock::SystemTaskStartConfirmPrompt => Some(&CONFIRMATION_PROMPT_CONTEXT_CLUES),
|
||||||
|
_ if ADD_MOVIE_BLOCKS.contains(&active_radarr_block) => {
|
||||||
|
Some(&ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES)
|
||||||
|
}
|
||||||
|
ActiveRadarrBlock::CollectionDetails => Some(&COLLECTION_DETAILS_CONTEXT_CLUES),
|
||||||
|
_ => app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.main_tabs
|
||||||
|
.get_active_route_contextual_help(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use crate::app::context_clues::{
|
||||||
|
ContextClue, ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES,
|
||||||
|
CONFIRMATION_PROMPT_CONTEXT_CLUES, DOWNLOADS_CONTEXT_CLUES, INDEXERS_CONTEXT_CLUES,
|
||||||
|
ROOT_FOLDERS_CONTEXT_CLUES, SYSTEM_CONTEXT_CLUES,
|
||||||
|
};
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
use crate::app::radarr::radarr_context_clues::{
|
use crate::app::radarr::radarr_context_clues::{
|
||||||
ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, COLLECTIONS_CONTEXT_CLUES,
|
RadarrContextClueProvider, ADD_MOVIE_SEARCH_RESULTS_CONTEXT_CLUES, COLLECTIONS_CONTEXT_CLUES,
|
||||||
COLLECTION_DETAILS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES,
|
COLLECTION_DETAILS_CONTEXT_CLUES, LIBRARY_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES,
|
||||||
MANUAL_MOVIE_SEARCH_CONTEXTUAL_CONTEXT_CLUES, MANUAL_MOVIE_SEARCH_CONTEXT_CLUES,
|
|
||||||
MOVIE_DETAILS_CONTEXT_CLUES, SYSTEM_TASKS_CONTEXT_CLUES,
|
MOVIE_DETAILS_CONTEXT_CLUES, 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 rstest::rstest;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_library_context_clues() {
|
fn test_library_context_clues() {
|
||||||
@@ -26,6 +33,11 @@ mod tests {
|
|||||||
|
|
||||||
let (key_binding, description) = library_context_clues_iter.next().unwrap();
|
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_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
||||||
|
|
||||||
@@ -174,26 +186,15 @@ mod tests {
|
|||||||
|
|
||||||
let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap();
|
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_eq!(manual_movie_search_context_clues_iter.next(), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_manual_movie_search_contextual_context_clues() {
|
|
||||||
let mut manual_movie_search_contextual_context_clues_iter =
|
|
||||||
MANUAL_MOVIE_SEARCH_CONTEXTUAL_CONTEXT_CLUES.iter();
|
|
||||||
|
|
||||||
let (key_binding, description) = manual_movie_search_contextual_context_clues_iter
|
|
||||||
.next()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||||
assert_str_eq!(*description, "details");
|
assert_str_eq!(*description, "details");
|
||||||
assert_eq!(
|
|
||||||
manual_movie_search_contextual_context_clues_iter.next(),
|
let (key_binding, description) = manual_movie_search_context_clues_iter.next().unwrap();
|
||||||
None
|
|
||||||
);
|
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||||
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||||
|
|
||||||
|
assert_eq!(manual_movie_search_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -249,4 +250,255 @@ mod tests {
|
|||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||||
assert_eq!(collection_details_context_clues_iter.next(), None);
|
assert_eq!(collection_details_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(
|
||||||
|
expected = "RadarrContextClueProvider::get_context_clues called with non-Radarr route"
|
||||||
|
)]
|
||||||
|
fn test_radarr_context_clue_provider_get_context_clues_non_radarr_route() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveSonarrBlock::default().into());
|
||||||
|
|
||||||
|
// This should panic because the route is not a Radarr route
|
||||||
|
RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(ActiveRadarrBlock::TestAllIndexers, None)]
|
||||||
|
#[case(ActiveRadarrBlock::AddMovieSearchInput, None)]
|
||||||
|
#[case(ActiveRadarrBlock::AddMovieEmptySearchResults, None)]
|
||||||
|
#[case(ActiveRadarrBlock::SystemLogs, None)]
|
||||||
|
#[case(ActiveRadarrBlock::SystemUpdates, None)]
|
||||||
|
#[case(ActiveRadarrBlock::ViewMovieOverview, None)]
|
||||||
|
#[case(
|
||||||
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
|
Some(ActiveRadarrBlock::ViewMovieOverview)
|
||||||
|
)]
|
||||||
|
fn test_radarr_context_clue_provider_bare_popup_context_clues(
|
||||||
|
#[case] active_radarr_block: ActiveRadarrBlock,
|
||||||
|
#[case] context_option: Option<ActiveRadarrBlock>,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack((active_radarr_block, context_option).into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&BARE_POPUP_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveRadarrBlock::MovieDetails, &MOVIE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(1, ActiveRadarrBlock::MovieHistory, &MOVIE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(2, ActiveRadarrBlock::FileInfo, &MOVIE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(3, ActiveRadarrBlock::Cast, &MOVIE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(4, ActiveRadarrBlock::Crew, &MOVIE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(5, ActiveRadarrBlock::ManualSearch, &MANUAL_MOVIE_SEARCH_CONTEXT_CLUES)]
|
||||||
|
fn test_radarr_context_clue_provider_movie_details_block_context_clues(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] active_radarr_block: ActiveRadarrBlock,
|
||||||
|
#[case] expected_context_clues: &[ContextClue],
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.data.radarr_data.movie_info_tabs.set_index(index);
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(expected_context_clues, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_context_clue_provider_confirmation_prompt_context_clues(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
|
ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
|
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
||||||
|
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
||||||
|
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
||||||
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
|
ActiveRadarrBlock::SystemTaskStartConfirmPrompt
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_context_clue_provider_confirmation_prompt_context_clues_edit_collection_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
|
ActiveRadarrBlock::EditCollectionConfirmPrompt,
|
||||||
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
|
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
||||||
|
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
||||||
|
ActiveRadarrBlock::EditCollectionToggleSearchOnAdd,
|
||||||
|
ActiveRadarrBlock::EditCollectionToggleMonitored
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_context_clue_provider_confirmation_prompt_context_clues_edit_indexer_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::EditIndexerPrompt,
|
||||||
|
ActiveRadarrBlock::EditIndexerConfirmPrompt,
|
||||||
|
ActiveRadarrBlock::EditIndexerApiKeyInput,
|
||||||
|
ActiveRadarrBlock::EditIndexerNameInput,
|
||||||
|
ActiveRadarrBlock::EditIndexerSeedRatioInput,
|
||||||
|
ActiveRadarrBlock::EditIndexerToggleEnableRss,
|
||||||
|
ActiveRadarrBlock::EditIndexerToggleEnableAutomaticSearch,
|
||||||
|
ActiveRadarrBlock::EditIndexerToggleEnableInteractiveSearch,
|
||||||
|
ActiveRadarrBlock::EditIndexerPriorityInput,
|
||||||
|
ActiveRadarrBlock::EditIndexerUrlInput,
|
||||||
|
ActiveRadarrBlock::EditIndexerTagsInput
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_context_clue_provider_confirmation_prompt_context_clues_indexer_settings_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsConfirmPrompt,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsRetentionInput,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsToggleAllowHardcodedSubs,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags,
|
||||||
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_context_clue_provider_confirmation_prompt_context_clues_edit_movie_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
|
ActiveRadarrBlock::EditMovieConfirmPrompt,
|
||||||
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
|
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
||||||
|
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
||||||
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
|
ActiveRadarrBlock::EditMovieToggleMonitored
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&CONFIRMATION_PROMPT_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_context_clue_provider_add_movie_search_results_context_clues(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
|
ActiveRadarrBlock::AddMovieAlreadyInLibrary
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_radarr_context_clue_provider_collection_details_context_clues() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&COLLECTION_DETAILS_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_radarr_context_clue_provider_system_tasks_context_clues() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(&SYSTEM_TASKS_CONTEXT_CLUES, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveRadarrBlock::Movies, &LIBRARY_CONTEXT_CLUES)]
|
||||||
|
#[case(1, ActiveRadarrBlock::Collections, &COLLECTIONS_CONTEXT_CLUES)]
|
||||||
|
#[case(2, ActiveRadarrBlock::Downloads, &DOWNLOADS_CONTEXT_CLUES)]
|
||||||
|
#[case(3, ActiveRadarrBlock::Blocklist, &BLOCKLIST_CONTEXT_CLUES)]
|
||||||
|
#[case(4, ActiveRadarrBlock::RootFolders, &ROOT_FOLDERS_CONTEXT_CLUES)]
|
||||||
|
#[case(5, ActiveRadarrBlock::Indexers, &INDEXERS_CONTEXT_CLUES)]
|
||||||
|
#[case(6, ActiveRadarrBlock::System, &SYSTEM_CONTEXT_CLUES)]
|
||||||
|
fn test_radarr_context_clue_provider_radarr_blocks_context_clues(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] active_radarr_block: ActiveRadarrBlock,
|
||||||
|
#[case] expected_context_clues: &[ContextClue],
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = RadarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(expected_context_clues, context_clues.unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ mod tests {
|
|||||||
assert!(app.is_loading);
|
assert!(app.is_loading);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
@@ -186,7 +186,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
@@ -467,7 +467,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_dispatch_by_cast_crew_blocks_cast_and_crew_non_empty() {
|
async fn test_dispatch_by_cast_crew_blocks_cast_and_crew_non_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
for active_radarr_block in &[ActiveRadarrBlock::Cast, ActiveRadarrBlock::Crew] {
|
for active_radarr_block in &[ActiveRadarrBlock::Cast, ActiveRadarrBlock::Crew] {
|
||||||
let mut movie_details_modal = MovieDetailsModal::default();
|
let mut movie_details_modal = MovieDetailsModal::default();
|
||||||
@@ -511,7 +511,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_dispatch_by_manual_search_block_movie_releases_non_empty() {
|
async fn test_dispatch_by_manual_search_block_movie_releases_non_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut movie_details_modal = MovieDetailsModal::default();
|
let mut movie_details_modal = MovieDetailsModal::default();
|
||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
@@ -531,7 +531,7 @@ mod tests {
|
|||||||
async fn test_dispatch_by_manual_search_block_is_loading() {
|
async fn test_dispatch_by_manual_search_block_is_loading() {
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app
|
app
|
||||||
@@ -545,7 +545,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_check_for_radarr_prompt_action_no_prompt_confirm() {
|
async fn test_check_for_radarr_prompt_action_no_prompt_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.prompt_confirm = false;
|
app.data.radarr_data.prompt_confirm = false;
|
||||||
|
|
||||||
app.check_for_radarr_prompt_action().await;
|
app.check_for_radarr_prompt_action().await;
|
||||||
@@ -591,7 +591,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
@@ -625,7 +625,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
@@ -650,7 +650,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -675,7 +675,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
@@ -692,7 +692,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(app.is_loading);
|
assert!(app.is_loading);
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
@@ -722,14 +722,14 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetDownloads.into()
|
RadarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(app.is_loading);
|
assert!(app.is_loading);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_populate_movie_collection_table_unfiltered() {
|
async fn test_populate_movie_collection_table_unfiltered() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.collections.set_items(vec![Collection {
|
app.data.radarr_data.collections.set_items(vec![Collection {
|
||||||
movies: Some(vec![CollectionMovie::default()]),
|
movies: Some(vec![CollectionMovie::default()]),
|
||||||
..Collection::default()
|
..Collection::default()
|
||||||
@@ -742,7 +742,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_populate_movie_collection_table_filtered() {
|
async fn test_populate_movie_collection_table_filtered() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -759,7 +759,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_movie_id() {
|
async fn test_extract_movie_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.movies.set_items(vec![Movie {
|
app.data.radarr_data.movies.set_items(vec![Movie {
|
||||||
id: 1,
|
id: 1,
|
||||||
..Movie::default()
|
..Movie::default()
|
||||||
@@ -770,7 +770,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_radarr_indexer_id() {
|
async fn test_extract_radarr_indexer_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexers.set_items(vec![Indexer {
|
app.data.radarr_data.indexers.set_items(vec![Indexer {
|
||||||
id: 1,
|
id: 1,
|
||||||
..Indexer::default()
|
..Indexer::default()
|
||||||
@@ -785,7 +785,7 @@ mod tests {
|
|||||||
network_tx: Some(sync_network_tx),
|
network_tx: Some(sync_network_tx),
|
||||||
tick_count: 1,
|
tick_count: 1,
|
||||||
is_first_render: false,
|
is_first_render: false,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub mod sonarr_context_clues;
|
|||||||
#[path = "sonarr_tests.rs"]
|
#[path = "sonarr_tests.rs"]
|
||||||
mod sonarr_tests;
|
mod sonarr_tests;
|
||||||
|
|
||||||
impl<'a> App<'a> {
|
impl App<'_> {
|
||||||
pub(super) async fn dispatch_by_sonarr_block(&mut self, active_sonarr_block: &ActiveSonarrBlock) {
|
pub(super) async fn dispatch_by_sonarr_block(&mut self, active_sonarr_block: &ActiveSonarrBlock) {
|
||||||
match active_sonarr_block {
|
match active_sonarr_block {
|
||||||
ActiveSonarrBlock::Series => {
|
ActiveSonarrBlock::Series => {
|
||||||
@@ -53,7 +53,7 @@ impl<'a> App<'a> {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
.dispatch_network_event(SonarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::SeasonHistory => {
|
ActiveSonarrBlock::SeasonHistory => {
|
||||||
@@ -108,7 +108,7 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
ActiveSonarrBlock::Downloads => {
|
ActiveSonarrBlock::Downloads => {
|
||||||
self
|
self
|
||||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
.dispatch_network_event(SonarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::Blocklist => {
|
ActiveSonarrBlock::Blocklist => {
|
||||||
@@ -187,12 +187,9 @@ impl<'a> App<'a> {
|
|||||||
async fn check_for_sonarr_prompt_action(&mut self) {
|
async fn check_for_sonarr_prompt_action(&mut self) {
|
||||||
if self.data.sonarr_data.prompt_confirm {
|
if self.data.sonarr_data.prompt_confirm {
|
||||||
self.data.sonarr_data.prompt_confirm = false;
|
self.data.sonarr_data.prompt_confirm = false;
|
||||||
if let Some(sonarr_event) = &self.data.sonarr_data.prompt_confirm_action {
|
if let Some(sonarr_event) = self.data.sonarr_data.prompt_confirm_action.take() {
|
||||||
self
|
self.dispatch_network_event(sonarr_event.into()).await;
|
||||||
.dispatch_network_event(sonarr_event.clone().into())
|
|
||||||
.await;
|
|
||||||
self.should_refresh = true;
|
self.should_refresh = true;
|
||||||
self.data.sonarr_data.prompt_confirm_action = None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +234,7 @@ impl<'a> App<'a> {
|
|||||||
.dispatch_network_event(SonarrEvent::GetRootFolders.into())
|
.dispatch_network_event(SonarrEvent::GetRootFolders.into())
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(SonarrEvent::GetDownloads.into())
|
.dispatch_network_event(SonarrEvent::GetDownloads(500).into())
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(SonarrEvent::GetDiskSpace.into())
|
.dispatch_network_event(SonarrEvent::GetDiskSpace.into())
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
use crate::app::{context_clues::ContextClue, key_binding::DEFAULT_KEYBINDINGS};
|
use crate::app::context_clues::{
|
||||||
|
ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, CONFIRMATION_PROMPT_CONTEXT_CLUES,
|
||||||
|
};
|
||||||
|
use crate::app::{context_clues::ContextClue, key_binding::DEFAULT_KEYBINDINGS, App};
|
||||||
|
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||||
|
ActiveSonarrBlock, ADD_SERIES_BLOCKS, EDIT_INDEXER_BLOCKS, EDIT_SERIES_BLOCKS,
|
||||||
|
EPISODE_DETAILS_BLOCKS, INDEXER_SETTINGS_BLOCKS, SEASON_DETAILS_BLOCKS, SERIES_DETAILS_BLOCKS,
|
||||||
|
};
|
||||||
|
use crate::models::Route;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "sonarr_context_clues_tests.rs"]
|
#[path = "sonarr_context_clues_tests.rs"]
|
||||||
@@ -9,9 +17,13 @@ pub static ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES: [ContextClue; 2] = [
|
|||||||
(DEFAULT_KEYBINDINGS.esc, "edit search"),
|
(DEFAULT_KEYBINDINGS.esc, "edit search"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static SERIES_CONTEXT_CLUES: [ContextClue; 10] = [
|
pub static SERIES_CONTEXT_CLUES: [ContextClue; 11] = [
|
||||||
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
(DEFAULT_KEYBINDINGS.add, DEFAULT_KEYBINDINGS.add.desc),
|
||||||
(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc),
|
(DEFAULT_KEYBINDINGS.edit, DEFAULT_KEYBINDINGS.edit.desc),
|
||||||
|
(
|
||||||
|
DEFAULT_KEYBINDINGS.toggle_monitoring,
|
||||||
|
DEFAULT_KEYBINDINGS.toggle_monitoring.desc,
|
||||||
|
),
|
||||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||||
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
(DEFAULT_KEYBINDINGS.delete, DEFAULT_KEYBINDINGS.delete.desc),
|
||||||
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
|
||||||
@@ -75,12 +87,7 @@ pub static SERIES_HISTORY_CONTEXT_CLUES: [ContextClue; 9] = [
|
|||||||
(DEFAULT_KEYBINDINGS.esc, "cancel filter/close"),
|
(DEFAULT_KEYBINDINGS.esc, "cancel filter/close"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static SEASON_DETAILS_CONTEXTUAL_CONTEXT_CLUES: [ContextClue; 2] = [
|
pub static SEASON_DETAILS_CONTEXT_CLUES: [ContextClue; 7] = [
|
||||||
(DEFAULT_KEYBINDINGS.submit, "episode details"),
|
|
||||||
(DEFAULT_KEYBINDINGS.delete, "delete episode"),
|
|
||||||
];
|
|
||||||
|
|
||||||
pub static SEASON_DETAILS_CONTEXT_CLUES: [ContextClue; 5] = [
|
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
@@ -95,9 +102,11 @@ pub static SEASON_DETAILS_CONTEXT_CLUES: [ContextClue; 5] = [
|
|||||||
DEFAULT_KEYBINDINGS.auto_search.desc,
|
DEFAULT_KEYBINDINGS.auto_search.desc,
|
||||||
),
|
),
|
||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
|
(DEFAULT_KEYBINDINGS.submit, "episode details"),
|
||||||
|
(DEFAULT_KEYBINDINGS.delete, "delete episode"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static SEASON_HISTORY_CONTEXT_CLUES: [ContextClue; 6] = [
|
pub static SEASON_HISTORY_CONTEXT_CLUES: [ContextClue; 7] = [
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
@@ -109,10 +118,11 @@ pub static SEASON_HISTORY_CONTEXT_CLUES: [ContextClue; 6] = [
|
|||||||
DEFAULT_KEYBINDINGS.auto_search,
|
DEFAULT_KEYBINDINGS.auto_search,
|
||||||
DEFAULT_KEYBINDINGS.auto_search.desc,
|
DEFAULT_KEYBINDINGS.auto_search.desc,
|
||||||
),
|
),
|
||||||
|
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, "cancel filter/close"),
|
(DEFAULT_KEYBINDINGS.esc, "cancel filter/close"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static MANUAL_SEASON_SEARCH_CONTEXT_CLUES: [ContextClue; 4] = [
|
pub static MANUAL_SEASON_SEARCH_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
@@ -122,10 +132,11 @@ pub static MANUAL_SEASON_SEARCH_CONTEXT_CLUES: [ContextClue; 4] = [
|
|||||||
DEFAULT_KEYBINDINGS.auto_search.desc,
|
DEFAULT_KEYBINDINGS.auto_search.desc,
|
||||||
),
|
),
|
||||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||||
|
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static MANUAL_EPISODE_SEARCH_CONTEXT_CLUES: [ContextClue; 4] = [
|
pub static MANUAL_EPISODE_SEARCH_CONTEXT_CLUES: [ContextClue; 5] = [
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
DEFAULT_KEYBINDINGS.refresh.desc,
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
@@ -135,12 +146,10 @@ pub static MANUAL_EPISODE_SEARCH_CONTEXT_CLUES: [ContextClue; 4] = [
|
|||||||
DEFAULT_KEYBINDINGS.auto_search.desc,
|
DEFAULT_KEYBINDINGS.auto_search.desc,
|
||||||
),
|
),
|
||||||
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
(DEFAULT_KEYBINDINGS.sort, DEFAULT_KEYBINDINGS.sort.desc),
|
||||||
|
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub static DETAILS_CONTEXTUAL_CONTEXT_CLUES: [ContextClue; 1] =
|
|
||||||
[(DEFAULT_KEYBINDINGS.submit, "details")];
|
|
||||||
|
|
||||||
pub static EPISODE_DETAILS_CONTEXT_CLUES: [ContextClue; 3] = [
|
pub static EPISODE_DETAILS_CONTEXT_CLUES: [ContextClue; 3] = [
|
||||||
(
|
(
|
||||||
DEFAULT_KEYBINDINGS.refresh,
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
@@ -153,7 +162,84 @@ pub static EPISODE_DETAILS_CONTEXT_CLUES: [ContextClue; 3] = [
|
|||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub static SELECTABLE_EPISODE_DETAILS_CONTEXT_CLUES: [ContextClue; 4] = [
|
||||||
|
(
|
||||||
|
DEFAULT_KEYBINDINGS.refresh,
|
||||||
|
DEFAULT_KEYBINDINGS.refresh.desc,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
DEFAULT_KEYBINDINGS.auto_search,
|
||||||
|
DEFAULT_KEYBINDINGS.auto_search.desc,
|
||||||
|
),
|
||||||
|
(DEFAULT_KEYBINDINGS.submit, "details"),
|
||||||
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
|
];
|
||||||
|
|
||||||
pub static SYSTEM_TASKS_CONTEXT_CLUES: [ContextClue; 2] = [
|
pub static SYSTEM_TASKS_CONTEXT_CLUES: [ContextClue; 2] = [
|
||||||
(DEFAULT_KEYBINDINGS.submit, "start task"),
|
(DEFAULT_KEYBINDINGS.submit, "start task"),
|
||||||
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
pub(in crate::app) struct SonarrContextClueProvider;
|
||||||
|
|
||||||
|
impl ContextClueProvider for SonarrContextClueProvider {
|
||||||
|
fn get_context_clues(app: &mut App<'_>) -> Option<&'static [ContextClue]> {
|
||||||
|
let Route::Sonarr(active_sonarr_block, _) = app.get_current_route() else {
|
||||||
|
panic!("SonarrContextClueProvider::get_context_clues called with non-Sonarr route");
|
||||||
|
};
|
||||||
|
match active_sonarr_block {
|
||||||
|
_ if SERIES_DETAILS_BLOCKS.contains(&active_sonarr_block) => app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_info_tabs
|
||||||
|
.get_active_route_contextual_help(),
|
||||||
|
_ if SEASON_DETAILS_BLOCKS.contains(&active_sonarr_block) => app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.season_details_modal
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.season_details_tabs
|
||||||
|
.get_active_route_contextual_help(),
|
||||||
|
_ if EPISODE_DETAILS_BLOCKS.contains(&active_sonarr_block) => app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.season_details_modal
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.episode_details_modal
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.episode_details_tabs
|
||||||
|
.get_active_route_contextual_help(),
|
||||||
|
ActiveSonarrBlock::TestAllIndexers
|
||||||
|
| ActiveSonarrBlock::AddSeriesSearchInput
|
||||||
|
| ActiveSonarrBlock::AddSeriesEmptySearchResults
|
||||||
|
| ActiveSonarrBlock::SystemLogs
|
||||||
|
| ActiveSonarrBlock::SystemUpdates => Some(&BARE_POPUP_CONTEXT_CLUES),
|
||||||
|
_ if EDIT_INDEXER_BLOCKS.contains(&active_sonarr_block)
|
||||||
|
|| INDEXER_SETTINGS_BLOCKS.contains(&active_sonarr_block)
|
||||||
|
|| EDIT_SERIES_BLOCKS.contains(&active_sonarr_block) =>
|
||||||
|
{
|
||||||
|
Some(&CONFIRMATION_PROMPT_CONTEXT_CLUES)
|
||||||
|
}
|
||||||
|
ActiveSonarrBlock::AddSeriesPrompt
|
||||||
|
| ActiveSonarrBlock::AddSeriesSelectMonitor
|
||||||
|
| ActiveSonarrBlock::AddSeriesSelectSeriesType
|
||||||
|
| ActiveSonarrBlock::AddSeriesSelectQualityProfile
|
||||||
|
| ActiveSonarrBlock::AddSeriesSelectLanguageProfile
|
||||||
|
| ActiveSonarrBlock::AddSeriesSelectRootFolder
|
||||||
|
| ActiveSonarrBlock::AddSeriesTagsInput
|
||||||
|
| ActiveSonarrBlock::SystemTaskStartConfirmPrompt => Some(&CONFIRMATION_PROMPT_CONTEXT_CLUES),
|
||||||
|
_ if ADD_SERIES_BLOCKS.contains(&active_sonarr_block) => {
|
||||||
|
Some(&ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES)
|
||||||
|
}
|
||||||
|
ActiveSonarrBlock::SystemTasks => Some(&SYSTEM_TASKS_CONTEXT_CLUES),
|
||||||
|
_ => app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.main_tabs
|
||||||
|
.get_active_route_contextual_help(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,17 +1,29 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use crate::app::context_clues::{
|
||||||
|
ContextClue, ContextClueProvider, BARE_POPUP_CONTEXT_CLUES, BLOCKLIST_CONTEXT_CLUES,
|
||||||
|
CONFIRMATION_PROMPT_CONTEXT_CLUES, 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,
|
||||||
|
};
|
||||||
use crate::app::{
|
use crate::app::{
|
||||||
key_binding::DEFAULT_KEYBINDINGS,
|
key_binding::DEFAULT_KEYBINDINGS,
|
||||||
sonarr::sonarr_context_clues::{
|
sonarr::sonarr_context_clues::{
|
||||||
ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES, DETAILS_CONTEXTUAL_CONTEXT_CLUES,
|
ADD_SERIES_SEARCH_RESULTS_CONTEXT_CLUES, EPISODE_DETAILS_CONTEXT_CLUES,
|
||||||
EPISODE_DETAILS_CONTEXT_CLUES, HISTORY_CONTEXT_CLUES, MANUAL_EPISODE_SEARCH_CONTEXT_CLUES,
|
HISTORY_CONTEXT_CLUES, MANUAL_EPISODE_SEARCH_CONTEXT_CLUES,
|
||||||
MANUAL_SEASON_SEARCH_CONTEXT_CLUES, SEASON_DETAILS_CONTEXTUAL_CONTEXT_CLUES,
|
MANUAL_SEASON_SEARCH_CONTEXT_CLUES, SEASON_DETAILS_CONTEXT_CLUES,
|
||||||
SEASON_DETAILS_CONTEXT_CLUES, SEASON_HISTORY_CONTEXT_CLUES, SERIES_CONTEXT_CLUES,
|
SEASON_HISTORY_CONTEXT_CLUES, SERIES_CONTEXT_CLUES, SERIES_DETAILS_CONTEXT_CLUES,
|
||||||
SERIES_DETAILS_CONTEXT_CLUES, SERIES_HISTORY_CONTEXT_CLUES, SYSTEM_TASKS_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]
|
#[test]
|
||||||
fn test_add_series_search_results_context_clues() {
|
fn test_add_series_search_results_context_clues() {
|
||||||
@@ -46,6 +58,11 @@ mod tests {
|
|||||||
|
|
||||||
let (key_binding, description) = series_context_clues_iter.next().unwrap();
|
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_eq!(*key_binding, DEFAULT_KEYBINDINGS.sort);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.sort.desc);
|
||||||
|
|
||||||
@@ -247,23 +264,18 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||||
assert_eq!(season_details_context_clues_iter.next(), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
let (key_binding, description) = season_details_context_clues_iter.next().unwrap();
|
||||||
fn test_season_details_contextual_context_clues() {
|
|
||||||
let mut season_details_contextual_context_clues_iter =
|
|
||||||
SEASON_DETAILS_CONTEXTUAL_CONTEXT_CLUES.iter();
|
|
||||||
let (key_binding, description) = season_details_contextual_context_clues_iter.next().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
||||||
assert_str_eq!(*description, "episode details");
|
assert_str_eq!(*description, "episode details");
|
||||||
|
|
||||||
let (key_binding, description) = season_details_contextual_context_clues_iter.next().unwrap();
|
let (key_binding, description) = season_details_context_clues_iter.next().unwrap();
|
||||||
|
|
||||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.delete);
|
||||||
assert_str_eq!(*description, "delete episode");
|
assert_str_eq!(*description, "delete episode");
|
||||||
assert_eq!(season_details_contextual_context_clues_iter.next(), None);
|
|
||||||
|
assert_eq!(season_details_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -296,6 +308,11 @@ mod tests {
|
|||||||
|
|
||||||
let (key_binding, description) = season_history_context_clues_iter.next().unwrap();
|
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_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||||
assert_str_eq!(*description, "cancel filter/close");
|
assert_str_eq!(*description, "cancel filter/close");
|
||||||
assert_eq!(season_history_context_clues_iter.next(), None);
|
assert_eq!(season_history_context_clues_iter.next(), None);
|
||||||
@@ -322,6 +339,11 @@ mod tests {
|
|||||||
|
|
||||||
let (key_binding, description) = manual_season_search_context_clues_iter.next().unwrap();
|
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_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||||
assert_eq!(manual_season_search_context_clues_iter.next(), None);
|
assert_eq!(manual_season_search_context_clues_iter.next(), None);
|
||||||
@@ -348,21 +370,16 @@ mod tests {
|
|||||||
|
|
||||||
let (key_binding, description) = manual_episode_search_context_clues_iter.next().unwrap();
|
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_eq!(*key_binding, DEFAULT_KEYBINDINGS.esc);
|
||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||||
assert_eq!(manual_episode_search_context_clues_iter.next(), None);
|
assert_eq!(manual_episode_search_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn details_contextual_context_clues() {
|
|
||||||
let mut manual_search_contextual_context_clues_iter = DETAILS_CONTEXTUAL_CONTEXT_CLUES.iter();
|
|
||||||
let (key_binding, description) = manual_search_contextual_context_clues_iter.next().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(*key_binding, DEFAULT_KEYBINDINGS.submit);
|
|
||||||
assert_str_eq!(*description, "details");
|
|
||||||
assert_eq!(manual_search_contextual_context_clues_iter.next(), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_episode_details_context_clues() {
|
fn test_episode_details_context_clues() {
|
||||||
let mut episode_details_context_clues_iter = EPISODE_DETAILS_CONTEXT_CLUES.iter();
|
let mut episode_details_context_clues_iter = EPISODE_DETAILS_CONTEXT_CLUES.iter();
|
||||||
@@ -384,6 +401,32 @@ mod tests {
|
|||||||
assert_eq!(episode_details_context_clues_iter.next(), None);
|
assert_eq!(episode_details_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_tasks_context_clues() {
|
fn test_system_tasks_context_clues() {
|
||||||
let mut system_tasks_context_clues_iter = SYSTEM_TASKS_CONTEXT_CLUES.iter();
|
let mut system_tasks_context_clues_iter = SYSTEM_TASKS_CONTEXT_CLUES.iter();
|
||||||
@@ -399,4 +442,258 @@ mod tests {
|
|||||||
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
assert_str_eq!(*description, DEFAULT_KEYBINDINGS.esc.desc);
|
||||||
assert_eq!(system_tasks_context_clues_iter.next(), None);
|
assert_eq!(system_tasks_context_clues_iter.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(
|
||||||
|
expected = "SonarrContextClueProvider::get_context_clues called with non-Sonarr route"
|
||||||
|
)]
|
||||||
|
fn test_sonarr_context_clue_provider_get_context_clues_non_sonarr_route() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::default().into());
|
||||||
|
|
||||||
|
// This should panic because the route is not a Sonarr route
|
||||||
|
SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveSonarrBlock::SeriesDetails, &SERIES_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(1, ActiveSonarrBlock::SeriesHistory, &SERIES_HISTORY_CONTEXT_CLUES)]
|
||||||
|
fn test_sonarr_context_clue_provider_series_info_tabs(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
#[case] expected_context_clues: &[ContextClue],
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.sonarr_data = SonarrData::default();
|
||||||
|
app.data.sonarr_data.series_info_tabs.set_index(index);
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(expected_context_clues, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveSonarrBlock::SeasonDetails, &SEASON_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(1, ActiveSonarrBlock::SeasonHistory, &SEASON_HISTORY_CONTEXT_CLUES)]
|
||||||
|
#[case(2, ActiveSonarrBlock::ManualSeasonSearch, &MANUAL_SEASON_SEARCH_CONTEXT_CLUES)]
|
||||||
|
fn test_sonarr_context_clue_provider_season_details_tabs(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
#[case] expected_context_clues: &[ContextClue],
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
let mut season_details_modal = SeasonDetailsModal::default();
|
||||||
|
season_details_modal.season_details_tabs.set_index(index);
|
||||||
|
let sonarr_data = SonarrData {
|
||||||
|
season_details_modal: Some(season_details_modal),
|
||||||
|
..SonarrData::default()
|
||||||
|
};
|
||||||
|
app.data.sonarr_data = sonarr_data;
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(expected_context_clues, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveSonarrBlock::EpisodeDetails, &EPISODE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(1, ActiveSonarrBlock::EpisodeHistory, &SELECTABLE_EPISODE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(2, ActiveSonarrBlock::EpisodeFile, &EPISODE_DETAILS_CONTEXT_CLUES)]
|
||||||
|
#[case(3, ActiveSonarrBlock::ManualEpisodeSearch, &MANUAL_EPISODE_SEARCH_CONTEXT_CLUES)]
|
||||||
|
fn test_sonarr_context_clue_provider_episode_details_tabs(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
#[case] expected_context_clues: &[ContextClue],
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
let mut episode_details_modal = EpisodeDetailsModal::default();
|
||||||
|
episode_details_modal.episode_details_tabs.set_index(index);
|
||||||
|
let sonarr_data = SonarrData {
|
||||||
|
season_details_modal: Some(SeasonDetailsModal {
|
||||||
|
episode_details_modal: Some(episode_details_modal),
|
||||||
|
..SeasonDetailsModal::default()
|
||||||
|
}),
|
||||||
|
..SonarrData::default()
|
||||||
|
};
|
||||||
|
app.data.sonarr_data = sonarr_data;
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(expected_context_clues, context_clues.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_context_clue_provider_bare_popup_context_clues(
|
||||||
|
#[values(
|
||||||
|
ActiveSonarrBlock::TestAllIndexers,
|
||||||
|
ActiveSonarrBlock::AddSeriesSearchInput,
|
||||||
|
ActiveSonarrBlock::AddSeriesEmptySearchResults,
|
||||||
|
ActiveSonarrBlock::SystemLogs,
|
||||||
|
ActiveSonarrBlock::SystemUpdates
|
||||||
|
)]
|
||||||
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(context_clues.unwrap(), &BARE_POPUP_CONTEXT_CLUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_context_clue_provider_confirmation_prompt_context_clues(
|
||||||
|
#[values(
|
||||||
|
ActiveSonarrBlock::AddSeriesPrompt,
|
||||||
|
ActiveSonarrBlock::AddSeriesSelectMonitor,
|
||||||
|
ActiveSonarrBlock::AddSeriesSelectSeriesType,
|
||||||
|
ActiveSonarrBlock::AddSeriesSelectQualityProfile,
|
||||||
|
ActiveSonarrBlock::AddSeriesSelectLanguageProfile,
|
||||||
|
ActiveSonarrBlock::AddSeriesSelectRootFolder,
|
||||||
|
ActiveSonarrBlock::AddSeriesTagsInput,
|
||||||
|
ActiveSonarrBlock::SystemTaskStartConfirmPrompt
|
||||||
|
)]
|
||||||
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_context_clue_provider_confirmation_prompt_popup_clues_edit_indexer_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveSonarrBlock::EditIndexerPrompt,
|
||||||
|
ActiveSonarrBlock::EditIndexerConfirmPrompt,
|
||||||
|
ActiveSonarrBlock::EditIndexerApiKeyInput,
|
||||||
|
ActiveSonarrBlock::EditIndexerNameInput,
|
||||||
|
ActiveSonarrBlock::EditIndexerSeedRatioInput,
|
||||||
|
ActiveSonarrBlock::EditIndexerToggleEnableRss,
|
||||||
|
ActiveSonarrBlock::EditIndexerToggleEnableAutomaticSearch,
|
||||||
|
ActiveSonarrBlock::EditIndexerToggleEnableInteractiveSearch,
|
||||||
|
ActiveSonarrBlock::EditIndexerPriorityInput,
|
||||||
|
ActiveSonarrBlock::EditIndexerUrlInput,
|
||||||
|
ActiveSonarrBlock::EditIndexerTagsInput
|
||||||
|
)]
|
||||||
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_context_clue_provider_confirmation_prompt_popup_clues_indexer_settings_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveSonarrBlock::AllIndexerSettingsPrompt,
|
||||||
|
ActiveSonarrBlock::IndexerSettingsConfirmPrompt,
|
||||||
|
ActiveSonarrBlock::IndexerSettingsMaximumSizeInput,
|
||||||
|
ActiveSonarrBlock::IndexerSettingsMinimumAgeInput,
|
||||||
|
ActiveSonarrBlock::IndexerSettingsRetentionInput,
|
||||||
|
ActiveSonarrBlock::IndexerSettingsRssSyncIntervalInput
|
||||||
|
)]
|
||||||
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_context_clue_provider_confirmation_prompt_popup_clues_edit_series_blocks(
|
||||||
|
#[values(
|
||||||
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
|
ActiveSonarrBlock::EditSeriesConfirmPrompt,
|
||||||
|
ActiveSonarrBlock::EditSeriesPathInput,
|
||||||
|
ActiveSonarrBlock::EditSeriesSelectSeriesType,
|
||||||
|
ActiveSonarrBlock::EditSeriesSelectQualityProfile,
|
||||||
|
ActiveSonarrBlock::EditSeriesSelectLanguageProfile,
|
||||||
|
ActiveSonarrBlock::EditSeriesTagsInput,
|
||||||
|
ActiveSonarrBlock::EditSeriesToggleMonitored,
|
||||||
|
ActiveSonarrBlock::EditSeriesToggleSeasonFolder
|
||||||
|
)]
|
||||||
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(context_clues.unwrap(), &CONFIRMATION_PROMPT_CONTEXT_CLUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_context_clue_provider_add_series_search_results_clues(
|
||||||
|
#[values(
|
||||||
|
ActiveSonarrBlock::AddSeriesAlreadyInLibrary,
|
||||||
|
ActiveSonarrBlock::AddSeriesSearchResults
|
||||||
|
)]
|
||||||
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sonarr_context_clue_provider_system_tasks_clues() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveSonarrBlock::Series, &SERIES_CONTEXT_CLUES)]
|
||||||
|
#[case(1, ActiveSonarrBlock::Downloads, &DOWNLOADS_CONTEXT_CLUES)]
|
||||||
|
#[case(2, ActiveSonarrBlock::Blocklist, &BLOCKLIST_CONTEXT_CLUES)]
|
||||||
|
#[case(3, ActiveSonarrBlock::History, &HISTORY_CONTEXT_CLUES)]
|
||||||
|
#[case(4, ActiveSonarrBlock::RootFolders, &ROOT_FOLDERS_CONTEXT_CLUES)]
|
||||||
|
#[case(5, ActiveSonarrBlock::Indexers, &INDEXERS_CONTEXT_CLUES)]
|
||||||
|
#[case(6, ActiveSonarrBlock::System, &SYSTEM_CONTEXT_CLUES)]
|
||||||
|
fn test_sonarr_context_clue_provider_sonarr_tabs(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] active_sonarr_block: ActiveSonarrBlock,
|
||||||
|
#[case] expected_context_clues: &[ContextClue],
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.sonarr_data = SonarrData::default();
|
||||||
|
app.data.sonarr_data.main_tabs.set_index(index);
|
||||||
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
|
let context_clues = SonarrContextClueProvider::get_context_clues(&mut app);
|
||||||
|
|
||||||
|
assert!(context_clues.is_some());
|
||||||
|
assert_eq!(expected_context_clues, context_clues.unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
@@ -185,7 +185,7 @@ mod tests {
|
|||||||
async fn test_dispatch_by_manual_season_search_block_is_loading() {
|
async fn test_dispatch_by_manual_season_search_block_is_loading() {
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app
|
app
|
||||||
@@ -199,7 +199,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_dispatch_by_manual_season_search_block_season_releases_non_empty() {
|
async fn test_dispatch_by_manual_season_search_block_season_releases_non_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut season_details_modal = SeasonDetailsModal::default();
|
let mut season_details_modal = SeasonDetailsModal::default();
|
||||||
season_details_modal
|
season_details_modal
|
||||||
.season_releases
|
.season_releases
|
||||||
@@ -304,7 +304,7 @@ mod tests {
|
|||||||
async fn test_dispatch_by_manual_episode_search_block_is_loading() {
|
async fn test_dispatch_by_manual_episode_search_block_is_loading() {
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
|
|
||||||
app
|
app
|
||||||
@@ -318,7 +318,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_dispatch_by_manual_episode_search_block_episode_releases_non_empty() {
|
async fn test_dispatch_by_manual_episode_search_block_episode_releases_non_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut episode_details_modal = EpisodeDetailsModal::default();
|
let mut episode_details_modal = EpisodeDetailsModal::default();
|
||||||
episode_details_modal
|
episode_details_modal
|
||||||
.episode_releases
|
.episode_releases
|
||||||
@@ -366,7 +366,7 @@ mod tests {
|
|||||||
assert!(app.is_loading);
|
assert!(app.is_loading);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
assert_eq!(app.tick_count, 0);
|
assert_eq!(app.tick_count, 0);
|
||||||
@@ -554,7 +554,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_check_for_sonarr_prompt_action_no_prompt_confirm() {
|
async fn test_check_for_sonarr_prompt_action_no_prompt_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.prompt_confirm = false;
|
app.data.sonarr_data.prompt_confirm = false;
|
||||||
|
|
||||||
app.check_for_sonarr_prompt_action().await;
|
app.check_for_sonarr_prompt_action().await;
|
||||||
@@ -604,7 +604,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
@@ -642,7 +642,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
@@ -667,7 +667,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -692,7 +692,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
@@ -709,7 +709,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(app.is_loading);
|
assert!(app.is_loading);
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
@@ -743,14 +743,14 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
SonarrEvent::GetDownloads.into()
|
SonarrEvent::GetDownloads(500).into()
|
||||||
);
|
);
|
||||||
assert!(app.is_loading);
|
assert!(app.is_loading);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_populate_seasons_table_unfiltered() {
|
async fn test_populate_seasons_table_unfiltered() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.series.set_items(vec![Series {
|
app.data.sonarr_data.series.set_items(vec![Series {
|
||||||
seasons: Some(vec![Season::default()]),
|
seasons: Some(vec![Season::default()]),
|
||||||
..Series::default()
|
..Series::default()
|
||||||
@@ -770,7 +770,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_populate_seasons_table_filtered() {
|
async fn test_populate_seasons_table_filtered() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.series.set_filtered_items(vec![Series {
|
app.data.sonarr_data.series.set_filtered_items(vec![Series {
|
||||||
seasons: Some(vec![Season::default()]),
|
seasons: Some(vec![Season::default()]),
|
||||||
..Series::default()
|
..Series::default()
|
||||||
@@ -790,7 +790,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_episode_id() {
|
async fn test_extract_episode_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut season_details_modal = SeasonDetailsModal::default();
|
let mut season_details_modal = SeasonDetailsModal::default();
|
||||||
season_details_modal.episodes.set_items(vec![Episode {
|
season_details_modal.episodes.set_items(vec![Episode {
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -804,14 +804,14 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[should_panic(expected = "Season details have not been loaded")]
|
#[should_panic(expected = "Season details have not been loaded")]
|
||||||
async fn test_extract_episode_id_requires_season_details_modal_to_be_some() {
|
async fn test_extract_episode_id_requires_season_details_modal_to_be_some() {
|
||||||
let app = App::default();
|
let app = App::test_default();
|
||||||
|
|
||||||
assert_eq!(app.extract_episode_id().await, 0);
|
assert_eq!(app.extract_episode_id().await, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_series_id() {
|
async fn test_extract_series_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.series.set_items(vec![Series {
|
app.data.sonarr_data.series.set_items(vec![Series {
|
||||||
id: 1,
|
id: 1,
|
||||||
..Series::default()
|
..Series::default()
|
||||||
@@ -822,7 +822,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_series_id_season_number_tuple() {
|
async fn test_extract_series_id_season_number_tuple() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.series.set_items(vec![Series {
|
app.data.sonarr_data.series.set_items(vec![Series {
|
||||||
id: 1,
|
id: 1,
|
||||||
..Series::default()
|
..Series::default()
|
||||||
@@ -837,7 +837,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_add_new_series_search_query() {
|
async fn test_extract_add_new_series_search_query() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.add_series_search = Some("test search".into());
|
app.data.sonarr_data.add_series_search = Some("test search".into());
|
||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
@@ -849,14 +849,14 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[should_panic(expected = "Add series search is empty")]
|
#[should_panic(expected = "Add series search is empty")]
|
||||||
async fn test_extract_add_new_series_search_query_panics_when_the_query_is_not_set() {
|
async fn test_extract_add_new_series_search_query_panics_when_the_query_is_not_set() {
|
||||||
let app = App::default();
|
let app = App::test_default();
|
||||||
|
|
||||||
app.extract_add_new_series_search_query().await;
|
app.extract_add_new_series_search_query().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_extract_sonarr_indexer_id() {
|
async fn test_extract_sonarr_indexer_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.indexers.set_items(vec![Indexer {
|
app.data.sonarr_data.indexers.set_items(vec![Indexer {
|
||||||
id: 1,
|
id: 1,
|
||||||
..Indexer::default()
|
..Indexer::default()
|
||||||
@@ -871,7 +871,7 @@ mod tests {
|
|||||||
network_tx: Some(sync_network_tx),
|
network_tx: Some(sync_network_tx),
|
||||||
tick_count: 1,
|
tick_count: 1,
|
||||||
is_first_render: false,
|
is_first_render: false,
|
||||||
..App::default()
|
..App::test_default()
|
||||||
};
|
};
|
||||||
app.data.sonarr_data.prompt_confirm = true;
|
app.data.sonarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let clear_blocklist_command = RadarrCommand::ClearBlocklist.into();
|
let clear_blocklist_command = RadarrCommand::ClearBlocklist.into();
|
||||||
|
|
||||||
let result = handle_command(&app_arc, clear_blocklist_command, &mut mock_network).await;
|
let result = handle_command(&app_arc, clear_blocklist_command, &mut mock_network).await;
|
||||||
@@ -167,7 +167,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let clear_blocklist_command = SonarrCommand::ClearBlocklist.into();
|
let clear_blocklist_command = SonarrCommand::ClearBlocklist.into();
|
||||||
|
|
||||||
let result = handle_command(&app_arc, clear_blocklist_command, &mut mock_network).await;
|
let result = handle_command(&app_arc, clear_blocklist_command, &mut mock_network).await;
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_movie_command = RadarrAddCommand::Movie {
|
let add_movie_command = RadarrAddCommand::Movie {
|
||||||
tmdb_id: 1,
|
tmdb_id: 1,
|
||||||
root_folder_path: "/test".to_owned(),
|
root_folder_path: "/test".to_owned(),
|
||||||
@@ -437,7 +437,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_root_folder_command = RadarrAddCommand::RootFolder {
|
let add_root_folder_command = RadarrAddCommand::RootFolder {
|
||||||
root_folder_path: expected_root_folder_path,
|
root_folder_path: expected_root_folder_path,
|
||||||
};
|
};
|
||||||
@@ -465,7 +465,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_tag_command = RadarrAddCommand::Tag {
|
let add_tag_command = RadarrAddCommand::Tag {
|
||||||
name: expected_tag_name,
|
name: expected_tag_name,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_blocklist_item_command = RadarrDeleteCommand::BlocklistItem {
|
let delete_blocklist_item_command = RadarrDeleteCommand::BlocklistItem {
|
||||||
blocklist_item_id: 1,
|
blocklist_item_id: 1,
|
||||||
};
|
};
|
||||||
@@ -307,7 +307,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_download_command = RadarrDeleteCommand::Download { download_id: 1 };
|
let delete_download_command = RadarrDeleteCommand::Download { download_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -333,7 +333,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_indexer_command = RadarrDeleteCommand::Indexer { indexer_id: 1 };
|
let delete_indexer_command = RadarrDeleteCommand::Indexer { indexer_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -363,7 +363,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_movie_command = RadarrDeleteCommand::Movie {
|
let delete_movie_command = RadarrDeleteCommand::Movie {
|
||||||
movie_id: 1,
|
movie_id: 1,
|
||||||
delete_files_from_disk: true,
|
delete_files_from_disk: true,
|
||||||
@@ -393,7 +393,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_root_folder_command = RadarrDeleteCommand::RootFolder { root_folder_id: 1 };
|
let delete_root_folder_command = RadarrDeleteCommand::RootFolder { root_folder_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -419,7 +419,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_tag_command = RadarrDeleteCommand::Tag { tag_id: 1 };
|
let delete_tag_command = RadarrDeleteCommand::Tag { tag_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
|||||||
@@ -379,13 +379,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrEditCommand> for RadarrEditCommandH
|
|||||||
rss_sync_interval: rss_sync_interval
|
rss_sync_interval: rss_sync_interval
|
||||||
.unwrap_or(previous_indexer_settings.rss_sync_interval),
|
.unwrap_or(previous_indexer_settings.rss_sync_interval),
|
||||||
whitelisted_hardcoded_subs: whitelisted_subtitle_tags
|
whitelisted_hardcoded_subs: whitelisted_subtitle_tags
|
||||||
.clone()
|
.unwrap_or(previous_indexer_settings.whitelisted_hardcoded_subs.text)
|
||||||
.unwrap_or_else(|| {
|
|
||||||
previous_indexer_settings
|
|
||||||
.whitelisted_hardcoded_subs
|
|
||||||
.text
|
|
||||||
.clone()
|
|
||||||
})
|
|
||||||
.into(),
|
.into(),
|
||||||
};
|
};
|
||||||
self
|
self
|
||||||
|
|||||||
@@ -865,7 +865,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_all_indexer_settings_command = RadarrEditCommand::AllIndexerSettings {
|
let edit_all_indexer_settings_command = RadarrEditCommand::AllIndexerSettings {
|
||||||
allow_hardcoded_subs: true,
|
allow_hardcoded_subs: true,
|
||||||
disable_allow_hardcoded_subs: false,
|
disable_allow_hardcoded_subs: false,
|
||||||
@@ -936,7 +936,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_all_indexer_settings_command = RadarrEditCommand::AllIndexerSettings {
|
let edit_all_indexer_settings_command = RadarrEditCommand::AllIndexerSettings {
|
||||||
allow_hardcoded_subs: false,
|
allow_hardcoded_subs: false,
|
||||||
disable_allow_hardcoded_subs: true,
|
disable_allow_hardcoded_subs: true,
|
||||||
@@ -1008,7 +1008,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_all_indexer_settings_command = RadarrEditCommand::AllIndexerSettings {
|
let edit_all_indexer_settings_command = RadarrEditCommand::AllIndexerSettings {
|
||||||
allow_hardcoded_subs: false,
|
allow_hardcoded_subs: false,
|
||||||
disable_allow_hardcoded_subs: false,
|
disable_allow_hardcoded_subs: false,
|
||||||
@@ -1055,7 +1055,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_collection_command = RadarrEditCommand::Collection {
|
let edit_collection_command = RadarrEditCommand::Collection {
|
||||||
collection_id: 1,
|
collection_id: 1,
|
||||||
enable_monitoring: true,
|
enable_monitoring: true,
|
||||||
@@ -1097,7 +1097,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_collection_command = RadarrEditCommand::Collection {
|
let edit_collection_command = RadarrEditCommand::Collection {
|
||||||
collection_id: 1,
|
collection_id: 1,
|
||||||
enable_monitoring: false,
|
enable_monitoring: false,
|
||||||
@@ -1139,7 +1139,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_collection_command = RadarrEditCommand::Collection {
|
let edit_collection_command = RadarrEditCommand::Collection {
|
||||||
collection_id: 1,
|
collection_id: 1,
|
||||||
enable_monitoring: false,
|
enable_monitoring: false,
|
||||||
@@ -1187,7 +1187,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_indexer_command = RadarrEditCommand::Indexer {
|
let edit_indexer_command = RadarrEditCommand::Indexer {
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
name: Some("Test".to_owned()),
|
name: Some("Test".to_owned()),
|
||||||
@@ -1241,7 +1241,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_indexer_command = RadarrEditCommand::Indexer {
|
let edit_indexer_command = RadarrEditCommand::Indexer {
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
name: Some("Test".to_owned()),
|
name: Some("Test".to_owned()),
|
||||||
@@ -1295,7 +1295,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_indexer_command = RadarrEditCommand::Indexer {
|
let edit_indexer_command = RadarrEditCommand::Indexer {
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
name: Some("Test".to_owned()),
|
name: Some("Test".to_owned()),
|
||||||
@@ -1345,7 +1345,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_movie_command = RadarrEditCommand::Movie {
|
let edit_movie_command = RadarrEditCommand::Movie {
|
||||||
movie_id: 1,
|
movie_id: 1,
|
||||||
enable_monitoring: true,
|
enable_monitoring: true,
|
||||||
@@ -1388,7 +1388,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_movie_command = RadarrEditCommand::Movie {
|
let edit_movie_command = RadarrEditCommand::Movie {
|
||||||
movie_id: 1,
|
movie_id: 1,
|
||||||
enable_monitoring: false,
|
enable_monitoring: false,
|
||||||
@@ -1431,7 +1431,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_movie_command = RadarrEditCommand::Movie {
|
let edit_movie_command = RadarrEditCommand::Movie {
|
||||||
movie_id: 1,
|
movie_id: 1,
|
||||||
enable_monitoring: false,
|
enable_monitoring: false,
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_all_indexer_settings_command = RadarrGetCommand::AllIndexerSettings;
|
let get_all_indexer_settings_command = RadarrGetCommand::AllIndexerSettings;
|
||||||
|
|
||||||
let result = RadarrGetCommandHandler::with(
|
let result = RadarrGetCommandHandler::with(
|
||||||
@@ -164,7 +164,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_host_config_command = RadarrGetCommand::HostConfig;
|
let get_host_config_command = RadarrGetCommand::HostConfig;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -190,7 +190,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_movie_details_command = RadarrGetCommand::MovieDetails { movie_id: 1 };
|
let get_movie_details_command = RadarrGetCommand::MovieDetails { movie_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -216,7 +216,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_movie_history_command = RadarrGetCommand::MovieHistory { movie_id: 1 };
|
let get_movie_history_command = RadarrGetCommand::MovieHistory { movie_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -239,7 +239,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_security_config_command = RadarrGetCommand::SecurityConfig;
|
let get_security_config_command = RadarrGetCommand::SecurityConfig;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -262,7 +262,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_system_status_command = RadarrGetCommand::SystemStatus;
|
let get_system_status_command = RadarrGetCommand::SystemStatus;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ pub enum RadarrListCommand {
|
|||||||
#[command(about = "List all Radarr collections")]
|
#[command(about = "List all Radarr collections")]
|
||||||
Collections,
|
Collections,
|
||||||
#[command(about = "List all active downloads in Radarr")]
|
#[command(about = "List all active downloads in Radarr")]
|
||||||
Downloads,
|
Downloads {
|
||||||
|
#[arg(long, help = "How many downloads to fetch", default_value_t = 500)]
|
||||||
|
count: u64,
|
||||||
|
},
|
||||||
#[command(about = "List disk space details for all provisioned root folders in Radarr")]
|
#[command(about = "List disk space details for all provisioned root folders in Radarr")]
|
||||||
DiskSpace,
|
DiskSpace,
|
||||||
#[command(about = "List all Radarr indexers")]
|
#[command(about = "List all Radarr indexers")]
|
||||||
@@ -104,10 +107,10 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrListCommand> for RadarrListCommandH
|
|||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
RadarrListCommand::Downloads => {
|
RadarrListCommand::Downloads { count } => {
|
||||||
let resp = self
|
let resp = self
|
||||||
.network
|
.network
|
||||||
.handle_network_event(RadarrEvent::GetDownloads.into())
|
.handle_network_event(RadarrEvent::GetDownloads(count).into())
|
||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
@@ -135,9 +138,9 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrListCommand> for RadarrListCommandH
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if output_in_log_format {
|
if output_in_log_format {
|
||||||
let log_lines = self.app.lock().await.data.radarr_data.logs.items.clone();
|
let log_lines = &self.app.lock().await.data.radarr_data.logs.items;
|
||||||
|
|
||||||
serde_json::to_string_pretty(&log_lines)?
|
serde_json::to_string_pretty(log_lines)?
|
||||||
} else {
|
} else {
|
||||||
serde_json::to_string_pretty(&logs)?
|
serde_json::to_string_pretty(&logs)?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ mod tests {
|
|||||||
#[values(
|
#[values(
|
||||||
"blocklist",
|
"blocklist",
|
||||||
"collections",
|
"collections",
|
||||||
"downloads",
|
|
||||||
"disk-space",
|
"disk-space",
|
||||||
"indexers",
|
"indexers",
|
||||||
"movies",
|
"movies",
|
||||||
@@ -59,6 +58,15 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_downloads_count_flag_requires_arguments() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "radarr", "list", "downloads", "--count"]);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_logs_events_flag_requires_arguments() {
|
fn test_list_logs_events_flag_requires_arguments() {
|
||||||
let result =
|
let result =
|
||||||
@@ -87,6 +95,18 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_downloads_default_values() {
|
||||||
|
let expected_args = RadarrListCommand::Downloads { count: 500 };
|
||||||
|
let result = Cli::try_parse_from(["managarr", "radarr", "list", "downloads"]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
if let Some(Command::Radarr(RadarrCommand::List(refresh_command))) = result.unwrap().command {
|
||||||
|
assert_eq!(refresh_command, expected_args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_logs_default_values() {
|
fn test_list_logs_default_values() {
|
||||||
let expected_args = RadarrListCommand::Logs {
|
let expected_args = RadarrListCommand::Logs {
|
||||||
@@ -122,7 +142,6 @@ mod tests {
|
|||||||
#[rstest]
|
#[rstest]
|
||||||
#[case(RadarrListCommand::Blocklist, RadarrEvent::GetBlocklist)]
|
#[case(RadarrListCommand::Blocklist, RadarrEvent::GetBlocklist)]
|
||||||
#[case(RadarrListCommand::Collections, RadarrEvent::GetCollections)]
|
#[case(RadarrListCommand::Collections, RadarrEvent::GetCollections)]
|
||||||
#[case(RadarrListCommand::Downloads, RadarrEvent::GetDownloads)]
|
|
||||||
#[case(RadarrListCommand::DiskSpace, RadarrEvent::GetDiskSpace)]
|
#[case(RadarrListCommand::DiskSpace, RadarrEvent::GetDiskSpace)]
|
||||||
#[case(RadarrListCommand::Indexers, RadarrEvent::GetIndexers)]
|
#[case(RadarrListCommand::Indexers, RadarrEvent::GetIndexers)]
|
||||||
#[case(RadarrListCommand::Movies, RadarrEvent::GetMovies)]
|
#[case(RadarrListCommand::Movies, RadarrEvent::GetMovies)]
|
||||||
@@ -147,7 +166,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
|
||||||
let result = RadarrListCommandHandler::with(&app_arc, list_command, &mut mock_network)
|
let result = RadarrListCommandHandler::with(&app_arc, list_command, &mut mock_network)
|
||||||
.handle()
|
.handle()
|
||||||
@@ -171,7 +190,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_movie_credits_command = RadarrListCommand::MovieCredits { movie_id: 1 };
|
let list_movie_credits_command = RadarrListCommand::MovieCredits { movie_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -182,6 +201,32 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_list_downloads_command() {
|
||||||
|
let expected_count = 1000;
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
RadarrEvent::GetDownloads(expected_count).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Radarr(RadarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let list_downloads_command = RadarrListCommand::Downloads { count: 1000 };
|
||||||
|
|
||||||
|
let result =
|
||||||
|
RadarrListCommandHandler::with(&app_arc, list_downloads_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_list_logs_command() {
|
async fn test_handle_list_logs_command() {
|
||||||
let expected_events = 1000;
|
let expected_events = 1000;
|
||||||
@@ -197,7 +242,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_logs_command = RadarrListCommand::Logs {
|
let list_logs_command = RadarrListCommand::Logs {
|
||||||
events: 1000,
|
events: 1000,
|
||||||
output_in_log_format: false,
|
output_in_log_format: false,
|
||||||
|
|||||||
@@ -118,6 +118,17 @@ pub enum RadarrCommand {
|
|||||||
},
|
},
|
||||||
#[command(about = "Test all Radarr indexers")]
|
#[command(about = "Test all Radarr indexers")]
|
||||||
TestAllIndexers,
|
TestAllIndexers,
|
||||||
|
#[command(
|
||||||
|
about = "Toggle monitoring for the specified movie corresponding to the given movie ID"
|
||||||
|
)]
|
||||||
|
ToggleMovieMonitoring {
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
help = "The Radarr ID of the movie to toggle monitoring on",
|
||||||
|
required = true
|
||||||
|
)]
|
||||||
|
movie_id: i64,
|
||||||
|
},
|
||||||
#[command(about = "Trigger an automatic search for the movie with the specified ID")]
|
#[command(about = "Trigger an automatic search for the movie with the specified ID")]
|
||||||
TriggerAutomaticSearch {
|
TriggerAutomaticSearch {
|
||||||
#[arg(
|
#[arg(
|
||||||
@@ -250,6 +261,13 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrCommand> for RadarrCliHandler<'a, '
|
|||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
|
RadarrCommand::ToggleMovieMonitoring { movie_id } => {
|
||||||
|
let resp = self
|
||||||
|
.network
|
||||||
|
.handle_network_event(RadarrEvent::ToggleMovieMonitoring(movie_id).into())
|
||||||
|
.await?;
|
||||||
|
serde_json::to_string_pretty(&resp)?
|
||||||
|
}
|
||||||
RadarrCommand::TriggerAutomaticSearch { movie_id } => {
|
RadarrCommand::TriggerAutomaticSearch { movie_id } => {
|
||||||
let resp = self
|
let resp = self
|
||||||
.network
|
.network
|
||||||
|
|||||||
@@ -215,6 +215,31 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toggle_movie_monitoring_requires_movie_id() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "radarr", "toggle-movie-monitoring"]);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert_eq!(
|
||||||
|
result.unwrap_err().kind(),
|
||||||
|
ErrorKind::MissingRequiredArgument
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toggle_movie_monitoring_requirements_satisfied() {
|
||||||
|
let result = Cli::command().try_get_matches_from([
|
||||||
|
"managarr",
|
||||||
|
"radarr",
|
||||||
|
"toggle-movie-monitoring",
|
||||||
|
"--movie-id",
|
||||||
|
"1",
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trigger_automatic_search_requires_movie_id() {
|
fn test_trigger_automatic_search_requires_movie_id() {
|
||||||
let result =
|
let result =
|
||||||
@@ -292,7 +317,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let clear_blocklist_command = RadarrCommand::ClearBlocklist;
|
let clear_blocklist_command = RadarrCommand::ClearBlocklist;
|
||||||
|
|
||||||
let result = RadarrCliHandler::with(&app_arc, clear_blocklist_command, &mut mock_network)
|
let result = RadarrCliHandler::with(&app_arc, clear_blocklist_command, &mut mock_network)
|
||||||
@@ -321,7 +346,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let download_release_command = RadarrCommand::DownloadRelease {
|
let download_release_command = RadarrCommand::DownloadRelease {
|
||||||
guid: "guid".to_owned(),
|
guid: "guid".to_owned(),
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
@@ -350,7 +375,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let manual_search_command = RadarrCommand::ManualSearch { movie_id: 1 };
|
let manual_search_command = RadarrCommand::ManualSearch { movie_id: 1 };
|
||||||
|
|
||||||
let result = RadarrCliHandler::with(&app_arc, manual_search_command, &mut mock_network)
|
let result = RadarrCliHandler::with(&app_arc, manual_search_command, &mut mock_network)
|
||||||
@@ -375,7 +400,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let search_new_movie_command = RadarrCommand::SearchNewMovie {
|
let search_new_movie_command = RadarrCommand::SearchNewMovie {
|
||||||
query: "halo".to_owned(),
|
query: "halo".to_owned(),
|
||||||
};
|
};
|
||||||
@@ -402,7 +427,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let start_task_command = RadarrCommand::StartTask {
|
let start_task_command = RadarrCommand::StartTask {
|
||||||
task_name: RadarrTaskName::ApplicationCheckUpdate,
|
task_name: RadarrTaskName::ApplicationCheckUpdate,
|
||||||
};
|
};
|
||||||
@@ -429,7 +454,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let test_indexer_command = RadarrCommand::TestIndexer { indexer_id: 1 };
|
let test_indexer_command = RadarrCommand::TestIndexer { indexer_id: 1 };
|
||||||
|
|
||||||
let result = RadarrCliHandler::with(&app_arc, test_indexer_command, &mut mock_network)
|
let result = RadarrCliHandler::with(&app_arc, test_indexer_command, &mut mock_network)
|
||||||
@@ -451,7 +476,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let test_all_indexers_command = RadarrCommand::TestAllIndexers;
|
let test_all_indexers_command = RadarrCommand::TestAllIndexers;
|
||||||
|
|
||||||
let result = RadarrCliHandler::with(&app_arc, test_all_indexers_command, &mut mock_network)
|
let result = RadarrCliHandler::with(&app_arc, test_all_indexers_command, &mut mock_network)
|
||||||
@@ -461,6 +486,32 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_toggle_movie_monitoring_command() {
|
||||||
|
let expected_movie_id = 1;
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
RadarrEvent::ToggleMovieMonitoring(expected_movie_id).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Radarr(RadarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let toggle_movie_monitoring_command = RadarrCommand::ToggleMovieMonitoring { movie_id: 1 };
|
||||||
|
|
||||||
|
let result =
|
||||||
|
RadarrCliHandler::with(&app_arc, toggle_movie_monitoring_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_trigger_automatic_search_command() {
|
async fn test_trigger_automatic_search_command() {
|
||||||
let expected_movie_id = 1;
|
let expected_movie_id = 1;
|
||||||
@@ -476,7 +527,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let trigger_automatic_search_command = RadarrCommand::TriggerAutomaticSearch { movie_id: 1 };
|
let trigger_automatic_search_command = RadarrCommand::TriggerAutomaticSearch { movie_id: 1 };
|
||||||
|
|
||||||
let result = RadarrCliHandler::with(
|
let result = RadarrCliHandler::with(
|
||||||
@@ -505,7 +556,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_tag_command = RadarrCommand::Add(RadarrAddCommand::Tag {
|
let add_tag_command = RadarrCommand::Add(RadarrAddCommand::Tag {
|
||||||
name: expected_tag_name,
|
name: expected_tag_name,
|
||||||
});
|
});
|
||||||
@@ -532,7 +583,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_blocklist_item_command =
|
let delete_blocklist_item_command =
|
||||||
RadarrCommand::Delete(RadarrDeleteCommand::BlocklistItem {
|
RadarrCommand::Delete(RadarrDeleteCommand::BlocklistItem {
|
||||||
blocklist_item_id: 1,
|
blocklist_item_id: 1,
|
||||||
@@ -592,7 +643,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_all_indexer_settings_command =
|
let edit_all_indexer_settings_command =
|
||||||
RadarrCommand::Edit(RadarrEditCommand::AllIndexerSettings {
|
RadarrCommand::Edit(RadarrEditCommand::AllIndexerSettings {
|
||||||
allow_hardcoded_subs: true,
|
allow_hardcoded_subs: true,
|
||||||
@@ -632,7 +683,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_all_indexer_settings_command =
|
let get_all_indexer_settings_command =
|
||||||
RadarrCommand::Get(RadarrGetCommand::AllIndexerSettings);
|
RadarrCommand::Get(RadarrGetCommand::AllIndexerSettings);
|
||||||
|
|
||||||
@@ -662,7 +713,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_movie_credits_command =
|
let list_movie_credits_command =
|
||||||
RadarrCommand::List(RadarrListCommand::MovieCredits { movie_id: 1 });
|
RadarrCommand::List(RadarrListCommand::MovieCredits { movie_id: 1 });
|
||||||
|
|
||||||
@@ -688,7 +739,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let refresh_movie_command =
|
let refresh_movie_command =
|
||||||
RadarrCommand::Refresh(RadarrRefreshCommand::Movie { movie_id: 1 });
|
RadarrCommand::Refresh(RadarrRefreshCommand::Movie { movie_id: 1 });
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
|
||||||
let result = RadarrRefreshCommandHandler::with(&app_arc, refresh_command, &mut mock_network)
|
let result = RadarrRefreshCommandHandler::with(&app_arc, refresh_command, &mut mock_network)
|
||||||
.handle()
|
.handle()
|
||||||
@@ -120,7 +120,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let refresh_movie_command = RadarrRefreshCommand::Movie { movie_id: 1 };
|
let refresh_movie_command = RadarrRefreshCommand::Movie { movie_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_root_folder_command = SonarrAddCommand::RootFolder {
|
let add_root_folder_command = SonarrAddCommand::RootFolder {
|
||||||
root_folder_path: expected_root_folder_path,
|
root_folder_path: expected_root_folder_path,
|
||||||
};
|
};
|
||||||
@@ -535,7 +535,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_series_command = SonarrAddCommand::Series {
|
let add_series_command = SonarrAddCommand::Series {
|
||||||
tvdb_id: 1,
|
tvdb_id: 1,
|
||||||
title: "test".to_owned(),
|
title: "test".to_owned(),
|
||||||
@@ -572,7 +572,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_tag_command = SonarrAddCommand::Tag {
|
let add_tag_command = SonarrAddCommand::Tag {
|
||||||
name: expected_tag_name,
|
name: expected_tag_name,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_blocklist_item_command = SonarrDeleteCommand::BlocklistItem {
|
let delete_blocklist_item_command = SonarrDeleteCommand::BlocklistItem {
|
||||||
blocklist_item_id: 1,
|
blocklist_item_id: 1,
|
||||||
};
|
};
|
||||||
@@ -340,7 +340,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_download_command = SonarrDeleteCommand::Download { download_id: 1 };
|
let delete_download_command = SonarrDeleteCommand::Download { download_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -366,7 +366,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_episode_file_command = SonarrDeleteCommand::EpisodeFile { episode_file_id: 1 };
|
let delete_episode_file_command = SonarrDeleteCommand::EpisodeFile { episode_file_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -392,7 +392,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_indexer_command = SonarrDeleteCommand::Indexer { indexer_id: 1 };
|
let delete_indexer_command = SonarrDeleteCommand::Indexer { indexer_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -418,7 +418,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_root_folder_command = SonarrDeleteCommand::RootFolder { root_folder_id: 1 };
|
let delete_root_folder_command = SonarrDeleteCommand::RootFolder { root_folder_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -448,7 +448,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_series_command = SonarrDeleteCommand::Series {
|
let delete_series_command = SonarrDeleteCommand::Series {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
delete_files_from_disk: true,
|
delete_files_from_disk: true,
|
||||||
@@ -478,7 +478,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_tag_command = SonarrDeleteCommand::Tag { tag_id: 1 };
|
let delete_tag_command = SonarrDeleteCommand::Tag { tag_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let download_release_command = SonarrDownloadCommand::Series {
|
let download_release_command = SonarrDownloadCommand::Series {
|
||||||
guid: "guid".to_owned(),
|
guid: "guid".to_owned(),
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
@@ -369,7 +369,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let download_release_command = SonarrDownloadCommand::Season {
|
let download_release_command = SonarrDownloadCommand::Season {
|
||||||
guid: "guid".to_owned(),
|
guid: "guid".to_owned(),
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
@@ -405,7 +405,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let download_release_command = SonarrDownloadCommand::Episode {
|
let download_release_command = SonarrDownloadCommand::Episode {
|
||||||
guid: "guid".to_owned(),
|
guid: "guid".to_owned(),
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_all_indexer_settings_command = SonarrEditCommand::AllIndexerSettings {
|
let edit_all_indexer_settings_command = SonarrEditCommand::AllIndexerSettings {
|
||||||
maximum_size: Some(1),
|
maximum_size: Some(1),
|
||||||
minimum_age: Some(1),
|
minimum_age: Some(1),
|
||||||
@@ -705,7 +705,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_indexer_command = SonarrEditCommand::Indexer {
|
let edit_indexer_command = SonarrEditCommand::Indexer {
|
||||||
indexer_id: 1,
|
indexer_id: 1,
|
||||||
name: Some("Test".to_owned()),
|
name: Some("Test".to_owned()),
|
||||||
@@ -757,7 +757,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_series_command = SonarrEditCommand::Series {
|
let edit_series_command = SonarrEditCommand::Series {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
enable_monitoring: true,
|
enable_monitoring: true,
|
||||||
@@ -805,7 +805,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_series_command = SonarrEditCommand::Series {
|
let edit_series_command = SonarrEditCommand::Series {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
enable_monitoring: false,
|
enable_monitoring: false,
|
||||||
@@ -853,7 +853,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_series_command = SonarrEditCommand::Series {
|
let edit_series_command = SonarrEditCommand::Series {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
enable_monitoring: false,
|
enable_monitoring: false,
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_all_indexer_settings_command = SonarrGetCommand::AllIndexerSettings;
|
let get_all_indexer_settings_command = SonarrGetCommand::AllIndexerSettings;
|
||||||
|
|
||||||
let result = SonarrGetCommandHandler::with(
|
let result = SonarrGetCommandHandler::with(
|
||||||
@@ -168,7 +168,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_episode_details_command = SonarrGetCommand::EpisodeDetails { episode_id: 1 };
|
let get_episode_details_command = SonarrGetCommand::EpisodeDetails { episode_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -191,7 +191,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_host_config_command = SonarrGetCommand::HostConfig;
|
let get_host_config_command = SonarrGetCommand::HostConfig;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -214,7 +214,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_security_config_command = SonarrGetCommand::SecurityConfig;
|
let get_security_config_command = SonarrGetCommand::SecurityConfig;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -240,7 +240,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_series_details_command = SonarrGetCommand::SeriesDetails { series_id: 1 };
|
let get_series_details_command = SonarrGetCommand::SeriesDetails { series_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -263,7 +263,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_system_status_command = SonarrGetCommand::SystemStatus;
|
let get_system_status_command = SonarrGetCommand::SystemStatus;
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ pub enum SonarrListCommand {
|
|||||||
#[command(about = "List all items in the Sonarr blocklist")]
|
#[command(about = "List all items in the Sonarr blocklist")]
|
||||||
Blocklist,
|
Blocklist,
|
||||||
#[command(about = "List all active downloads in Sonarr")]
|
#[command(about = "List all active downloads in Sonarr")]
|
||||||
Downloads,
|
Downloads {
|
||||||
|
#[arg(long, help = "How many downloads to fetch", default_value_t = 500)]
|
||||||
|
count: u64,
|
||||||
|
},
|
||||||
#[command(about = "List disk space details for all provisioned root folders in Sonarr")]
|
#[command(about = "List disk space details for all provisioned root folders in Sonarr")]
|
||||||
DiskSpace,
|
DiskSpace,
|
||||||
#[command(about = "List the episodes for the series with the given ID")]
|
#[command(about = "List the episodes for the series with the given ID")]
|
||||||
@@ -146,10 +149,10 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrListCommand> for SonarrListCommandH
|
|||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
SonarrListCommand::Downloads => {
|
SonarrListCommand::Downloads { count } => {
|
||||||
let resp = self
|
let resp = self
|
||||||
.network
|
.network
|
||||||
.handle_network_event(SonarrEvent::GetDownloads.into())
|
.handle_network_event(SonarrEvent::GetDownloads(count).into())
|
||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
@@ -212,9 +215,9 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrListCommand> for SonarrListCommandH
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if output_in_log_format {
|
if output_in_log_format {
|
||||||
let log_lines = self.app.lock().await.data.sonarr_data.logs.items.clone();
|
let log_lines = &self.app.lock().await.data.sonarr_data.logs.items;
|
||||||
|
|
||||||
serde_json::to_string_pretty(&log_lines)?
|
serde_json::to_string_pretty(log_lines)?
|
||||||
} else {
|
} else {
|
||||||
serde_json::to_string_pretty(&logs)?
|
serde_json::to_string_pretty(&logs)?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ mod tests {
|
|||||||
#[values(
|
#[values(
|
||||||
"blocklist",
|
"blocklist",
|
||||||
"series",
|
"series",
|
||||||
"downloads",
|
|
||||||
"disk-space",
|
"disk-space",
|
||||||
"quality-profiles",
|
"quality-profiles",
|
||||||
"indexers",
|
"indexers",
|
||||||
@@ -102,6 +101,28 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_downloads_count_flag_requires_arguments() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "sonarr", "list", "downloads", "--count"]);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_downloads_default_values() {
|
||||||
|
let expected_args = SonarrListCommand::Downloads { count: 500 };
|
||||||
|
let result = Cli::try_parse_from(["managarr", "sonarr", "list", "downloads"]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
if let Some(Command::Sonarr(SonarrCommand::List(downloads_command))) = result.unwrap().command
|
||||||
|
{
|
||||||
|
assert_eq!(downloads_command, expected_args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_history_events_flag_requires_arguments() {
|
fn test_list_history_events_flag_requires_arguments() {
|
||||||
let result =
|
let result =
|
||||||
@@ -287,7 +308,6 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case(SonarrListCommand::Blocklist, SonarrEvent::GetBlocklist)]
|
#[case(SonarrListCommand::Blocklist, SonarrEvent::GetBlocklist)]
|
||||||
#[case(SonarrListCommand::Downloads, SonarrEvent::GetDownloads)]
|
|
||||||
#[case(SonarrListCommand::DiskSpace, SonarrEvent::GetDiskSpace)]
|
#[case(SonarrListCommand::DiskSpace, SonarrEvent::GetDiskSpace)]
|
||||||
#[case(SonarrListCommand::Indexers, SonarrEvent::GetIndexers)]
|
#[case(SonarrListCommand::Indexers, SonarrEvent::GetIndexers)]
|
||||||
#[case(SonarrListCommand::QualityProfiles, SonarrEvent::GetQualityProfiles)]
|
#[case(SonarrListCommand::QualityProfiles, SonarrEvent::GetQualityProfiles)]
|
||||||
@@ -313,7 +333,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
|
||||||
let result = SonarrListCommandHandler::with(&app_arc, list_command, &mut mock_network)
|
let result = SonarrListCommandHandler::with(&app_arc, list_command, &mut mock_network)
|
||||||
.handle()
|
.handle()
|
||||||
@@ -337,7 +357,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_episodes_command = SonarrListCommand::Episodes { series_id: 1 };
|
let list_episodes_command = SonarrListCommand::Episodes { series_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -363,7 +383,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_episode_files_command = SonarrListCommand::EpisodeFiles { series_id: 1 };
|
let list_episode_files_command = SonarrListCommand::EpisodeFiles { series_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -374,6 +394,32 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_list_downloads_command() {
|
||||||
|
let expected_count = 1000;
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
SonarrEvent::GetDownloads(expected_count).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Sonarr(SonarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let list_downloads_command = SonarrListCommand::Downloads { count: 1000 };
|
||||||
|
|
||||||
|
let result =
|
||||||
|
SonarrListCommandHandler::with(&app_arc, list_downloads_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_list_history_command() {
|
async fn test_handle_list_history_command() {
|
||||||
let expected_events = 1000;
|
let expected_events = 1000;
|
||||||
@@ -389,7 +435,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_history_command = SonarrListCommand::History { events: 1000 };
|
let list_history_command = SonarrListCommand::History { events: 1000 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -415,7 +461,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_logs_command = SonarrListCommand::Logs {
|
let list_logs_command = SonarrListCommand::Logs {
|
||||||
events: 1000,
|
events: 1000,
|
||||||
output_in_log_format: false,
|
output_in_log_format: false,
|
||||||
@@ -443,7 +489,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_series_history_command = SonarrListCommand::SeriesHistory { series_id: 1 };
|
let list_series_history_command = SonarrListCommand::SeriesHistory { series_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -469,7 +515,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_episode_history_command = SonarrListCommand::EpisodeHistory { episode_id: 1 };
|
let list_episode_history_command = SonarrListCommand::EpisodeHistory { episode_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
@@ -496,7 +542,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_season_history_command = SonarrListCommand::SeasonHistory {
|
let list_season_history_command = SonarrListCommand::SeasonHistory {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
season_number: 1,
|
season_number: 1,
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let manual_episode_search_command = SonarrManualSearchCommand::Episode { episode_id: 1 };
|
let manual_episode_search_command = SonarrManualSearchCommand::Episode { episode_id: 1 };
|
||||||
|
|
||||||
let result = SonarrManualSearchCommandHandler::with(
|
let result = SonarrManualSearchCommandHandler::with(
|
||||||
@@ -168,7 +168,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let manual_season_search_command = SonarrManualSearchCommand::Season {
|
let manual_season_search_command = SonarrManualSearchCommand::Season {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
season_number: 1,
|
season_number: 1,
|
||||||
|
|||||||
@@ -146,6 +146,17 @@ pub enum SonarrCommand {
|
|||||||
)]
|
)]
|
||||||
season_number: i64,
|
season_number: i64,
|
||||||
},
|
},
|
||||||
|
#[command(
|
||||||
|
about = "Toggle monitoring for the specified series corresponding to the given series ID"
|
||||||
|
)]
|
||||||
|
ToggleSeriesMonitoring {
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
help = "The Sonarr ID of the series to toggle monitoring on",
|
||||||
|
required = true
|
||||||
|
)]
|
||||||
|
series_id: i64,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SonarrCommand> for Command {
|
impl From<SonarrCommand> for Command {
|
||||||
@@ -290,6 +301,13 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrCommand> for SonarrCliHandler<'a, '
|
|||||||
.await?;
|
.await?;
|
||||||
serde_json::to_string_pretty(&resp)?
|
serde_json::to_string_pretty(&resp)?
|
||||||
}
|
}
|
||||||
|
SonarrCommand::ToggleSeriesMonitoring { series_id } => {
|
||||||
|
let resp = self
|
||||||
|
.network
|
||||||
|
.handle_network_event(SonarrEvent::ToggleSeriesMonitoring(series_id).into())
|
||||||
|
.await?;
|
||||||
|
serde_json::to_string_pretty(&resp)?
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
|
||||||
let result = SonarrRefreshCommandHandler::with(&app_arc, refresh_command, &mut mock_network)
|
let result = SonarrRefreshCommandHandler::with(&app_arc, refresh_command, &mut mock_network)
|
||||||
.handle()
|
.handle()
|
||||||
@@ -127,7 +127,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let refresh_series_command = SonarrRefreshCommand::Series { series_id: 1 };
|
let refresh_series_command = SonarrRefreshCommand::Series { series_id: 1 };
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
|
|||||||
@@ -216,6 +216,31 @@ mod tests {
|
|||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toggle_series_monitoring_requires_series_id() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "sonarr", "toggle-series-monitoring"]);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert_eq!(
|
||||||
|
result.unwrap_err().kind(),
|
||||||
|
ErrorKind::MissingRequiredArgument
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toggle_series_monitoring_requirements_satisfied() {
|
||||||
|
let result = Cli::command().try_get_matches_from([
|
||||||
|
"managarr",
|
||||||
|
"sonarr",
|
||||||
|
"toggle-series-monitoring",
|
||||||
|
"--series-id",
|
||||||
|
"1",
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod handler {
|
mod handler {
|
||||||
@@ -272,7 +297,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let claer_blocklist_command = SonarrCommand::ClearBlocklist;
|
let claer_blocklist_command = SonarrCommand::ClearBlocklist;
|
||||||
|
|
||||||
let result = SonarrCliHandler::with(&app_arc, claer_blocklist_command, &mut mock_network)
|
let result = SonarrCliHandler::with(&app_arc, claer_blocklist_command, &mut mock_network)
|
||||||
@@ -297,7 +322,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let mark_history_item_as_failed_command =
|
let mark_history_item_as_failed_command =
|
||||||
SonarrCommand::MarkHistoryItemAsFailed { history_item_id: 1 };
|
SonarrCommand::MarkHistoryItemAsFailed { history_item_id: 1 };
|
||||||
|
|
||||||
@@ -327,7 +352,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let add_tag_command = SonarrCommand::Add(SonarrAddCommand::Tag {
|
let add_tag_command = SonarrCommand::Add(SonarrAddCommand::Tag {
|
||||||
name: expected_tag_name,
|
name: expected_tag_name,
|
||||||
});
|
});
|
||||||
@@ -354,7 +379,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let delete_blocklist_item_command =
|
let delete_blocklist_item_command =
|
||||||
SonarrCommand::Delete(SonarrDeleteCommand::BlocklistItem {
|
SonarrCommand::Delete(SonarrDeleteCommand::BlocklistItem {
|
||||||
blocklist_item_id: 1,
|
blocklist_item_id: 1,
|
||||||
@@ -388,7 +413,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let download_series_release_command =
|
let download_series_release_command =
|
||||||
SonarrCommand::Download(SonarrDownloadCommand::Series {
|
SonarrCommand::Download(SonarrDownloadCommand::Series {
|
||||||
guid: "1234".to_owned(),
|
guid: "1234".to_owned(),
|
||||||
@@ -442,7 +467,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let edit_all_indexer_settings_command =
|
let edit_all_indexer_settings_command =
|
||||||
SonarrCommand::Edit(SonarrEditCommand::AllIndexerSettings {
|
SonarrCommand::Edit(SonarrEditCommand::AllIndexerSettings {
|
||||||
maximum_size: Some(1),
|
maximum_size: Some(1),
|
||||||
@@ -478,7 +503,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let manual_episode_search_command =
|
let manual_episode_search_command =
|
||||||
SonarrCommand::ManualSearch(SonarrManualSearchCommand::Episode { episode_id: 1 });
|
SonarrCommand::ManualSearch(SonarrManualSearchCommand::Episode { episode_id: 1 });
|
||||||
|
|
||||||
@@ -506,7 +531,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let manual_episode_search_command =
|
let manual_episode_search_command =
|
||||||
SonarrCommand::TriggerAutomaticSearch(SonarrTriggerAutomaticSearchCommand::Episode {
|
SonarrCommand::TriggerAutomaticSearch(SonarrTriggerAutomaticSearchCommand::Episode {
|
||||||
episode_id: 1,
|
episode_id: 1,
|
||||||
@@ -532,7 +557,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let get_system_status_command = SonarrCommand::Get(SonarrGetCommand::SystemStatus);
|
let get_system_status_command = SonarrCommand::Get(SonarrGetCommand::SystemStatus);
|
||||||
|
|
||||||
let result = SonarrCliHandler::with(&app_arc, get_system_status_command, &mut mock_network)
|
let result = SonarrCliHandler::with(&app_arc, get_system_status_command, &mut mock_network)
|
||||||
@@ -554,7 +579,7 @@ mod tests {
|
|||||||
Series::default(),
|
Series::default(),
|
||||||
])))
|
])))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let list_series_command = SonarrCommand::List(SonarrListCommand::Series);
|
let list_series_command = SonarrCommand::List(SonarrListCommand::Series);
|
||||||
|
|
||||||
let result = SonarrCliHandler::with(&app_arc, list_series_command, &mut mock_network)
|
let result = SonarrCliHandler::with(&app_arc, list_series_command, &mut mock_network)
|
||||||
@@ -579,7 +604,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let refresh_series_command =
|
let refresh_series_command =
|
||||||
SonarrCommand::Refresh(SonarrRefreshCommand::Series { series_id: 1 });
|
SonarrCommand::Refresh(SonarrRefreshCommand::Series { series_id: 1 });
|
||||||
|
|
||||||
@@ -605,7 +630,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let search_new_series_command = SonarrCommand::SearchNewSeries {
|
let search_new_series_command = SonarrCommand::SearchNewSeries {
|
||||||
query: "halo".to_owned(),
|
query: "halo".to_owned(),
|
||||||
};
|
};
|
||||||
@@ -632,7 +657,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let start_task_command = SonarrCommand::StartTask {
|
let start_task_command = SonarrCommand::StartTask {
|
||||||
task_name: SonarrTaskName::ApplicationUpdateCheck,
|
task_name: SonarrTaskName::ApplicationUpdateCheck,
|
||||||
};
|
};
|
||||||
@@ -659,7 +684,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let test_indexer_command = SonarrCommand::TestIndexer { indexer_id: 1 };
|
let test_indexer_command = SonarrCommand::TestIndexer { indexer_id: 1 };
|
||||||
|
|
||||||
let result = SonarrCliHandler::with(&app_arc, test_indexer_command, &mut mock_network)
|
let result = SonarrCliHandler::with(&app_arc, test_indexer_command, &mut mock_network)
|
||||||
@@ -681,7 +706,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let test_all_indexers_command = SonarrCommand::TestAllIndexers;
|
let test_all_indexers_command = SonarrCommand::TestAllIndexers;
|
||||||
|
|
||||||
let result = SonarrCliHandler::with(&app_arc, test_all_indexers_command, &mut mock_network)
|
let result = SonarrCliHandler::with(&app_arc, test_all_indexers_command, &mut mock_network)
|
||||||
@@ -692,7 +717,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_list_toggle_episode_monitoring_command() {
|
async fn test_toggle_episode_monitoring_command() {
|
||||||
let expected_episode_id = 1;
|
let expected_episode_id = 1;
|
||||||
let mut mock_network = MockNetworkTrait::new();
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
mock_network
|
mock_network
|
||||||
@@ -706,7 +731,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let toggle_episode_monitoring_command =
|
let toggle_episode_monitoring_command =
|
||||||
SonarrCommand::ToggleEpisodeMonitoring { episode_id: 1 };
|
SonarrCommand::ToggleEpisodeMonitoring { episode_id: 1 };
|
||||||
|
|
||||||
@@ -722,7 +747,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_list_toggle_season_monitoring_command() {
|
async fn test_toggle_season_monitoring_command() {
|
||||||
let expected_series_id = 1;
|
let expected_series_id = 1;
|
||||||
let expected_season_number = 1;
|
let expected_season_number = 1;
|
||||||
let mut mock_network = MockNetworkTrait::new();
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
@@ -737,7 +762,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let toggle_season_monitoring_command = SonarrCommand::ToggleSeasonMonitoring {
|
let toggle_season_monitoring_command = SonarrCommand::ToggleSeasonMonitoring {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
season_number: 1,
|
season_number: 1,
|
||||||
@@ -753,5 +778,34 @@ mod tests {
|
|||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_toggle_series_monitoring_command() {
|
||||||
|
let expected_series_id = 1;
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(
|
||||||
|
SonarrEvent::ToggleSeriesMonitoring(expected_series_id).into(),
|
||||||
|
))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Sonarr(SonarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
|
let toggle_series_monitoring_command = SonarrCommand::ToggleSeriesMonitoring { series_id: 1 };
|
||||||
|
|
||||||
|
let result = SonarrCliHandler::with(
|
||||||
|
&app_arc,
|
||||||
|
toggle_series_monitoring_command,
|
||||||
|
&mut mock_network,
|
||||||
|
)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let trigger_automatic_series_search_command =
|
let trigger_automatic_series_search_command =
|
||||||
SonarrTriggerAutomaticSearchCommand::Series { series_id: 1 };
|
SonarrTriggerAutomaticSearchCommand::Series { series_id: 1 };
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let trigger_automatic_season_search_command = SonarrTriggerAutomaticSearchCommand::Season {
|
let trigger_automatic_season_search_command = SonarrTriggerAutomaticSearchCommand::Season {
|
||||||
series_id: 1,
|
series_id: 1,
|
||||||
season_number: 1,
|
season_number: 1,
|
||||||
@@ -238,7 +238,7 @@ mod tests {
|
|||||||
json!({"testResponse": "response"}),
|
json!({"testResponse": "response"}),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
let app_arc = Arc::new(Mutex::new(App::default()));
|
let app_arc = Arc::new(Mutex::new(App::test_default()));
|
||||||
let trigger_automatic_episode_search_command =
|
let trigger_automatic_episode_search_command =
|
||||||
SonarrTriggerAutomaticSearchCommand::Episode { episode_id: 1 };
|
SonarrTriggerAutomaticSearchCommand::Episode { episode_id: 1 };
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use std::thread;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crossterm::event;
|
use crossterm::event;
|
||||||
use crossterm::event::Event as CrosstermEvent;
|
use crossterm::event::{Event as CrosstermEvent, KeyEventKind};
|
||||||
|
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
|
||||||
@@ -30,8 +30,12 @@ impl Events {
|
|||||||
.unwrap_or_else(|| Duration::from_secs(0));
|
.unwrap_or_else(|| Duration::from_secs(0));
|
||||||
if event::poll(timeout).unwrap() {
|
if event::poll(timeout).unwrap() {
|
||||||
if let CrosstermEvent::Key(key_event) = event::read().unwrap() {
|
if let CrosstermEvent::Key(key_event) = event::read().unwrap() {
|
||||||
let key = Key::from(key_event);
|
// Only process the key event if it's a press event
|
||||||
tx.send(InputEvent::KeyEvent(key)).unwrap();
|
// 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-15
@@ -13,6 +13,8 @@ pub enum Key {
|
|||||||
Down,
|
Down,
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
PgDown,
|
||||||
|
PgUp,
|
||||||
Enter,
|
Enter,
|
||||||
Esc,
|
Esc,
|
||||||
Backspace,
|
Backspace,
|
||||||
@@ -29,21 +31,23 @@ pub enum Key {
|
|||||||
impl Display for Key {
|
impl Display for Key {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Key::Char(c) => write!(f, "<{c}>"),
|
Key::Char(c) => write!(f, "{c}"),
|
||||||
Key::Ctrl(c) => write!(f, "<ctrl-{c}>"),
|
Key::Ctrl(c) => write!(f, "ctrl-{c}"),
|
||||||
Key::Up => write!(f, "<↑>"),
|
Key::Up => write!(f, "↑"),
|
||||||
Key::Down => write!(f, "<↓>"),
|
Key::Down => write!(f, "↓"),
|
||||||
Key::Left => write!(f, "<←>"),
|
Key::Left => write!(f, "←"),
|
||||||
Key::Right => write!(f, "<→>"),
|
Key::Right => write!(f, "→"),
|
||||||
Key::Enter => write!(f, "<enter>"),
|
Key::PgDown => write!(f, "pgDown"),
|
||||||
Key::Esc => write!(f, "<esc>"),
|
Key::PgUp => write!(f, "pgUp"),
|
||||||
Key::Backspace => write!(f, "<backspace>"),
|
Key::Enter => write!(f, "enter"),
|
||||||
Key::Home => write!(f, "<home>"),
|
Key::Esc => write!(f, "esc"),
|
||||||
Key::End => write!(f, "<end>"),
|
Key::Backspace => write!(f, "backspace"),
|
||||||
Key::Tab => write!(f, "<tab>"),
|
Key::Home => write!(f, "home"),
|
||||||
Key::BackTab => write!(f, "<shift-tab>"),
|
Key::End => write!(f, "end"),
|
||||||
Key::Delete => write!(f, "<del>"),
|
Key::Tab => write!(f, "tab"),
|
||||||
_ => write!(f, "<{self:?}>"),
|
Key::BackTab => write!(f, "shift-tab"),
|
||||||
|
Key::Delete => write!(f, "del"),
|
||||||
|
_ => write!(f, "{self:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,6 +70,14 @@ impl From<KeyEvent> for Key {
|
|||||||
code: KeyCode::Right,
|
code: KeyCode::Right,
|
||||||
..
|
..
|
||||||
} => Key::Right,
|
} => Key::Right,
|
||||||
|
KeyEvent {
|
||||||
|
code: KeyCode::PageDown,
|
||||||
|
..
|
||||||
|
} => Key::PgDown,
|
||||||
|
KeyEvent {
|
||||||
|
code: KeyCode::PageUp,
|
||||||
|
..
|
||||||
|
} => Key::PgUp,
|
||||||
KeyEvent {
|
KeyEvent {
|
||||||
code: KeyCode::Backspace,
|
code: KeyCode::Backspace,
|
||||||
..
|
..
|
||||||
|
|||||||
+13
-1
@@ -11,6 +11,8 @@ mod tests {
|
|||||||
#[case(Key::Down, "↓")]
|
#[case(Key::Down, "↓")]
|
||||||
#[case(Key::Left, "←")]
|
#[case(Key::Left, "←")]
|
||||||
#[case(Key::Right, "→")]
|
#[case(Key::Right, "→")]
|
||||||
|
#[case(Key::PgDown, "pgDown")]
|
||||||
|
#[case(Key::PgUp, "pgUp")]
|
||||||
#[case(Key::Enter, "enter")]
|
#[case(Key::Enter, "enter")]
|
||||||
#[case(Key::Esc, "esc")]
|
#[case(Key::Esc, "esc")]
|
||||||
#[case(Key::Backspace, "backspace")]
|
#[case(Key::Backspace, "backspace")]
|
||||||
@@ -22,7 +24,7 @@ mod tests {
|
|||||||
#[case(Key::Char('q'), "q")]
|
#[case(Key::Char('q'), "q")]
|
||||||
#[case(Key::Ctrl('q'), "ctrl-q")]
|
#[case(Key::Ctrl('q'), "ctrl-q")]
|
||||||
fn test_key_formatter(#[case] key: Key, #[case] expected_str: &str) {
|
fn test_key_formatter(#[case] key: Key, #[case] expected_str: &str) {
|
||||||
assert_str_eq!(format!("{key}"), format!("<{expected_str}>"));
|
assert_str_eq!(format!("{key}"), format!("{expected_str}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -45,6 +47,16 @@ mod tests {
|
|||||||
assert_eq!(Key::from(KeyEvent::from(KeyCode::Right)), Key::Right);
|
assert_eq!(Key::from(KeyEvent::from(KeyCode::Right)), Key::Right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_key_from_page_down() {
|
||||||
|
assert_eq!(Key::from(KeyEvent::from(KeyCode::PageDown)), Key::PgDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_key_from_page_up() {
|
||||||
|
assert_eq!(Key::from(KeyEvent::from(KeyCode::PageUp)), Key::PgUp);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key_from_backspace() {
|
fn test_key_from_backspace() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $block:expr, $context:expr) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $block:expr, $context:expr) => {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -110,14 +110,14 @@ mod test_utils {
|
|||||||
.$data_ref
|
.$data_ref
|
||||||
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
||||||
|
|
||||||
$handler::with(&key, &mut app, &$block, &$context).handle();
|
$handler::new(&key, &mut app, &$block, &$context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection(),
|
app.data.$servarr_data.$data_ref.current_selection(),
|
||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(&key, &mut app, &$block, &$context).handle();
|
$handler::new(&key, &mut app, &$block, &$context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection(),
|
app.data.$servarr_data.$data_ref.current_selection(),
|
||||||
@@ -129,7 +129,7 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -137,14 +137,14 @@ mod test_utils {
|
|||||||
.$data_ref
|
.$data_ref
|
||||||
.set_items(simple_stateful_iterable_vec!($items));
|
.set_items(simple_stateful_iterable_vec!($items));
|
||||||
|
|
||||||
$handler::with(key, &mut app, $block, $context).handle();
|
$handler::new(key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(key, &mut app, $block, $context).handle();
|
$handler::new(key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
@@ -156,18 +156,18 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app.data.$servarr_data.$data_ref.set_items($items);
|
app.data.$servarr_data.$data_ref.set_items($items);
|
||||||
|
|
||||||
$handler::with(key, &mut app, $block, $context).handle();
|
$handler::new(key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(key, &mut app, $block, $context).handle();
|
$handler::new(key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
@@ -179,11 +179,11 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app.data.$servarr_data.$data_ref.set_items($items);
|
app.data.$servarr_data.$data_ref.set_items($items);
|
||||||
|
|
||||||
$handler::with(key, &mut app, $block, $context).handle();
|
$handler::new(key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app
|
app
|
||||||
@@ -196,7 +196,7 @@ mod test_utils {
|
|||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(key, &mut app, $block, $context).handle();
|
$handler::new(key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app
|
app
|
||||||
@@ -217,7 +217,7 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $block:expr, $context:expr) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $block:expr, $context:expr) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func() {
|
fn $func() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app.data.$servarr_data.$data_ref.set_items(vec![
|
app.data.$servarr_data.$data_ref.set_items(vec![
|
||||||
"Test 1".to_owned(),
|
"Test 1".to_owned(),
|
||||||
@@ -225,14 +225,14 @@ mod test_utils {
|
|||||||
"Test 3".to_owned(),
|
"Test 3".to_owned(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection(),
|
app.data.$servarr_data.$data_ref.current_selection(),
|
||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection(),
|
app.data.$servarr_data.$data_ref.current_selection(),
|
||||||
@@ -244,7 +244,7 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func() {
|
fn $func() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -252,14 +252,14 @@ mod test_utils {
|
|||||||
.$data_ref
|
.$data_ref
|
||||||
.set_items(extended_stateful_iterable_vec!($items));
|
.set_items(extended_stateful_iterable_vec!($items));
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
@@ -271,18 +271,18 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func() {
|
fn $func() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app.data.$servarr_data.$data_ref.set_items($items);
|
app.data.$servarr_data.$data_ref.set_items($items);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app.data.$servarr_data.$data_ref.current_selection().$field,
|
app.data.$servarr_data.$data_ref.current_selection().$field,
|
||||||
@@ -294,11 +294,11 @@ mod test_utils {
|
|||||||
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
|
($func:ident, $handler:ident, $servarr_data:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $func() {
|
fn $func() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
app.data.$servarr_data.$data_ref.set_items($items);
|
app.data.$servarr_data.$data_ref.set_items($items);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.end.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app
|
app
|
||||||
@@ -311,7 +311,7 @@ mod test_utils {
|
|||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.home.key, &mut app, $block, $context).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_str_eq!(
|
pretty_assertions::assert_str_eq!(
|
||||||
app
|
app
|
||||||
@@ -330,7 +330,7 @@ mod test_utils {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! test_handler_delegation {
|
macro_rules! test_handler_delegation {
|
||||||
($handler:ident, $base:expr, $active_block:expr) => {
|
($handler:ident, $base:expr, $active_block:expr) => {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.history.set_items(vec![
|
app.data.sonarr_data.history.set_items(vec![
|
||||||
$crate::models::sonarr_models::SonarrHistoryItem::default(),
|
$crate::models::sonarr_models::SonarrHistoryItem::default(),
|
||||||
]);
|
]);
|
||||||
@@ -417,7 +417,7 @@ mod test_utils {
|
|||||||
app.push_navigation_stack($base.into());
|
app.push_navigation_stack($base.into());
|
||||||
app.push_navigation_stack($active_block.into());
|
app.push_navigation_stack($active_block.into());
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.esc.key, &mut app, $active_block, None).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.esc.key, &mut app, $active_block, None).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_eq!(app.get_current_route(), $base.into());
|
pretty_assertions::assert_eq!(app.get_current_route(), $base.into());
|
||||||
};
|
};
|
||||||
@@ -426,15 +426,15 @@ mod test_utils {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! assert_delete_prompt {
|
macro_rules! assert_delete_prompt {
|
||||||
($handler:ident, $block:expr, $expected_block:expr) => {
|
($handler:ident, $block:expr, $expected_block:expr) => {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
$handler::with(DELETE_KEY, &mut app, $block, None).handle();
|
$handler::new(DELETE_KEY, &mut app, $block, None).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_eq!(app.get_current_route(), $expected_block.into());
|
pretty_assertions::assert_eq!(app.get_current_route(), $expected_block.into());
|
||||||
};
|
};
|
||||||
|
|
||||||
($handler:ident, $app:expr, $block:expr, $expected_block:expr) => {
|
($handler:ident, $app:expr, $block:expr, $expected_block:expr) => {
|
||||||
$handler::with(DELETE_KEY, &mut $app, $block, None).handle();
|
$handler::new(DELETE_KEY, &mut $app, $block, None).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_eq!($app.get_current_route(), $expected_block.into());
|
pretty_assertions::assert_eq!($app.get_current_route(), $expected_block.into());
|
||||||
};
|
};
|
||||||
@@ -443,10 +443,10 @@ mod test_utils {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! assert_refresh_key {
|
macro_rules! assert_refresh_key {
|
||||||
($handler:ident, $block:expr) => {
|
($handler:ident, $block:expr) => {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack($block.into());
|
app.push_navigation_stack($block.into());
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.refresh.key, &mut app, $block, None).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.refresh.key, &mut app, $block, None).handle();
|
||||||
|
|
||||||
pretty_assertions::assert_eq!(app.get_current_route(), $block.into());
|
pretty_assertions::assert_eq!(app.get_current_route(), $block.into());
|
||||||
assert!(app.should_refresh);
|
assert!(app.should_refresh);
|
||||||
|
|||||||
@@ -6,19 +6,26 @@ mod tests {
|
|||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::context_clues::SERVARR_CONTEXT_CLUES;
|
||||||
|
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
||||||
|
use crate::app::radarr::radarr_context_clues::{
|
||||||
|
LIBRARY_CONTEXT_CLUES, MOVIE_DETAILS_CONTEXT_CLUES,
|
||||||
|
};
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::handle_events;
|
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle};
|
||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
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::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::HorizontallyScrollableText;
|
||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_handle_clear_errors() {
|
fn test_handle_clear_errors() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.error = "test error".to_owned().into();
|
app.error = "test error".to_owned().into();
|
||||||
|
|
||||||
handle_clear_errors(&mut app);
|
handle_clear_errors(&mut app);
|
||||||
@@ -30,7 +37,7 @@ mod tests {
|
|||||||
#[case(ActiveRadarrBlock::Movies.into(), ActiveRadarrBlock::SearchMovie.into())]
|
#[case(ActiveRadarrBlock::Movies.into(), ActiveRadarrBlock::SearchMovie.into())]
|
||||||
#[case(ActiveSonarrBlock::Series.into(), ActiveSonarrBlock::SearchSeries.into())]
|
#[case(ActiveSonarrBlock::Series.into(), ActiveSonarrBlock::SearchSeries.into())]
|
||||||
fn test_handle_events(#[case] base_block: Route, #[case] top_block: Route) {
|
fn test_handle_events(#[case] base_block: Route, #[case] top_block: Route) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(base_block);
|
app.push_navigation_stack(base_block);
|
||||||
app.push_navigation_stack(top_block);
|
app.push_navigation_stack(top_block);
|
||||||
app
|
app
|
||||||
@@ -56,7 +63,7 @@ mod tests {
|
|||||||
where
|
where
|
||||||
T: Into<Route> + Copy,
|
T: Into<Route> + Copy,
|
||||||
{
|
{
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.error = "Test".into();
|
app.error = "Test".into();
|
||||||
app.server_tabs.set_index(index);
|
app.server_tabs.set_index(index);
|
||||||
|
|
||||||
@@ -82,9 +89,85 @@ mod tests {
|
|||||||
assert!(app.cancellation_token.is_cancelled());
|
assert!(app.cancellation_token.is_cancelled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handle_populate_keybindings_table_on_help_button_press() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
let expected_keybinding_items = Vec::from(SERVARR_CONTEXT_CLUES)
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
app.push_navigation_stack(ActiveKeybindingBlock::Help.into());
|
||||||
|
|
||||||
|
handle_events(DEFAULT_KEYBINDINGS.help.key, &mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
expected_keybinding_items,
|
||||||
|
app.keymapping_table.unwrap().items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handle_ignore_help_button_when_ignore_special_keys_for_textbox_input_is_true() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::default().into());
|
||||||
|
|
||||||
|
handle_events(DEFAULT_KEYBINDINGS.help.key, &mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
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()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut stateful_table = StatefulTable::default();
|
||||||
|
stateful_table.set_items(keybinding_items);
|
||||||
|
app.keymapping_table = Some(stateful_table);
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::default().into());
|
||||||
|
|
||||||
|
handle_events(DEFAULT_KEYBINDINGS.help.key, &mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handle_shows_keymapping_popup_when_keymapping_table_is_populated() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
let keybinding_items = Vec::from(SERVARR_CONTEXT_CLUES)
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut stateful_table = StatefulTable::default();
|
||||||
|
stateful_table.set_items(keybinding_items);
|
||||||
|
app.keymapping_table = Some(stateful_table);
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::default().into());
|
||||||
|
let expected_selection = KeybindingItem {
|
||||||
|
key: SERVARR_CONTEXT_CLUES[1].0.key.to_string(),
|
||||||
|
alt_key: SERVARR_CONTEXT_CLUES[1]
|
||||||
|
.0
|
||||||
|
.alt
|
||||||
|
.map_or(String::new(), |k| k.to_string()),
|
||||||
|
desc: SERVARR_CONTEXT_CLUES[1].1.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
handle_events(DEFAULT_KEYBINDINGS.down.key, &mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
&expected_selection,
|
||||||
|
app.keymapping_table.unwrap().current_selection()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_handle_prompt_toggle_left_right_radarr(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_handle_prompt_toggle_left_right_radarr(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
@@ -100,7 +183,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_handle_prompt_toggle_left_right_sonarr(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_handle_prompt_toggle_left_right_sonarr(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
|
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
@@ -113,4 +196,95 @@ mod tests {
|
|||||||
|
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_populate_keymapping_table_global_options() {
|
||||||
|
let expected_keybinding_items = Vec::from(SERVARR_CONTEXT_CLUES)
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| {
|
||||||
|
let (key, alt_key) = if key.alt.is_some() {
|
||||||
|
(key.key.to_string(), key.alt.as_ref().unwrap().to_string())
|
||||||
|
} else {
|
||||||
|
(key.key.to_string(), String::new())
|
||||||
|
};
|
||||||
|
KeybindingItem {
|
||||||
|
key,
|
||||||
|
alt_key,
|
||||||
|
desc: desc.to_string(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(ActiveKeybindingBlock::Help.into());
|
||||||
|
|
||||||
|
populate_keymapping_table(&mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
expected_keybinding_items,
|
||||||
|
app.keymapping_table.unwrap().items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_populate_keymapping_table_populates_servarr_specific_tab_info_before_global_options() {
|
||||||
|
let mut expected_keybinding_items = LIBRARY_CONTEXT_CLUES
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
expected_keybinding_items.extend(
|
||||||
|
SERVARR_CONTEXT_CLUES
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc)),
|
||||||
|
);
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::default().into());
|
||||||
|
|
||||||
|
populate_keymapping_table(&mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
expected_keybinding_items,
|
||||||
|
app.keymapping_table.unwrap().items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
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))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
expected_keybinding_items.extend(
|
||||||
|
SERVARR_CONTEXT_CLUES
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc)),
|
||||||
|
);
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = RadarrData::default();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
||||||
|
|
||||||
|
populate_keymapping_table(&mut app);
|
||||||
|
|
||||||
|
assert!(app.keymapping_table.is_some());
|
||||||
|
assert_eq!(
|
||||||
|
expected_keybinding_items,
|
||||||
|
app.keymapping_table.unwrap().items
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn context_clue_to_keybinding_item(key: &KeyBinding, desc: &&str) -> KeybindingItem {
|
||||||
|
let (key, alt_key) = if key.alt.is_some() {
|
||||||
|
(key.key.to_string(), key.alt.as_ref().unwrap().to_string())
|
||||||
|
} else {
|
||||||
|
(key.key.to_string(), String::new())
|
||||||
|
};
|
||||||
|
KeybindingItem {
|
||||||
|
key,
|
||||||
|
alt_key,
|
||||||
|
desc: desc.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
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::ActiveKeybindingBlock;
|
||||||
|
use crate::models::servarr_models::KeybindingItem;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "keybinding_handler_tests.rs"]
|
||||||
|
mod keybinding_handler_tests;
|
||||||
|
|
||||||
|
pub(super) struct KeybindingHandler<'a, 'b> {
|
||||||
|
key: Key,
|
||||||
|
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) {
|
||||||
|
self.handle_key_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accepts(_active_block: ActiveKeybindingBlock) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
|
key: Key,
|
||||||
|
app: &'a mut App<'b>,
|
||||||
|
_active_block: ActiveKeybindingBlock,
|
||||||
|
_context: Option<ActiveKeybindingBlock>,
|
||||||
|
) -> KeybindingHandler<'a, 'b> {
|
||||||
|
KeybindingHandler { key, app }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_key(&self) -> Key {
|
||||||
|
self.key
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ready(&self) -> bool {
|
||||||
|
self.app.keymapping_table.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_scroll_up(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_scroll_down(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_home(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_end(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_delete(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_left_right_action(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_submit(&mut self) {}
|
||||||
|
|
||||||
|
fn handle_esc(&mut self) {
|
||||||
|
self.app.keymapping_table = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_char_key_event(&mut self) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
|
use crate::app::App;
|
||||||
|
use crate::event::Key;
|
||||||
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::handlers::KeybindingHandler;
|
||||||
|
use crate::models::servarr_data::ActiveKeybindingBlock;
|
||||||
|
use crate::models::stateful_table::StatefulTable;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
mod test_handle_esc {
|
||||||
|
use super::*;
|
||||||
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_esc_empties_keymapping_table() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_keybinding_handler_accepts() {
|
||||||
|
assert!(KeybindingHandler::accepts(ActiveKeybindingBlock::Help));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_keybinding_handler_not_ready_when_keybinding_is_empty() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = false;
|
||||||
|
|
||||||
|
let handler = KeybindingHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveKeybindingBlock::Help,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(!handler.is_ready());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_keybinding_handler_ready_when_keymapping_table_is_not_empty(
|
||||||
|
#[values(true, false)] is_loading: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.keymapping_table = Some(StatefulTable::default());
|
||||||
|
app.is_loading = is_loading;
|
||||||
|
|
||||||
|
let handler = KeybindingHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveKeybindingBlock::Help,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(handler.is_ready());
|
||||||
|
}
|
||||||
|
}
|
||||||
+87
-26
@@ -1,11 +1,20 @@
|
|||||||
use radarr_handlers::RadarrHandler;
|
use radarr_handlers::RadarrHandler;
|
||||||
use sonarr_handlers::SonarrHandler;
|
use sonarr_handlers::SonarrHandler;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::context_clues::{
|
||||||
|
ContextClueProvider, ServarrContextClueProvider, SERVARR_CONTEXT_CLUES,
|
||||||
|
};
|
||||||
|
use crate::app::key_binding::KeyBinding;
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
use crate::handlers::keybinding_handler::KeybindingHandler;
|
||||||
|
use crate::matches_key;
|
||||||
|
use crate::models::servarr_data::ActiveKeybindingBlock;
|
||||||
|
use crate::models::servarr_models::KeybindingItem;
|
||||||
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{HorizontallyScrollableText, Route};
|
use crate::models::{HorizontallyScrollableText, Route};
|
||||||
|
|
||||||
|
mod keybinding_handler;
|
||||||
mod radarr_handlers;
|
mod radarr_handlers;
|
||||||
mod sonarr_handlers;
|
mod sonarr_handlers;
|
||||||
|
|
||||||
@@ -22,40 +31,42 @@ pub trait KeyEventHandler<'a, 'b, T: Into<Route> + Copy> {
|
|||||||
fn handle_key_event(&mut self) {
|
fn handle_key_event(&mut self) {
|
||||||
let key = self.get_key();
|
let key = self.get_key();
|
||||||
match key {
|
match key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.up.key => {
|
_ if matches_key!(up, key, self.ignore_special_keys()) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_scroll_up();
|
self.handle_scroll_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.down.key => {
|
_ if matches_key!(down, key, self.ignore_special_keys()) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_scroll_down();
|
self.handle_scroll_down();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.home.key => {
|
_ if matches_key!(home, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_home();
|
self.handle_home();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.end.key => {
|
_ if matches_key!(end, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_end();
|
self.handle_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.delete.key => {
|
_ if matches_key!(delete, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_delete();
|
self.handle_delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key || key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(left, key, self.ignore_special_keys())
|
||||||
|
|| matches_key!(right, key, self.ignore_special_keys()) =>
|
||||||
|
{
|
||||||
self.handle_left_right_action()
|
self.handle_left_right_action()
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.submit.key => {
|
_ if matches_key!(submit, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_submit();
|
self.handle_submit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.esc.key => self.handle_esc(),
|
_ if matches_key!(esc, key) => self.handle_esc(),
|
||||||
_ => {
|
_ => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_char_key_event();
|
self.handle_char_key_event();
|
||||||
@@ -69,8 +80,9 @@ pub trait KeyEventHandler<'a, 'b, T: Into<Route> + Copy> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn accepts(active_block: T) -> bool;
|
fn accepts(active_block: T) -> bool;
|
||||||
fn with(key: Key, app: &'a mut App<'b>, active_block: T, context: Option<T>) -> Self;
|
fn new(key: Key, app: &'a mut App<'b>, active_block: T, context: Option<T>) -> Self;
|
||||||
fn get_key(&self) -> Key;
|
fn get_key(&self) -> Key;
|
||||||
|
fn ignore_special_keys(&self) -> bool;
|
||||||
fn is_ready(&self) -> bool;
|
fn is_ready(&self) -> bool;
|
||||||
fn handle_scroll_up(&mut self);
|
fn handle_scroll_up(&mut self);
|
||||||
fn handle_scroll_down(&mut self);
|
fn handle_scroll_down(&mut self);
|
||||||
@@ -84,29 +96,80 @@ pub trait KeyEventHandler<'a, 'b, T: Into<Route> + Copy> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_events(key: Key, app: &mut App<'_>) {
|
pub fn handle_events(key: Key, app: &mut App<'_>) {
|
||||||
if key == DEFAULT_KEYBINDINGS.next_servarr.key {
|
if matches_key!(next_servarr, key) {
|
||||||
app.reset();
|
app.reset();
|
||||||
app.server_tabs.next();
|
app.server_tabs.next();
|
||||||
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
||||||
app.cancellation_token.cancel();
|
app.cancellation_token.cancel();
|
||||||
} else if key == DEFAULT_KEYBINDINGS.previous_servarr.key {
|
} else if matches_key!(previous_servarr, key) {
|
||||||
app.reset();
|
app.reset();
|
||||||
app.server_tabs.previous();
|
app.server_tabs.previous();
|
||||||
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
||||||
app.cancellation_token.cancel();
|
app.cancellation_token.cancel();
|
||||||
|
} else if matches_key!(help, key) && !app.ignore_special_keys_for_textbox_input {
|
||||||
|
if app.keymapping_table.is_none() {
|
||||||
|
populate_keymapping_table(app);
|
||||||
|
} else {
|
||||||
|
app.keymapping_table = None;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
match app.get_current_route() {
|
match app.get_current_route() {
|
||||||
|
_ if app.keymapping_table.is_some() => {
|
||||||
|
KeybindingHandler::new(key, app, ActiveKeybindingBlock::Help, None).handle();
|
||||||
|
}
|
||||||
Route::Radarr(active_radarr_block, context) => {
|
Route::Radarr(active_radarr_block, context) => {
|
||||||
RadarrHandler::with(key, app, active_radarr_block, context).handle()
|
RadarrHandler::new(key, app, active_radarr_block, context).handle()
|
||||||
}
|
}
|
||||||
Route::Sonarr(active_sonarr_block, context) => {
|
Route::Sonarr(active_sonarr_block, context) => {
|
||||||
SonarrHandler::with(key, app, active_sonarr_block, context).handle()
|
SonarrHandler::new(key, app, active_sonarr_block, context).handle()
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
} else {
|
||||||
|
(key.key.to_string(), String::new())
|
||||||
|
};
|
||||||
|
KeybindingItem {
|
||||||
|
key,
|
||||||
|
alt_key,
|
||||||
|
desc: desc.to_string(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut keybindings = Vec::new();
|
||||||
|
let global_keybindings = Vec::from(SERVARR_CONTEXT_CLUES)
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if let Some(contextual_help) = app.server_tabs.get_active_route_contextual_help() {
|
||||||
|
keybindings.extend(
|
||||||
|
contextual_help
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(contextual_help) = ServarrContextClueProvider::get_context_clues(app) {
|
||||||
|
keybindings.extend(
|
||||||
|
contextual_help
|
||||||
|
.iter()
|
||||||
|
.map(|(key, desc)| context_clue_to_keybinding_item(key, desc)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
keybindings.extend(global_keybindings);
|
||||||
|
|
||||||
|
let mut table = StatefulTable::default();
|
||||||
|
table.set_items(keybindings);
|
||||||
|
app.keymapping_table = Some(table);
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_clear_errors(app: &mut App<'_>) {
|
fn handle_clear_errors(app: &mut App<'_>) {
|
||||||
if !app.error.text.is_empty() {
|
if !app.error.text.is_empty() {
|
||||||
app.error = HorizontallyScrollableText::default();
|
app.error = HorizontallyScrollableText::default();
|
||||||
@@ -115,17 +178,15 @@ fn handle_clear_errors(app: &mut App<'_>) {
|
|||||||
|
|
||||||
fn handle_prompt_toggle(app: &mut App<'_>, key: Key) {
|
fn handle_prompt_toggle(app: &mut App<'_>, key: Key) {
|
||||||
match key {
|
match key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key || key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(left, key) || matches_key!(right, key) => match app.get_current_route() {
|
||||||
match app.get_current_route() {
|
Route::Radarr(_, _) => {
|
||||||
Route::Radarr(_, _) => {
|
app.data.radarr_data.prompt_confirm = !app.data.radarr_data.prompt_confirm
|
||||||
app.data.radarr_data.prompt_confirm = !app.data.radarr_data.prompt_confirm
|
|
||||||
}
|
|
||||||
Route::Sonarr(_, _) => {
|
|
||||||
app.data.sonarr_data.prompt_confirm = !app.data.sonarr_data.prompt_confirm
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
Route::Sonarr(_, _) => {
|
||||||
|
app.data.sonarr_data.prompt_confirm = !app.data.sonarr_data.prompt_confirm
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +210,7 @@ macro_rules! handle_text_box_left_right_keys {
|
|||||||
macro_rules! handle_text_box_keys {
|
macro_rules! handle_text_box_keys {
|
||||||
($self:expr, $key:expr, $input:expr) => {
|
($self:expr, $key:expr, $input:expr) => {
|
||||||
match $self.key {
|
match $self.key {
|
||||||
_ if $key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.backspace.key => {
|
_ if $crate::matches_key!(backspace, $key) => {
|
||||||
$input.pop();
|
$input.pop();
|
||||||
}
|
}
|
||||||
Key::Char(character) => {
|
Key::Char(character) => {
|
||||||
@@ -165,7 +226,7 @@ macro_rules! handle_prompt_left_right_keys {
|
|||||||
($self:expr, $confirm_prompt:expr, $data:ident) => {
|
($self:expr, $confirm_prompt:expr, $data:ident) => {
|
||||||
if $self.app.data.$data.selected_block.get_active_block() == $confirm_prompt {
|
if $self.app.data.$data.selected_block.get_active_block() == $confirm_prompt {
|
||||||
handle_prompt_toggle($self.app, $self.key);
|
handle_prompt_toggle($self.app, $self.key);
|
||||||
} else if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.left.key {
|
} else if $crate::matches_key!(left, $self.key) {
|
||||||
$self.app.data.$data.selected_block.left();
|
$self.app.data.$data.selected_block.left();
|
||||||
} else {
|
} else {
|
||||||
$self.app.data.$data.selected_block.right();
|
$self.app.data.$data.selected_block.right();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod tests {
|
|||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -24,10 +25,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_blocklist_item_prompt() {
|
fn test_delete_blocklist_item_prompt() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
|
|
||||||
BlocklistHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
BlocklistHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -37,12 +38,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_blocklist_item_no_op_when_not_ready() {
|
fn test_delete_blocklist_item_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
|
|
||||||
BlocklistHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
BlocklistHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into());
|
||||||
}
|
}
|
||||||
@@ -56,11 +57,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_blocklist_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_blocklist_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(3);
|
app.data.radarr_data.main_tabs.set_index(3);
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -77,11 +78,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_blocklist_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_blocklist_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(3);
|
app.data.radarr_data.main_tabs.set_index(3);
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -108,13 +109,13 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
BlocklistHandler::with(key, &mut app, active_radarr_block, None).handle();
|
BlocklistHandler::new(key, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
BlocklistHandler::with(key, &mut app, active_radarr_block, None).handle();
|
BlocklistHandler::new(key, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -132,11 +133,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blocklist_submit() {
|
fn test_blocklist_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
|
|
||||||
BlocklistHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
BlocklistHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -146,12 +147,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blocklist_submit_no_op_when_not_ready() {
|
fn test_blocklist_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
|
|
||||||
BlocklistHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
BlocklistHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into());
|
||||||
}
|
}
|
||||||
@@ -172,13 +173,13 @@ mod tests {
|
|||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
#[case] expected_action: RadarrEvent,
|
#[case] expected_action: RadarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
app.push_navigation_stack(base_route.into());
|
app.push_navigation_stack(base_route.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
BlocklistHandler::with(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
BlocklistHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -196,12 +197,12 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
prompt_block: ActiveRadarrBlock,
|
prompt_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
BlocklistHandler::with(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
BlocklistHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
@@ -232,12 +233,12 @@ mod tests {
|
|||||||
#[case] base_block: ActiveRadarrBlock,
|
#[case] base_block: ActiveRadarrBlock,
|
||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(base_block.into());
|
app.push_navigation_stack(base_block.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
BlocklistHandler::with(ESC_KEY, &mut app, prompt_block, None).handle();
|
BlocklistHandler::new(ESC_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), base_block.into());
|
assert_eq!(app.get_current_route(), base_block.into());
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
@@ -245,11 +246,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_esc_blocklist_item_details() {
|
fn test_esc_blocklist_item_details() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::BlocklistItemDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::BlocklistItemDetails.into());
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::BlocklistItemDetails,
|
ActiveRadarrBlock::BlocklistItemDetails,
|
||||||
@@ -262,13 +263,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.error = "test error".to_owned().into();
|
app.error = "test error".to_owned().into();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
|
|
||||||
DownloadsHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
DownloadsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Blocklist, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Blocklist.into());
|
||||||
assert!(app.error.text.is_empty());
|
assert!(app.error.text.is_empty());
|
||||||
@@ -285,11 +286,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_blocklist_key() {
|
fn test_refresh_blocklist_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -303,12 +304,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_blocklist_key_no_op_when_not_ready() {
|
fn test_refresh_blocklist_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -322,10 +323,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clear_blocklist_key() {
|
fn test_clear_blocklist_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.clear.key,
|
DEFAULT_KEYBINDINGS.clear.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -341,12 +342,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clear_blocklist_key_no_op_when_not_ready() {
|
fn test_clear_blocklist_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Blocklist.into());
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.clear.key,
|
DEFAULT_KEYBINDINGS.clear.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -373,12 +374,12 @@ mod tests {
|
|||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
#[case] expected_action: RadarrEvent,
|
#[case] expected_action: RadarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
app.push_navigation_stack(base_route.into());
|
app.push_navigation_stack(base_route.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
BlocklistHandler::with(
|
BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
prompt_block,
|
prompt_block,
|
||||||
@@ -541,12 +542,31 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_blocklist_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = BlocklistHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_blocklist_item_id() {
|
fn test_extract_blocklist_item_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
app.data.radarr_data.blocklist.set_items(blocklist_vec());
|
||||||
|
|
||||||
let blocklist_item_id = BlocklistHandler::with(
|
let blocklist_item_id = BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -559,10 +579,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blocklist_handler_not_ready_when_loading() {
|
fn test_blocklist_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = BlocklistHandler::with(
|
let handler = BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -574,10 +594,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blocklist_handler_not_ready_when_blocklist_is_empty() {
|
fn test_blocklist_handler_not_ready_when_blocklist_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = BlocklistHandler::with(
|
let handler = BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
@@ -589,7 +609,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blocklist_handler_ready_when_not_loading_and_blocklist_is_not_empty() {
|
fn test_blocklist_handler_ready_when_not_loading_and_blocklist_is_not_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -597,7 +617,7 @@ mod tests {
|
|||||||
.blocklist
|
.blocklist
|
||||||
.set_items(vec![BlocklistItem::default()]);
|
.set_items(vec![BlocklistItem::default()]);
|
||||||
|
|
||||||
let handler = BlocklistHandler::with(
|
let handler = BlocklistHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Blocklist,
|
ActiveRadarrBlock::Blocklist,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -9,6 +7,7 @@ use crate::models::radarr_models::BlocklistItem;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS};
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "blocklist_handler_tests.rs"]
|
#[path = "blocklist_handler_tests.rs"]
|
||||||
@@ -21,7 +20,7 @@ pub(super) struct BlocklistHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> BlocklistHandler<'a, 'b> {
|
impl BlocklistHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
blocklist,
|
blocklist,
|
||||||
@@ -51,7 +50,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
BLOCKLIST_BLOCKS.contains(&active_block)
|
BLOCKLIST_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -143,10 +146,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Blocklist => match self.key {
|
ActiveRadarrBlock::Blocklist => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.clear.key => {
|
_ if matches_key!(clear, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::BlocklistClearAllItemsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::BlocklistClearAllItemsPrompt.into());
|
||||||
@@ -154,7 +157,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::DeleteBlocklistItemPrompt => {
|
ActiveRadarrBlock::DeleteBlocklistItemPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteBlocklistItem(
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteBlocklistItem(
|
||||||
self.extract_blocklist_item_id(),
|
self.extract_blocklist_item_id(),
|
||||||
@@ -164,7 +167,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::BlocklistClearAllItemsPrompt => {
|
ActiveRadarrBlock::BlocklistClearAllItemsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::ClearBlocklist);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::ClearBlocklist);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::models::radarr_models::CollectionMovie;
|
use crate::models::radarr_models::CollectionMovie;
|
||||||
@@ -11,6 +9,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
};
|
};
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "collection_details_handler_tests.rs"]
|
#[path = "collection_details_handler_tests.rs"]
|
||||||
@@ -23,7 +22,7 @@ pub(super) struct CollectionDetailsHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> CollectionDetailsHandler<'a, 'b> {
|
impl CollectionDetailsHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
collection_movies,
|
collection_movies,
|
||||||
@@ -46,7 +45,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan
|
|||||||
COLLECTION_DETAILS_BLOCKS.contains(&active_block)
|
COLLECTION_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -130,7 +133,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan
|
|||||||
|
|
||||||
fn handle_char_key_event(&mut self) {
|
fn handle_char_key_event(&mut self) {
|
||||||
if self.active_radarr_block == ActiveRadarrBlock::CollectionDetails
|
if self.active_radarr_block == ActiveRadarrBlock::CollectionDetails
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.edit.key
|
&& matches_key!(edit, self.key)
|
||||||
{
|
{
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -27,7 +28,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_submit() {
|
fn test_collection_details_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -42,7 +43,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -104,7 +105,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_submit_no_op_when_not_ready() {
|
fn test_collection_details_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
||||||
app
|
app
|
||||||
@@ -113,7 +114,7 @@ mod tests {
|
|||||||
.collection_movies
|
.collection_movies
|
||||||
.set_items(vec![CollectionMovie::default()]);
|
.set_items(vec![CollectionMovie::default()]);
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -130,7 +131,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_submit_movie_already_in_library() {
|
fn test_collection_details_submit_movie_already_in_library() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -142,7 +143,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -166,7 +167,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_esc_collection_details(#[values(true, false)] is_ready: bool) {
|
fn test_esc_collection_details(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
||||||
@@ -176,7 +177,7 @@ mod tests {
|
|||||||
.collection_movies
|
.collection_movies
|
||||||
.set_items(vec![CollectionMovie::default()]);
|
.set_items(vec![CollectionMovie::default()]);
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -193,11 +194,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_esc_view_movie_overview() {
|
fn test_esc_view_movie_overview() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into());
|
app.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into());
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::ViewMovieOverview,
|
ActiveRadarrBlock::ViewMovieOverview,
|
||||||
@@ -237,7 +238,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_key_no_op_when_not_ready() {
|
fn test_edit_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
|
||||||
let mut radarr_data = create_test_radarr_data();
|
let mut radarr_data = create_test_radarr_data();
|
||||||
@@ -251,7 +252,7 @@ mod tests {
|
|||||||
}]);
|
}]);
|
||||||
app.data.radarr_data = radarr_data;
|
app.data.radarr_data = radarr_data;
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.edit.key,
|
DEFAULT_KEYBINDINGS.edit.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -278,12 +279,31 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_collection_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = CollectionDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_handler_not_ready_when_loading() {
|
fn test_collection_details_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = CollectionDetailsHandler::with(
|
let handler = CollectionDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -295,10 +315,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_handler_not_ready_when_collection_movies_is_empty() {
|
fn test_collection_details_handler_not_ready_when_collection_movies_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = CollectionDetailsHandler::with(
|
let handler = CollectionDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
@@ -310,7 +330,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_handler_ready_when_not_loading_and_collection_movies_is_not_empty() {
|
fn test_collection_details_handler_ready_when_not_loading_and_collection_movies_is_not_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -318,7 +338,7 @@ mod tests {
|
|||||||
.collection_movies
|
.collection_movies
|
||||||
.set_items(vec![CollectionMovie::default()]);
|
.set_items(vec![CollectionMovie::default()]);
|
||||||
|
|
||||||
let handler = CollectionDetailsHandler::with(
|
let handler = CollectionDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::CollectionDetails,
|
ActiveRadarrBlock::CollectionDetails,
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_collections_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_collections_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(1);
|
app.data.radarr_data.main_tabs.set_index(1);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -49,11 +49,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_collections_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_collections_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(1);
|
app.data.radarr_data.main_tabs.set_index(1);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -72,9 +72,9 @@ mod tests {
|
|||||||
fn test_left_right_update_all_collections_prompt_toggle(
|
fn test_left_right_update_all_collections_prompt_toggle(
|
||||||
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||||
@@ -84,7 +84,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||||
@@ -107,14 +107,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collections_submit() {
|
fn test_collections_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
CollectionsHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle();
|
CollectionsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -124,7 +124,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collections_submit_no_op_when_not_ready() {
|
fn test_collections_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app
|
app
|
||||||
@@ -133,7 +133,7 @@ mod tests {
|
|||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
CollectionsHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle();
|
CollectionsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -143,7 +143,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_collections_prompt_confirm_submit() {
|
fn test_update_all_collections_prompt_confirm_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -153,7 +153,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||||
@@ -174,7 +174,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_collections_prompt_decline_submit() {
|
fn test_update_all_collections_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -183,7 +183,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||||
@@ -211,12 +211,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_collections_prompt_block_esc() {
|
fn test_update_all_collections_prompt_block_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||||
@@ -233,14 +233,14 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.error = "test error".to_owned().into();
|
app.error = "test error".to_owned().into();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
|
|
||||||
CollectionsHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle();
|
CollectionsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Collections, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -272,7 +272,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_edit_key_no_op_when_not_ready() {
|
fn test_collection_edit_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
let mut radarr_data = create_test_radarr_data();
|
let mut radarr_data = create_test_radarr_data();
|
||||||
@@ -286,7 +286,7 @@ mod tests {
|
|||||||
}]);
|
}]);
|
||||||
app.data.radarr_data = radarr_data;
|
app.data.radarr_data = radarr_data;
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.edit.key,
|
DEFAULT_KEYBINDINGS.edit.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -303,14 +303,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_key() {
|
fn test_update_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -326,7 +326,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_key_no_op_when_not_ready() {
|
fn test_update_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app
|
app
|
||||||
@@ -335,7 +335,7 @@ mod tests {
|
|||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -351,7 +351,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_collections_key() {
|
fn test_refresh_collections_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -359,7 +359,7 @@ mod tests {
|
|||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -376,7 +376,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_collections_key_no_op_when_not_ready() {
|
fn test_refresh_collections_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app
|
app
|
||||||
@@ -385,7 +385,7 @@ mod tests {
|
|||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -402,7 +402,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_collections_prompt_confirm_confirm() {
|
fn test_update_all_collections_prompt_confirm_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -411,7 +411,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||||
|
|
||||||
CollectionsHandler::with(
|
CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||||
@@ -589,12 +589,31 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_collections_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = CollectionsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collections_handler_not_ready_when_loading() {
|
fn test_collections_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = CollectionsHandler::with(
|
let handler = CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -606,10 +625,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collections_handler_not_ready_when_collections_is_empty() {
|
fn test_collections_handler_not_ready_when_collections_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = CollectionsHandler::with(
|
let handler = CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -621,7 +640,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collections_handler_ready_when_not_loading_and_collections_is_not_empty() {
|
fn test_collections_handler_ready_when_not_loading_and_collections_is_not_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -629,7 +648,7 @@ mod tests {
|
|||||||
.collections
|
.collections
|
||||||
.set_items(vec![Collection::default()]);
|
.set_items(vec![Collection::default()]);
|
||||||
|
|
||||||
let handler = CollectionsHandler::with(
|
let handler = CollectionsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Collections,
|
ActiveRadarrBlock::Collections,
|
||||||
@@ -644,7 +663,7 @@ mod tests {
|
|||||||
Collection {
|
Collection {
|
||||||
id: 3,
|
id: 3,
|
||||||
title: "test 1".into(),
|
title: "test 1".into(),
|
||||||
movies: Some(iter::repeat(CollectionMovie::default()).take(3).collect()),
|
movies: Some(iter::repeat_n(CollectionMovie::default(), 3).collect()),
|
||||||
root_folder_path: Some("/nfs/movies".into()),
|
root_folder_path: Some("/nfs/movies".into()),
|
||||||
quality_profile_id: 1,
|
quality_profile_id: 1,
|
||||||
search_on_add: false,
|
search_on_add: false,
|
||||||
@@ -654,7 +673,7 @@ mod tests {
|
|||||||
Collection {
|
Collection {
|
||||||
id: 2,
|
id: 2,
|
||||||
title: "test 2".into(),
|
title: "test 2".into(),
|
||||||
movies: Some(iter::repeat(CollectionMovie::default()).take(7).collect()),
|
movies: Some(iter::repeat_n(CollectionMovie::default(), 7).collect()),
|
||||||
root_folder_path: Some("/htpc/movies".into()),
|
root_folder_path: Some("/htpc/movies".into()),
|
||||||
quality_profile_id: 3,
|
quality_profile_id: 3,
|
||||||
search_on_add: true,
|
search_on_add: true,
|
||||||
@@ -664,7 +683,7 @@ mod tests {
|
|||||||
Collection {
|
Collection {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "test 3".into(),
|
title: "test 3".into(),
|
||||||
movies: Some(iter::repeat(CollectionMovie::default()).take(1).collect()),
|
movies: Some(iter::repeat_n(CollectionMovie::default(), 1).collect()),
|
||||||
root_folder_path: Some("/nfs/some/stupidly/long/path/to/test/with".into()),
|
root_folder_path: Some("/nfs/some/stupidly/long/path/to/test/with".into()),
|
||||||
quality_profile_id: 1,
|
quality_profile_id: 1,
|
||||||
search_on_add: false,
|
search_on_add: false,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,7 @@ use crate::models::servarr_data::radarr::modals::EditCollectionModal;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS};
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_collection_handler_tests.rs"]
|
#[path = "edit_collection_handler_tests.rs"]
|
||||||
@@ -20,8 +19,15 @@ pub(super) struct EditCollectionHandler<'a, 'b> {
|
|||||||
context: Option<ActiveRadarrBlock>,
|
context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> EditCollectionHandler<'a, 'b> {
|
impl EditCollectionHandler<'_, '_> {
|
||||||
fn build_edit_collection_params(&mut self) -> EditCollectionParams {
|
fn build_edit_collection_params(&mut self) -> EditCollectionParams {
|
||||||
|
let edit_collection_modal = self
|
||||||
|
.app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.edit_collection_modal
|
||||||
|
.take()
|
||||||
|
.expect("EditCollectionModal is None");
|
||||||
let collection_id = self.app.data.radarr_data.collections.current_selection().id;
|
let collection_id = self.app.data.radarr_data.collections.current_selection().id;
|
||||||
let EditCollectionModal {
|
let EditCollectionModal {
|
||||||
path,
|
path,
|
||||||
@@ -29,13 +35,7 @@ impl<'a, 'b> EditCollectionHandler<'a, 'b> {
|
|||||||
minimum_availability_list,
|
minimum_availability_list,
|
||||||
monitored,
|
monitored,
|
||||||
quality_profile_list,
|
quality_profile_list,
|
||||||
} = self
|
} = edit_collection_modal;
|
||||||
.app
|
|
||||||
.data
|
|
||||||
.radarr_data
|
|
||||||
.edit_collection_modal
|
|
||||||
.as_ref()
|
|
||||||
.unwrap();
|
|
||||||
let quality_profile = quality_profile_list.current_selection();
|
let quality_profile = quality_profile_list.current_selection();
|
||||||
let quality_profile_id = *self
|
let quality_profile_id = *self
|
||||||
.app
|
.app
|
||||||
@@ -48,15 +48,13 @@ impl<'a, 'b> EditCollectionHandler<'a, 'b> {
|
|||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let root_folder_path: String = path.text.clone();
|
let root_folder_path = path.text;
|
||||||
let monitored = monitored.unwrap_or_default();
|
|
||||||
let search_on_add = search_on_add.unwrap_or_default();
|
let search_on_add = search_on_add.unwrap_or_default();
|
||||||
let minimum_availability = *minimum_availability_list.current_selection();
|
let minimum_availability = *minimum_availability_list.current_selection();
|
||||||
self.app.data.radarr_data.edit_collection_modal = None;
|
|
||||||
|
|
||||||
EditCollectionParams {
|
EditCollectionParams {
|
||||||
collection_id,
|
collection_id,
|
||||||
monitored: Some(monitored),
|
monitored,
|
||||||
minimum_availability: Some(minimum_availability),
|
minimum_availability: Some(minimum_availability),
|
||||||
quality_profile_id: Some(quality_profile_id),
|
quality_profile_id: Some(quality_profile_id),
|
||||||
root_folder_path: Some(root_folder_path),
|
root_folder_path: Some(root_folder_path),
|
||||||
@@ -70,7 +68,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
EDIT_COLLECTION_BLOCKS.contains(&active_block)
|
EDIT_COLLECTION_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -263,7 +265,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditCollectionToggleMonitored => {
|
ActiveRadarrBlock::EditCollectionToggleMonitored => {
|
||||||
self
|
self
|
||||||
@@ -312,7 +314,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -322,7 +324,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditCollectionPrompt => {
|
ActiveRadarrBlock::EditCollectionPrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -355,7 +357,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
ActiveRadarrBlock::EditCollectionPrompt => {
|
ActiveRadarrBlock::EditCollectionPrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::EditCollectionConfirmPrompt
|
== ActiveRadarrBlock::EditCollectionConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -32,7 +33,7 @@ mod tests {
|
|||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -45,7 +46,7 @@ mod tests {
|
|||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
for i in (0..minimum_availability_vec.len()).rev() {
|
for i in (0..minimum_availability_vec.len()).rev() {
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
||||||
@@ -67,7 +68,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..minimum_availability_vec.len() {
|
for i in 0..minimum_availability_vec.len() {
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
||||||
@@ -94,7 +95,7 @@ mod tests {
|
|||||||
fn test_edit_collection_select_quality_profile_scroll(
|
fn test_edit_collection_select_quality_profile_scroll(
|
||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -105,7 +106,7 @@ mod tests {
|
|||||||
.quality_profile_list
|
.quality_profile_list
|
||||||
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
||||||
@@ -125,7 +126,7 @@ mod tests {
|
|||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
||||||
@@ -148,13 +149,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_edit_collection_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
EditCollectionHandler::with(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
EditCollectionHandler::new(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
@@ -174,14 +175,14 @@ mod tests {
|
|||||||
fn test_edit_collection_prompt_scroll_no_op_when_not_ready(
|
fn test_edit_collection_prompt_scroll_no_op_when_not_ready(
|
||||||
#[values(Key::Up, Key::Down)] key: Key,
|
#[values(Key::Up, Key::Down)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
EditCollectionHandler::with(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
EditCollectionHandler::new(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -204,7 +205,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_select_minimum_availability_home_end() {
|
fn test_edit_collection_select_minimum_availability_home_end() {
|
||||||
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -215,7 +216,7 @@ mod tests {
|
|||||||
.minimum_availability_list
|
.minimum_availability_list
|
||||||
.set_items(minimum_availability_vec.clone());
|
.set_items(minimum_availability_vec.clone());
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
||||||
@@ -235,7 +236,7 @@ mod tests {
|
|||||||
&minimum_availability_vec[minimum_availability_vec.len() - 1]
|
&minimum_availability_vec[minimum_availability_vec.len() - 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
ActiveRadarrBlock::EditCollectionSelectMinimumAvailability,
|
||||||
@@ -258,7 +259,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_select_quality_profile_scroll() {
|
fn test_edit_collection_select_quality_profile_scroll() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -273,7 +274,7 @@ mod tests {
|
|||||||
"Test 3".to_owned(),
|
"Test 3".to_owned(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
||||||
@@ -293,7 +294,7 @@ mod tests {
|
|||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
ActiveRadarrBlock::EditCollectionSelectQualityProfile,
|
||||||
@@ -316,13 +317,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_home_end_keys() {
|
fn test_edit_collection_root_folder_path_input_home_end_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
||||||
path: "Test".into(),
|
path: "Test".into(),
|
||||||
..EditCollectionModal::default()
|
..EditCollectionModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -343,7 +344,7 @@ mod tests {
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -376,14 +377,14 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
EditCollectionHandler::with(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
EditCollectionHandler::new(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
EditCollectionHandler::with(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
EditCollectionHandler::new(key, &mut app, ActiveRadarrBlock::EditCollectionPrompt, None)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
@@ -391,13 +392,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_left_right_keys() {
|
fn test_edit_collection_root_folder_path_input_left_right_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
||||||
path: "Test".into(),
|
path: "Test".into(),
|
||||||
..EditCollectionModal::default()
|
..EditCollectionModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -418,7 +419,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -456,8 +457,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_submit() {
|
fn test_edit_collection_root_folder_path_input_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
||||||
path: "Test Path".into(),
|
path: "Test Path".into(),
|
||||||
..EditCollectionModal::default()
|
..EditCollectionModal::default()
|
||||||
@@ -465,7 +466,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -473,7 +474,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -491,7 +492,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_prompt_prompt_decline_submit() {
|
fn test_edit_collection_prompt_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
@@ -503,7 +504,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -520,7 +521,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit() {
|
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut edit_collection_modal = EditCollectionModal {
|
let mut edit_collection_modal = EditCollectionModal {
|
||||||
path: "/nfs/Test Path".into(),
|
path: "/nfs/Test Path".into(),
|
||||||
monitored: Some(false),
|
monitored: Some(false),
|
||||||
@@ -560,7 +561,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -582,7 +583,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
fn test_edit_collection_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
@@ -596,7 +597,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -618,13 +619,13 @@ mod tests {
|
|||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
Some(ActiveRadarrBlock::Collections),
|
Some(ActiveRadarrBlock::Collections),
|
||||||
));
|
));
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
app.push_navigation_stack(current_route);
|
app.push_navigation_stack(current_route);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -644,7 +645,7 @@ mod tests {
|
|||||||
Some(true)
|
Some(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -671,7 +672,7 @@ mod tests {
|
|||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
Some(ActiveRadarrBlock::Collections),
|
Some(ActiveRadarrBlock::Collections),
|
||||||
));
|
));
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
@@ -682,7 +683,7 @@ mod tests {
|
|||||||
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 2);
|
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 2);
|
||||||
app.push_navigation_stack(current_route);
|
app.push_navigation_stack(current_route);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -702,7 +703,7 @@ mod tests {
|
|||||||
Some(true)
|
Some(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -731,7 +732,7 @@ mod tests {
|
|||||||
#[case] selected_block: ActiveRadarrBlock,
|
#[case] selected_block: ActiveRadarrBlock,
|
||||||
#[case] index: usize,
|
#[case] index: usize,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.push_navigation_stack(
|
app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
@@ -744,7 +745,7 @@ mod tests {
|
|||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(0, index);
|
app.data.radarr_data.selected_block.set_index(0, index);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -759,7 +760,7 @@ mod tests {
|
|||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
|
|
||||||
if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,12 +773,12 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -791,7 +792,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -808,14 +809,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_esc() {
|
fn test_edit_collection_root_folder_path_input_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -823,7 +824,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::EditCollectionPrompt.into()
|
ActiveRadarrBlock::EditCollectionPrompt.into()
|
||||||
@@ -832,12 +833,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_prompt_esc() {
|
fn test_edit_collection_prompt_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -864,13 +865,13 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
#[values(true, false)] is_ready: bool,
|
#[values(true, false)] is_ready: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Collections.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
EditCollectionHandler::with(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
EditCollectionHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -893,13 +894,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_backspace() {
|
fn test_edit_collection_root_folder_path_input_backspace() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
||||||
path: "Test".into(),
|
path: "Test".into(),
|
||||||
..EditCollectionModal::default()
|
..EditCollectionModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.backspace.key,
|
DEFAULT_KEYBINDINGS.backspace.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
@@ -922,11 +923,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_char_key() {
|
fn test_edit_collection_root_folder_path_input_char_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
None,
|
None,
|
||||||
@@ -942,13 +943,13 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.path
|
.path
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_confirm_prompt_prompt_confirmation_confirm() {
|
fn test_edit_collection_confirm_prompt_prompt_confirmation_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut edit_collection_modal = EditCollectionModal {
|
let mut edit_collection_modal = EditCollectionModal {
|
||||||
path: "/nfs/Test Path".into(),
|
path: "/nfs/Test Path".into(),
|
||||||
monitored: Some(false),
|
monitored: Some(false),
|
||||||
@@ -987,7 +988,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_COLLECTION_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditCollectionHandler::with(
|
EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -1019,9 +1020,28 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_collection_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditCollectionHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_collection_params() {
|
fn test_build_edit_collection_params() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut edit_collection_modal = EditCollectionModal {
|
let mut edit_collection_modal = EditCollectionModal {
|
||||||
path: "/nfs/Test Path".into(),
|
path: "/nfs/Test Path".into(),
|
||||||
monitored: Some(false),
|
monitored: Some(false),
|
||||||
@@ -1051,7 +1071,7 @@ mod tests {
|
|||||||
search_on_add: Some(false),
|
search_on_add: Some(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
let edit_collection_params = EditCollectionHandler::with(
|
let edit_collection_params = EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -1065,10 +1085,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_handler_is_not_ready_when_loading() {
|
fn test_edit_collection_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = EditCollectionHandler::with(
|
let handler = EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -1080,10 +1100,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_handler_is_not_ready_when_edit_collection_modal_is_none() {
|
fn test_edit_collection_handler_is_not_ready_when_edit_collection_modal_is_none() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = EditCollectionHandler::with(
|
let handler = EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
@@ -1095,11 +1115,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_handler_is_ready_when_edit_collection_modal_is_some() {
|
fn test_edit_collection_handler_is_ready_when_edit_collection_modal_is_some() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
|
|
||||||
let handler = EditCollectionHandler::with(
|
let handler = EditCollectionHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionPrompt,
|
ActiveRadarrBlock::EditCollectionPrompt,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler;
|
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::collections::edit_collection_handler::EditCollectionHandler;
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
@@ -14,6 +12,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod collection_details_handler;
|
mod collection_details_handler;
|
||||||
mod edit_collection_handler;
|
mod edit_collection_handler;
|
||||||
@@ -29,7 +28,7 @@ pub(super) struct CollectionsHandler<'a, 'b> {
|
|||||||
context: Option<ActiveRadarrBlock>,
|
context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> CollectionsHandler<'a, 'b> {
|
impl CollectionsHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
collections,
|
collections,
|
||||||
@@ -55,16 +54,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
if !self.handle_collections_table_events(collections_table_handling_config) {
|
if !self.handle_collections_table_events(collections_table_handling_config) {
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
_ if CollectionDetailsHandler::accepts(self.active_radarr_block) => {
|
_ if CollectionDetailsHandler::accepts(self.active_radarr_block) => {
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
self.key,
|
.handle();
|
||||||
self.app,
|
|
||||||
self.active_radarr_block,
|
|
||||||
self.context,
|
|
||||||
)
|
|
||||||
.handle();
|
|
||||||
}
|
}
|
||||||
_ if EditCollectionHandler::accepts(self.active_radarr_block) => {
|
_ if EditCollectionHandler::accepts(self.active_radarr_block) => {
|
||||||
EditCollectionHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
EditCollectionHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle();
|
.handle();
|
||||||
}
|
}
|
||||||
_ => self.handle_key_event(),
|
_ => self.handle_key_event(),
|
||||||
@@ -78,7 +72,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
|| COLLECTIONS_BLOCKS.contains(&active_block)
|
|| COLLECTIONS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -150,7 +148,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Collections => match self.key {
|
ActiveRadarrBlock::Collections => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
@@ -159,18 +157,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
self.app.data.radarr_data.selected_block =
|
self.app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt => {
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateCollections);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateCollections);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -21,14 +22,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_download_prompt() {
|
fn test_delete_download_prompt() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
|
|
||||||
DownloadsHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle();
|
DownloadsHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -38,7 +39,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_download_prompt_no_op_when_not_ready() {
|
fn test_delete_download_prompt_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||||
app
|
app
|
||||||
@@ -47,7 +48,7 @@ mod tests {
|
|||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
|
|
||||||
DownloadsHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle();
|
DownloadsHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into());
|
||||||
}
|
}
|
||||||
@@ -61,11 +62,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_downloads_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_downloads_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(2);
|
app.data.radarr_data.main_tabs.set_index(2);
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -85,11 +86,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_downloads_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_downloads_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(2);
|
app.data.radarr_data.main_tabs.set_index(2);
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -113,13 +114,13 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
DownloadsHandler::with(key, &mut app, active_radarr_block, None).handle();
|
DownloadsHandler::new(key, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
DownloadsHandler::with(key, &mut app, active_radarr_block, None).handle();
|
DownloadsHandler::new(key, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -151,7 +152,7 @@ mod tests {
|
|||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
#[case] expected_action: RadarrEvent,
|
#[case] expected_action: RadarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -161,7 +162,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(base_route.into());
|
app.push_navigation_stack(base_route.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
DownloadsHandler::with(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
DownloadsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -178,7 +179,7 @@ mod tests {
|
|||||||
#[case] base_route: ActiveRadarrBlock,
|
#[case] base_route: ActiveRadarrBlock,
|
||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -187,7 +188,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(base_route.into());
|
app.push_navigation_stack(base_route.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
DownloadsHandler::with(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
DownloadsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
@@ -210,12 +211,12 @@ mod tests {
|
|||||||
#[case] base_block: ActiveRadarrBlock,
|
#[case] base_block: ActiveRadarrBlock,
|
||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(base_block.into());
|
app.push_navigation_stack(base_block.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
DownloadsHandler::with(ESC_KEY, &mut app, prompt_block, None).handle();
|
DownloadsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), base_block.into());
|
assert_eq!(app.get_current_route(), base_block.into());
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
@@ -223,13 +224,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.error = "test error".to_owned().into();
|
app.error = "test error".to_owned().into();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||||
|
|
||||||
DownloadsHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle();
|
DownloadsHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Downloads, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Downloads.into());
|
||||||
assert!(app.error.text.is_empty());
|
assert!(app.error.text.is_empty());
|
||||||
@@ -246,14 +247,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_downloads_key() {
|
fn test_update_downloads_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -269,7 +270,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_downloads_key_no_op_when_not_ready() {
|
fn test_update_downloads_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||||
app
|
app
|
||||||
@@ -278,7 +279,7 @@ mod tests {
|
|||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -291,7 +292,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_downloads_key() {
|
fn test_refresh_downloads_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -299,7 +300,7 @@ mod tests {
|
|||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -313,7 +314,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_downloads_key_no_op_when_not_ready() {
|
fn test_refresh_downloads_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
|
||||||
app
|
app
|
||||||
@@ -322,7 +323,7 @@ mod tests {
|
|||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -350,7 +351,7 @@ mod tests {
|
|||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
#[case] expected_action: RadarrEvent,
|
#[case] expected_action: RadarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -359,7 +360,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(base_route.into());
|
app.push_navigation_stack(base_route.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
DownloadsHandler::with(
|
DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
prompt_block,
|
prompt_block,
|
||||||
@@ -387,16 +388,35 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_downloads_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DownloadsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_download_id() {
|
fn test_extract_download_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![download_record()]);
|
.set_items(vec![download_record()]);
|
||||||
|
|
||||||
let download_id = DownloadsHandler::with(
|
let download_id = DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -409,10 +429,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_downloads_handler_not_ready_when_loading() {
|
fn test_downloads_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = DownloadsHandler::with(
|
let handler = DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -424,10 +444,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_downloads_handler_not_ready_when_downloads_is_empty() {
|
fn test_downloads_handler_not_ready_when_downloads_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = DownloadsHandler::with(
|
let handler = DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
@@ -439,7 +459,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_downloads_handler_ready_when_not_loading_and_downloads_is_not_empty() {
|
fn test_downloads_handler_ready_when_not_loading_and_downloads_is_not_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
app
|
app
|
||||||
@@ -447,7 +467,7 @@ mod tests {
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.downloads
|
.downloads
|
||||||
.set_items(vec![DownloadRecord::default()]);
|
.set_items(vec![DownloadRecord::default()]);
|
||||||
let handler = DownloadsHandler::with(
|
let handler = DownloadsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Downloads,
|
ActiveRadarrBlock::Downloads,
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::radarr_models::DownloadRecord;
|
use crate::models::radarr_models::DownloadRecord;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "downloads_handler_tests.rs"]
|
#[path = "downloads_handler_tests.rs"]
|
||||||
@@ -20,7 +19,7 @@ pub(super) struct DownloadsHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DownloadsHandler<'a, 'b> {
|
impl DownloadsHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
downloads,
|
downloads,
|
||||||
@@ -47,7 +46,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
|||||||
DOWNLOADS_BLOCKS.contains(&active_block)
|
DOWNLOADS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -130,18 +133,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Downloads => match self.key {
|
ActiveRadarrBlock::Downloads => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateDownloadsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateDownloadsPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::DeleteDownloadPrompt => {
|
ActiveRadarrBlock::DeleteDownloadPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::DeleteDownload(self.extract_download_id()));
|
Some(RadarrEvent::DeleteDownload(self.extract_download_id()));
|
||||||
@@ -150,7 +153,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::UpdateDownloadsPrompt => {
|
ActiveRadarrBlock::UpdateDownloadsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateDownloads);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateDownloads);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -6,7 +5,9 @@ use crate::models::servarr_data::modals::EditIndexerModal;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
||||||
use crate::models::servarr_models::EditIndexerParams;
|
use crate::models::servarr_models::EditIndexerParams;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_indexer_handler_tests.rs"]
|
#[path = "edit_indexer_handler_tests.rs"]
|
||||||
@@ -19,58 +20,44 @@ pub(super) struct EditIndexerHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> EditIndexerHandler<'a, 'b> {
|
impl EditIndexerHandler<'_, '_> {
|
||||||
fn build_edit_indexer_params(&mut self) -> EditIndexerParams {
|
fn build_edit_indexer_params(&mut self) -> EditIndexerParams {
|
||||||
let indexer_id = self.app.data.radarr_data.indexers.current_selection().id;
|
let edit_indexer_modal = self
|
||||||
let tags = self
|
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.edit_indexer_modal
|
.edit_indexer_modal
|
||||||
.as_ref()
|
.take()
|
||||||
.unwrap()
|
.expect("Edit Indexer Modal is None");
|
||||||
.tags
|
let indexer_id = self.app.data.radarr_data.indexers.current_selection().id;
|
||||||
.text
|
let tags = edit_indexer_modal.tags.text;
|
||||||
.clone();
|
|
||||||
|
|
||||||
let params = {
|
let EditIndexerModal {
|
||||||
let EditIndexerModal {
|
name,
|
||||||
name,
|
enable_rss,
|
||||||
enable_rss,
|
enable_automatic_search,
|
||||||
enable_automatic_search,
|
enable_interactive_search,
|
||||||
enable_interactive_search,
|
url,
|
||||||
url,
|
api_key,
|
||||||
api_key,
|
seed_ratio,
|
||||||
seed_ratio,
|
priority,
|
||||||
priority,
|
..
|
||||||
..
|
} = edit_indexer_modal;
|
||||||
} = self
|
|
||||||
.app
|
|
||||||
.data
|
|
||||||
.radarr_data
|
|
||||||
.edit_indexer_modal
|
|
||||||
.as_ref()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
EditIndexerParams {
|
EditIndexerParams {
|
||||||
indexer_id,
|
indexer_id,
|
||||||
name: Some(name.text.clone()),
|
name: Some(name.text),
|
||||||
enable_rss: Some(enable_rss.unwrap_or_default()),
|
enable_rss: Some(enable_rss.unwrap_or_default()),
|
||||||
enable_automatic_search: Some(enable_automatic_search.unwrap_or_default()),
|
enable_automatic_search: Some(enable_automatic_search.unwrap_or_default()),
|
||||||
enable_interactive_search: Some(enable_interactive_search.unwrap_or_default()),
|
enable_interactive_search: Some(enable_interactive_search.unwrap_or_default()),
|
||||||
url: Some(url.text.clone()),
|
url: Some(url.text),
|
||||||
api_key: Some(api_key.text.clone()),
|
api_key: Some(api_key.text),
|
||||||
seed_ratio: Some(seed_ratio.text.clone()),
|
seed_ratio: Some(seed_ratio.text),
|
||||||
tags: None,
|
tags: None,
|
||||||
tag_input_string: Some(tags),
|
tag_input_string: Some(tags),
|
||||||
priority: Some(*priority),
|
priority: Some(priority),
|
||||||
clear_tags: false,
|
clear_tags: false,
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
self.app.data.radarr_data.edit_indexer_modal = None;
|
|
||||||
|
|
||||||
params
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +66,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -370,7 +361,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
||||||
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.push_navigation_stack(selected_block.into());
|
self.app.push_navigation_stack(selected_block.into());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditIndexerPriorityInput => self
|
ActiveRadarrBlock::EditIndexerPriorityInput => self
|
||||||
.app
|
.app
|
||||||
@@ -416,7 +407,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
||||||
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditIndexerPriorityInput => self.app.pop_navigation_stack(),
|
ActiveRadarrBlock::EditIndexerPriorityInput => self.app.pop_navigation_stack(),
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -437,7 +428,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveRadarrBlock::EditIndexerPriorityInput
|
| ActiveRadarrBlock::EditIndexerPriorityInput
|
||||||
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => self.app.pop_navigation_stack(),
|
_ => self.app.pop_navigation_stack(),
|
||||||
}
|
}
|
||||||
@@ -518,7 +509,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
ActiveRadarrBlock::EditIndexerPrompt => {
|
ActiveRadarrBlock::EditIndexerPrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::EditIndexerConfirmPrompt
|
== ActiveRadarrBlock::EditIndexerConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,9 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
|
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_indexer_settings_handler_tests.rs"]
|
#[path = "edit_indexer_settings_handler_tests.rs"]
|
||||||
@@ -20,11 +21,15 @@ pub(super) struct IndexerSettingsHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> IndexerSettingsHandler<'a, 'b> {
|
impl IndexerSettingsHandler<'_, '_> {
|
||||||
fn build_edit_indexer_settings_body(&mut self) -> IndexerSettings {
|
fn build_edit_indexer_settings_body(&mut self) -> IndexerSettings {
|
||||||
let indexer_settings = self.app.data.radarr_data.indexer_settings.clone().unwrap();
|
self
|
||||||
self.app.data.radarr_data.indexer_settings = None;
|
.app
|
||||||
indexer_settings
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.indexer_settings
|
||||||
|
.take()
|
||||||
|
.expect("Indexer settings not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +38,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -203,7 +212,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags => {
|
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags => {
|
||||||
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
|
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
|
||||||
@@ -220,7 +229,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput
|
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput
|
||||||
| ActiveRadarrBlock::IndexerSettingsRetentionInput
|
| ActiveRadarrBlock::IndexerSettingsRetentionInput
|
||||||
@@ -240,7 +249,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => self.app.pop_navigation_stack(),
|
_ => self.app.pop_navigation_stack(),
|
||||||
}
|
}
|
||||||
@@ -265,7 +274,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt => {
|
ActiveRadarrBlock::AllIndexerSettingsPrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::IndexerSettingsConfirmPrompt
|
== ActiveRadarrBlock::IndexerSettingsConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(
|
self.app.data.radarr_data.prompt_confirm_action = Some(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -26,10 +27,10 @@ mod tests {
|
|||||||
|
|
||||||
macro_rules! test_i64_counter_scroll_value {
|
macro_rules! test_i64_counter_scroll_value {
|
||||||
($block:expr, $key:expr, $data_ref:ident, $negatives:literal) => {
|
($block:expr, $key:expr, $data_ref:ident, $negatives:literal) => {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
IndexerSettingsHandler::with($key, &mut app, $block, None).handle();
|
IndexerSettingsHandler::new($key, &mut app, $block, None).handle();
|
||||||
|
|
||||||
if $key == Key::Up {
|
if $key == Key::Up {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -66,7 +67,7 @@ mod tests {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(Key::Up, &mut app, $block, None).handle();
|
IndexerSettingsHandler::new(Key::Up, &mut app, $block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
@@ -79,7 +80,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with($key, &mut app, $block, None).handle();
|
IndexerSettingsHandler::new($key, &mut app, $block, None).handle();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -97,13 +98,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_edit_indexer_settings_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_edit_indexer_settings_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -128,14 +129,14 @@ mod tests {
|
|||||||
fn test_edit_indexer_settings_prompt_scroll_no_op_when_not_ready(
|
fn test_edit_indexer_settings_prompt_scroll_no_op_when_not_ready(
|
||||||
#[values(Key::Up, Key::Down)] key: Key,
|
#[values(Key::Up, Key::Down)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -213,13 +214,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whiteliested_subtitle_tags_input_home_end() {
|
fn test_edit_indexer_settings_whiteliested_subtitle_tags_input_home_end() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
||||||
whitelisted_hardcoded_subs: "Test".into(),
|
whitelisted_hardcoded_subs: "Test".into(),
|
||||||
..IndexerSettings::default()
|
..IndexerSettings::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -240,7 +241,7 @@ mod tests {
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -276,12 +277,12 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.y = INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1;
|
app.data.radarr_data.selected_block.y = INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1;
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -291,7 +292,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -329,7 +330,7 @@ mod tests {
|
|||||||
#[case] left_block: ActiveRadarrBlock,
|
#[case] left_block: ActiveRadarrBlock,
|
||||||
#[case] right_block: ActiveRadarrBlock,
|
#[case] right_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.y = starting_y_index;
|
app.data.radarr_data.selected_block.y = starting_y_index;
|
||||||
@@ -339,7 +340,7 @@ mod tests {
|
|||||||
left_block
|
left_block
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -352,7 +353,7 @@ mod tests {
|
|||||||
right_block
|
right_block
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -368,13 +369,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_left_right_keys() {
|
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_left_right_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
||||||
whitelisted_hardcoded_subs: "Test".into(),
|
whitelisted_hardcoded_subs: "Test".into(),
|
||||||
..IndexerSettings::default()
|
..IndexerSettings::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -395,7 +396,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -436,7 +437,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_prompt_prompt_decline_submit() {
|
fn test_edit_indexer_settings_prompt_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
@@ -448,7 +449,7 @@ mod tests {
|
|||||||
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -464,7 +465,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_prompt_prompt_confirmation_submit() {
|
fn test_edit_indexer_settings_prompt_prompt_confirmation_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
@@ -477,7 +478,7 @@ mod tests {
|
|||||||
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -496,14 +497,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
fn test_edit_indexer_settings_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -529,7 +530,7 @@ mod tests {
|
|||||||
#[case] y_index: usize,
|
#[case] y_index: usize,
|
||||||
#[case] x_index: usize,
|
#[case] x_index: usize,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
@@ -540,7 +541,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(x_index, y_index);
|
.set_index(x_index, y_index);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -555,7 +556,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_settings_prompt_submit_selected_block_no_op_when_not_ready(
|
fn test_edit_indexer_settings_prompt_submit_selected_block_no_op_when_not_ready(
|
||||||
#[values((0, 0), (1, 0), (2, 0), (0, 1), (1, 1))] index: (usize, usize),
|
#[values((0, 0), (1, 0), (2, 0), (0, 1), (1, 1))] index: (usize, usize),
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
@@ -567,7 +568,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(index.1, index.0);
|
.set_index(index.1, index.0);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -583,14 +584,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_prompt_submit_whitelisted_subtitle_tags_input() {
|
fn test_edit_indexer_settings_prompt_submit_whitelisted_subtitle_tags_input() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(1, 2);
|
app.data.radarr_data.selected_block.set_index(1, 2);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -602,19 +603,19 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into()
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_toggle_prefer_indexer_flags_submit() {
|
fn test_edit_indexer_settings_toggle_prefer_indexer_flags_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(0, 3);
|
app.data.radarr_data.selected_block.set_index(0, 3);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -636,7 +637,7 @@ mod tests {
|
|||||||
.prefer_indexer_flags
|
.prefer_indexer_flags
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -661,14 +662,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_toggle_allow_hardcoded_subs_submit() {
|
fn test_edit_indexer_settings_toggle_allow_hardcoded_subs_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
BlockSelectionState::new(INDEXER_SETTINGS_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(1, 3);
|
app.data.radarr_data.selected_block.set_index(1, 3);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -690,7 +691,7 @@ mod tests {
|
|||||||
.allow_hardcoded_subs
|
.allow_hardcoded_subs
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -715,8 +716,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_submit() {
|
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
||||||
whitelisted_hardcoded_subs: "Test tags".into(),
|
whitelisted_hardcoded_subs: "Test tags".into(),
|
||||||
..IndexerSettings::default()
|
..IndexerSettings::default()
|
||||||
@@ -726,7 +727,7 @@ mod tests {
|
|||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -734,7 +735,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -761,12 +762,12 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(SUBMIT_KEY, &mut app, active_radarr_block, None).handle();
|
IndexerSettingsHandler::new(SUBMIT_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -787,13 +788,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_edit_indexer_settings_prompt_esc(#[values(true, false)] is_ready: bool) {
|
fn test_edit_indexer_settings_prompt_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -808,15 +809,15 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_esc() {
|
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(
|
app.push_navigation_stack(
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
||||||
);
|
);
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -825,7 +826,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.indexer_settings,
|
app.data.radarr_data.indexer_settings,
|
||||||
Some(IndexerSettings::default())
|
Some(IndexerSettings::default())
|
||||||
@@ -844,12 +845,12 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
IndexerSettingsHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -874,13 +875,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_backspace() {
|
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_backspace() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
||||||
whitelisted_hardcoded_subs: "Test".into(),
|
whitelisted_hardcoded_subs: "Test".into(),
|
||||||
..IndexerSettings::default()
|
..IndexerSettings::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.backspace.key,
|
DEFAULT_KEYBINDINGS.backspace.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
@@ -903,11 +904,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_char_key() {
|
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_char_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -923,13 +924,13 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.whitelisted_hardcoded_subs
|
.whitelisted_hardcoded_subs
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_prompt_prompt_confirmation_confirm() {
|
fn test_edit_indexer_settings_prompt_prompt_confirmation_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
app.data.radarr_data.selected_block =
|
app.data.radarr_data.selected_block =
|
||||||
@@ -941,7 +942,7 @@ mod tests {
|
|||||||
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, INDEXER_SETTINGS_SELECTION_BLOCKS.len() - 1);
|
||||||
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
||||||
|
|
||||||
IndexerSettingsHandler::with(
|
IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -970,12 +971,31 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_indexer_settings_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = IndexerSettingsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_indexer_settings_body() {
|
fn test_build_edit_indexer_settings_body() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
app.data.radarr_data.indexer_settings = Some(indexer_settings());
|
||||||
|
|
||||||
let body = IndexerSettingsHandler::with(
|
let body = IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -989,10 +1009,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_handler_not_ready_when_loading() {
|
fn test_edit_indexer_settings_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = IndexerSettingsHandler::with(
|
let handler = IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -1004,10 +1024,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_handler_not_ready_when_indexer_settings_is_none() {
|
fn test_edit_indexer_settings_handler_not_ready_when_indexer_settings_is_none() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = IndexerSettingsHandler::with(
|
let handler = IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
@@ -1019,11 +1039,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_handler_ready_when_not_loading_and_indexer_settings_is_some() {
|
fn test_edit_indexer_settings_handler_ready_when_not_loading_and_indexer_settings_is_some() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
let handler = IndexerSettingsHandler::with(
|
let handler = IndexerSettingsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_indexer_prompt() {
|
fn test_delete_indexer_prompt() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
IndexersHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -42,7 +42,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_indexer_prompt_no_op_when_not_ready() {
|
fn test_delete_indexer_prompt_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app
|
app
|
||||||
@@ -51,7 +51,7 @@ mod tests {
|
|||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
IndexersHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
}
|
}
|
||||||
@@ -65,11 +65,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_indexers_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_indexers_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(5);
|
app.data.radarr_data.main_tabs.set_index(5);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -89,11 +89,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_indexers_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_indexers_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(5);
|
app.data.radarr_data.main_tabs.set_index(5);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -112,13 +112,13 @@ mod tests {
|
|||||||
fn test_left_right_delete_indexer_prompt_toggle(
|
fn test_left_right_delete_indexer_prompt_toggle(
|
||||||
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
IndexersHandler::with(key, &mut app, ActiveRadarrBlock::DeleteIndexerPrompt, None).handle();
|
IndexersHandler::new(key, &mut app, ActiveRadarrBlock::DeleteIndexerPrompt, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
IndexersHandler::with(key, &mut app, ActiveRadarrBlock::DeleteIndexerPrompt, None).handle();
|
IndexersHandler::new(key, &mut app, ActiveRadarrBlock::DeleteIndexerPrompt, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_edit_indexer_submit(#[values(true, false)] torrent_protocol: bool) {
|
fn test_edit_indexer_submit(#[values(true, false)] torrent_protocol: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let protocol = if torrent_protocol {
|
let protocol = if torrent_protocol {
|
||||||
"torrent".to_owned()
|
"torrent".to_owned()
|
||||||
} else {
|
} else {
|
||||||
@@ -194,7 +194,7 @@ mod tests {
|
|||||||
radarr_data.indexers.set_items(vec![indexer]);
|
radarr_data.indexers.set_items(vec![indexer]);
|
||||||
app.data.radarr_data = radarr_data;
|
app.data.radarr_data = radarr_data;
|
||||||
|
|
||||||
IndexersHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
IndexersHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -223,7 +223,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_submit_no_op_when_not_ready() {
|
fn test_edit_indexer_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app
|
app
|
||||||
@@ -232,7 +232,7 @@ mod tests {
|
|||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
IndexersHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert_eq!(app.data.radarr_data.edit_indexer_modal, None);
|
assert_eq!(app.data.radarr_data.edit_indexer_modal, None);
|
||||||
@@ -240,13 +240,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_indexer_prompt_confirm_submit() {
|
fn test_delete_indexer_prompt_confirm_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteIndexerPrompt,
|
ActiveRadarrBlock::DeleteIndexerPrompt,
|
||||||
@@ -264,7 +264,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_prompt_decline_submit() {
|
fn test_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -273,7 +273,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteIndexerPrompt,
|
ActiveRadarrBlock::DeleteIndexerPrompt,
|
||||||
@@ -296,13 +296,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_delete_indexer_prompt_block_esc(#[values(true, false)] is_ready: bool) {
|
fn test_delete_indexer_prompt_block_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteIndexerPrompt,
|
ActiveRadarrBlock::DeleteIndexerPrompt,
|
||||||
@@ -316,13 +316,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_test_indexer_esc(#[values(true, false)] is_ready: bool) {
|
fn test_test_indexer_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.indexer_test_errors = Some("test result".to_owned());
|
app.data.radarr_data.indexer_test_errors = Some("test result".to_owned());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into());
|
app.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into());
|
||||||
|
|
||||||
IndexersHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::TestIndexer, None).handle();
|
IndexersHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::TestIndexer, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert_eq!(app.data.radarr_data.indexer_test_errors, None);
|
assert_eq!(app.data.radarr_data.indexer_test_errors, None);
|
||||||
@@ -330,13 +330,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.error = "test error".to_owned().into();
|
app.error = "test error".to_owned().into();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
|
|
||||||
IndexersHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
IndexersHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Indexers, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert!(app.error.text.is_empty());
|
assert!(app.error.text.is_empty());
|
||||||
@@ -355,7 +355,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_indexers_key() {
|
fn test_refresh_indexers_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -363,7 +363,7 @@ mod tests {
|
|||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -377,7 +377,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_indexers_key_no_op_when_not_ready() {
|
fn test_refresh_indexers_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -386,7 +386,7 @@ mod tests {
|
|||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -400,14 +400,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_indexer_settings_key() {
|
fn test_indexer_settings_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.settings.key,
|
DEFAULT_KEYBINDINGS.settings.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -427,7 +427,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_indexer_settings_key_no_op_when_not_ready() {
|
fn test_indexer_settings_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app
|
app
|
||||||
@@ -436,7 +436,7 @@ mod tests {
|
|||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.settings.key,
|
DEFAULT_KEYBINDINGS.settings.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -449,14 +449,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_key() {
|
fn test_test_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.test.key,
|
DEFAULT_KEYBINDINGS.test.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -472,7 +472,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_key_no_op_when_not_ready() {
|
fn test_test_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app
|
app
|
||||||
@@ -481,7 +481,7 @@ mod tests {
|
|||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.test.key,
|
DEFAULT_KEYBINDINGS.test.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -494,14 +494,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_key() {
|
fn test_test_all_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.test_all.key,
|
DEFAULT_KEYBINDINGS.test_all.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -517,7 +517,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_key_no_op_when_not_ready() {
|
fn test_test_all_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app
|
app
|
||||||
@@ -526,7 +526,7 @@ mod tests {
|
|||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.test_all.key,
|
DEFAULT_KEYBINDINGS.test_all.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -539,12 +539,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_indexer_prompt_confirm() {
|
fn test_delete_indexer_prompt_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteIndexerPrompt.into());
|
||||||
|
|
||||||
IndexersHandler::with(
|
IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteIndexerPrompt,
|
ActiveRadarrBlock::DeleteIndexerPrompt,
|
||||||
@@ -633,12 +633,31 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_indexers_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = IndexersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_indexer_id() {
|
fn test_extract_indexer_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
app.data.radarr_data.indexers.set_items(vec![indexer()]);
|
||||||
|
|
||||||
let indexer_id = IndexersHandler::with(
|
let indexer_id = IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -651,10 +670,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_indexers_handler_not_ready_when_loading() {
|
fn test_indexers_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = IndexersHandler::with(
|
let handler = IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -666,10 +685,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_indexers_handler_not_ready_when_indexers_is_empty() {
|
fn test_indexers_handler_not_ready_when_indexers_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = IndexersHandler::with(
|
let handler = IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
@@ -681,7 +700,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_indexers_handler_ready_when_not_loading_and_indexers_is_not_empty() {
|
fn test_indexers_handler_ready_when_not_loading_and_indexers_is_not_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -689,7 +708,7 @@ mod tests {
|
|||||||
.indexers
|
.indexers
|
||||||
.set_items(vec![Indexer::default()]);
|
.set_items(vec![Indexer::default()]);
|
||||||
|
|
||||||
let handler = IndexersHandler::with(
|
let handler = IndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Indexers,
|
ActiveRadarrBlock::Indexers,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
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_handler::EditIndexerHandler;
|
||||||
use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
||||||
@@ -15,6 +13,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::servarr_models::Indexer;
|
use crate::models::servarr_models::Indexer;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod edit_indexer_handler;
|
mod edit_indexer_handler;
|
||||||
mod edit_indexer_settings_handler;
|
mod edit_indexer_settings_handler;
|
||||||
@@ -31,7 +30,7 @@ pub(super) struct IndexersHandler<'a, 'b> {
|
|||||||
context: Option<ActiveRadarrBlock>,
|
context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> IndexersHandler<'a, 'b> {
|
impl IndexersHandler<'_, '_> {
|
||||||
handle_table_events!(self, indexers, self.app.data.radarr_data.indexers, Indexer);
|
handle_table_events!(self, indexers, self.app.data.radarr_data.indexers, Indexer);
|
||||||
|
|
||||||
fn extract_indexer_id(&self) -> i64 {
|
fn extract_indexer_id(&self) -> i64 {
|
||||||
@@ -47,15 +46,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
if !self.handle_indexers_table_events(indexer_table_handling_config) {
|
if !self.handle_indexers_table_events(indexer_table_handling_config) {
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
_ if EditIndexerHandler::accepts(self.active_radarr_block) => {
|
_ if EditIndexerHandler::accepts(self.active_radarr_block) => {
|
||||||
EditIndexerHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
EditIndexerHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle()
|
.handle()
|
||||||
}
|
}
|
||||||
_ if IndexerSettingsHandler::accepts(self.active_radarr_block) => {
|
_ if IndexerSettingsHandler::accepts(self.active_radarr_block) => {
|
||||||
IndexerSettingsHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
IndexerSettingsHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle()
|
.handle()
|
||||||
}
|
}
|
||||||
_ if TestAllIndexersHandler::accepts(self.active_radarr_block) => {
|
_ if TestAllIndexersHandler::accepts(self.active_radarr_block) => {
|
||||||
TestAllIndexersHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
TestAllIndexersHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle()
|
.handle()
|
||||||
}
|
}
|
||||||
_ => self.handle_key_event(),
|
_ => self.handle_key_event(),
|
||||||
@@ -70,7 +69,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
|| INDEXERS_BLOCKS.contains(&active_block)
|
|| INDEXERS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -169,20 +172,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Indexers => match self.key {
|
ActiveRadarrBlock::Indexers => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.test.key => {
|
_ if matches_key!(test, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into());
|
.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.test_all.key => {
|
_ if matches_key!(test_all, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into());
|
.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.settings.key => {
|
_ if matches_key!(settings, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
@@ -192,7 +195,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::DeleteIndexerPrompt => {
|
ActiveRadarrBlock::DeleteIndexerPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
Some(RadarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub(super) struct TestAllIndexersHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> TestAllIndexersHandler<'a, 'b> {
|
impl TestAllIndexersHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
indexer_test_all_results,
|
indexer_test_all_results,
|
||||||
@@ -48,7 +48,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for TestAllIndexersHandl
|
|||||||
active_block == ActiveRadarrBlock::TestAllIndexers
|
active_block == ActiveRadarrBlock::TestAllIndexers
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ mod tests {
|
|||||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
mod test_handle_esc {
|
mod test_handle_esc {
|
||||||
@@ -17,13 +18,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_test_all_indexers_esc(#[values(true, false)] is_ready: bool) {
|
fn test_test_all_indexers_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into());
|
||||||
app.data.radarr_data.indexer_test_all_results = Some(StatefulTable::default());
|
app.data.radarr_data.indexer_test_all_results = Some(StatefulTable::default());
|
||||||
|
|
||||||
TestAllIndexersHandler::with(
|
TestAllIndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::TestAllIndexers,
|
ActiveRadarrBlock::TestAllIndexers,
|
||||||
@@ -48,12 +49,31 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_test_all_indexers_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = TestAllIndexersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_indexers_handler_is_not_ready_when_loading() {
|
fn test_test_all_indexers_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = TestAllIndexersHandler::with(
|
let handler = TestAllIndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::TestAllIndexers,
|
ActiveRadarrBlock::TestAllIndexers,
|
||||||
@@ -65,10 +85,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_indexers_handler_is_not_ready_when_results_is_none() {
|
fn test_test_all_indexers_handler_is_not_ready_when_results_is_none() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = TestAllIndexersHandler::with(
|
let handler = TestAllIndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::TestAllIndexers,
|
ActiveRadarrBlock::TestAllIndexers,
|
||||||
@@ -80,11 +100,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_indexers_handler_is_not_ready_when_results_is_empty() {
|
fn test_test_all_indexers_handler_is_not_ready_when_results_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app.data.radarr_data.indexer_test_all_results = Some(StatefulTable::default());
|
app.data.radarr_data.indexer_test_all_results = Some(StatefulTable::default());
|
||||||
|
|
||||||
let handler = TestAllIndexersHandler::with(
|
let handler = TestAllIndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::TestAllIndexers,
|
ActiveRadarrBlock::TestAllIndexers,
|
||||||
@@ -96,13 +116,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_indexers_handler_is_ready_when_results_is_not_empty_and_is_loaded() {
|
fn test_test_all_indexers_handler_is_ready_when_results_is_not_empty_and_is_loaded() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
let mut indexer_test_results = StatefulTable::default();
|
let mut indexer_test_results = StatefulTable::default();
|
||||||
indexer_test_results.set_items(vec![IndexerTestResultModalItem::default()]);
|
indexer_test_results.set_items(vec![IndexerTestResultModalItem::default()]);
|
||||||
app.data.radarr_data.indexer_test_all_results = Some(indexer_test_results);
|
app.data.radarr_data.indexer_test_all_results = Some(indexer_test_results);
|
||||||
|
|
||||||
let handler = TestAllIndexersHandler::with(
|
let handler = TestAllIndexersHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::TestAllIndexers,
|
ActiveRadarrBlock::TestAllIndexers,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
@@ -11,7 +10,9 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{BlockSelectionState, Scrollable};
|
use crate::models::{BlockSelectionState, Scrollable};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
|
use crate::{
|
||||||
|
handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, App, Key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "add_movie_handler_tests.rs"]
|
#[path = "add_movie_handler_tests.rs"]
|
||||||
@@ -24,7 +25,7 @@ pub(super) struct AddMovieHandler<'a, 'b> {
|
|||||||
context: Option<ActiveRadarrBlock>,
|
context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
impl AddMovieHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
add_movie_search_results,
|
add_movie_search_results,
|
||||||
@@ -39,23 +40,21 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
fn build_add_movie_body(&mut self) -> AddMovieBody {
|
fn build_add_movie_body(&mut self) -> AddMovieBody {
|
||||||
let tags = self
|
let add_movie_modal = self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.add_movie_modal
|
.add_movie_modal
|
||||||
.as_ref()
|
.take()
|
||||||
.unwrap()
|
.expect("AddMovieModal is None");
|
||||||
.tags
|
let tags = add_movie_modal.tags.text;
|
||||||
.text
|
|
||||||
.clone();
|
|
||||||
let AddMovieModal {
|
let AddMovieModal {
|
||||||
root_folder_list,
|
root_folder_list,
|
||||||
monitor_list,
|
monitor_list,
|
||||||
minimum_availability_list,
|
minimum_availability_list,
|
||||||
quality_profile_list,
|
quality_profile_list,
|
||||||
..
|
..
|
||||||
} = self.app.data.radarr_data.add_movie_modal.as_ref().unwrap();
|
} = add_movie_modal;
|
||||||
let (tmdb_id, title) = if let Some(context) = self.context {
|
let (tmdb_id, title) = if let Some(context) = self.context {
|
||||||
if context == ActiveRadarrBlock::CollectionDetails {
|
if context == ActiveRadarrBlock::CollectionDetails {
|
||||||
let CollectionMovie { tmdb_id, title, .. } = self
|
let CollectionMovie { tmdb_id, title, .. } = self
|
||||||
@@ -63,9 +62,8 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
|||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.collection_movies
|
.collection_movies
|
||||||
.current_selection()
|
.current_selection();
|
||||||
.clone();
|
(*tmdb_id, title.clone().text)
|
||||||
(tmdb_id, title.text)
|
|
||||||
} else {
|
} else {
|
||||||
let AddMovieSearchResult { tmdb_id, title, .. } = self
|
let AddMovieSearchResult { tmdb_id, title, .. } = self
|
||||||
.app
|
.app
|
||||||
@@ -74,9 +72,8 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
|||||||
.add_searched_movies
|
.add_searched_movies
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.current_selection()
|
.current_selection();
|
||||||
.clone();
|
(*tmdb_id, title.clone().text)
|
||||||
(tmdb_id, title.text)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let AddMovieSearchResult { tmdb_id, title, .. } = self
|
let AddMovieSearchResult { tmdb_id, title, .. } = self
|
||||||
@@ -86,9 +83,8 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
|||||||
.add_searched_movies
|
.add_searched_movies
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.current_selection()
|
.current_selection();
|
||||||
.clone();
|
(*tmdb_id, title.clone().text)
|
||||||
(tmdb_id, title.text)
|
|
||||||
};
|
};
|
||||||
let quality_profile = quality_profile_list.current_selection();
|
let quality_profile = quality_profile_list.current_selection();
|
||||||
let quality_profile_id = *self
|
let quality_profile_id = *self
|
||||||
@@ -106,8 +102,6 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> {
|
|||||||
let monitor = monitor_list.current_selection().to_string();
|
let monitor = monitor_list.current_selection().to_string();
|
||||||
let minimum_availability = minimum_availability_list.current_selection().to_string();
|
let minimum_availability = minimum_availability_list.current_selection().to_string();
|
||||||
|
|
||||||
self.app.data.radarr_data.add_movie_modal = None;
|
|
||||||
|
|
||||||
AddMovieBody {
|
AddMovieBody {
|
||||||
tmdb_id,
|
tmdb_id,
|
||||||
title,
|
title,
|
||||||
@@ -139,7 +133,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
ADD_MOVIE_BLOCKS.contains(&active_block)
|
ADD_MOVIE_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -411,7 +409,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ if self.active_radarr_block == ActiveRadarrBlock::AddMovieSearchResults
|
_ if self.active_radarr_block == ActiveRadarrBlock::AddMovieSearchResults
|
||||||
&& self.app.data.radarr_data.add_searched_movies.is_some() =>
|
&& self.app.data.radarr_data.add_searched_movies.is_some() =>
|
||||||
@@ -475,7 +473,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -486,7 +484,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::AddMovieTagsInput => {
|
ActiveRadarrBlock::AddMovieTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -497,12 +495,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
ActiveRadarrBlock::AddMovieSearchInput => {
|
ActiveRadarrBlock::AddMovieSearchInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.radarr_data.add_movie_search = None;
|
self.app.data.radarr_data.add_movie_search = None;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMovieSearchResults | ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
ActiveRadarrBlock::AddMovieSearchResults | ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.radarr_data.add_searched_movies = None;
|
self.app.data.radarr_data.add_searched_movies = None;
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMoviePrompt => {
|
ActiveRadarrBlock::AddMoviePrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -516,7 +514,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::AddMovieTagsInput => {
|
ActiveRadarrBlock::AddMovieTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -549,7 +547,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
ActiveRadarrBlock::AddMoviePrompt => {
|
ActiveRadarrBlock::AddMoviePrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::AddMovieConfirmPrompt
|
== ActiveRadarrBlock::AddMovieConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ mod tests {
|
|||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let monitor_vec = Vec::from_iter(MovieMonitor::iter());
|
let monitor_vec = Vec::from_iter(MovieMonitor::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -50,7 +50,7 @@ mod tests {
|
|||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
for i in (0..monitor_vec.len()).rev() {
|
for i in (0..monitor_vec.len()).rev() {
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMonitor,
|
ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
@@ -72,7 +72,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..monitor_vec.len() {
|
for i in 0..monitor_vec.len() {
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMonitor,
|
ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
@@ -100,7 +100,7 @@ mod tests {
|
|||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -113,7 +113,7 @@ mod tests {
|
|||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
for i in (0..minimum_availability_vec.len()).rev() {
|
for i in (0..minimum_availability_vec.len()).rev() {
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
||||||
@@ -135,7 +135,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..minimum_availability_vec.len() {
|
for i in 0..minimum_availability_vec.len() {
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
||||||
@@ -162,7 +162,7 @@ mod tests {
|
|||||||
fn test_add_movie_select_quality_profile_scroll(
|
fn test_add_movie_select_quality_profile_scroll(
|
||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -173,7 +173,7 @@ mod tests {
|
|||||||
.quality_profile_list
|
.quality_profile_list
|
||||||
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
||||||
@@ -193,7 +193,7 @@ mod tests {
|
|||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
||||||
@@ -218,7 +218,7 @@ mod tests {
|
|||||||
fn test_add_movie_select_root_folder_scroll(
|
fn test_add_movie_select_root_folder_scroll(
|
||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -229,7 +229,7 @@ mod tests {
|
|||||||
.root_folder_list
|
.root_folder_list
|
||||||
.set_items(simple_stateful_iterable_vec!(RootFolder, String, path));
|
.set_items(simple_stateful_iterable_vec!(RootFolder, String, path));
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
||||||
@@ -250,7 +250,7 @@ mod tests {
|
|||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
||||||
@@ -274,11 +274,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_add_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
AddMovieHandler::with(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
AddMovieHandler::new(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -295,12 +295,12 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_add_movie_prompt_scroll_no_op_when_not_ready(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_add_movie_prompt_scroll_no_op_when_not_ready(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
AddMovieHandler::with(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
AddMovieHandler::new(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.selected_block.get_active_block(),
|
app.data.radarr_data.selected_block.get_active_block(),
|
||||||
@@ -322,7 +322,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_select_monitor_home_end() {
|
fn test_add_movie_select_monitor_home_end() {
|
||||||
let monitor_vec = Vec::from_iter(MovieMonitor::iter());
|
let monitor_vec = Vec::from_iter(MovieMonitor::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -333,7 +333,7 @@ mod tests {
|
|||||||
.monitor_list
|
.monitor_list
|
||||||
.set_items(monitor_vec.clone());
|
.set_items(monitor_vec.clone());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMonitor,
|
ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
@@ -353,7 +353,7 @@ mod tests {
|
|||||||
&monitor_vec[monitor_vec.len() - 1]
|
&monitor_vec[monitor_vec.len() - 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMonitor,
|
ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
@@ -377,7 +377,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_select_minimum_availability_home_end() {
|
fn test_add_movie_select_minimum_availability_home_end() {
|
||||||
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -388,7 +388,7 @@ mod tests {
|
|||||||
.minimum_availability_list
|
.minimum_availability_list
|
||||||
.set_items(minimum_availability_vec.clone());
|
.set_items(minimum_availability_vec.clone());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
||||||
@@ -408,7 +408,7 @@ mod tests {
|
|||||||
&minimum_availability_vec[minimum_availability_vec.len() - 1]
|
&minimum_availability_vec[minimum_availability_vec.len() - 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
||||||
@@ -431,7 +431,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_select_quality_profile_home_end() {
|
fn test_add_movie_select_quality_profile_home_end() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -446,7 +446,7 @@ mod tests {
|
|||||||
"Test 3".to_owned(),
|
"Test 3".to_owned(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
||||||
@@ -466,7 +466,7 @@ mod tests {
|
|||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
ActiveRadarrBlock::AddMovieSelectQualityProfile,
|
||||||
@@ -489,7 +489,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_select_root_folder_home_end() {
|
fn test_add_movie_select_root_folder_home_end() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -500,7 +500,7 @@ mod tests {
|
|||||||
.root_folder_list
|
.root_folder_list
|
||||||
.set_items(extended_stateful_iterable_vec!(RootFolder, String, path));
|
.set_items(extended_stateful_iterable_vec!(RootFolder, String, path));
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
||||||
@@ -521,7 +521,7 @@ mod tests {
|
|||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
ActiveRadarrBlock::AddMovieSelectRootFolder,
|
||||||
@@ -545,10 +545,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_home_end_keys() {
|
fn test_add_movie_search_input_home_end_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_search = Some("Test".into());
|
app.data.radarr_data.add_movie_search = Some("Test".into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -568,7 +568,7 @@ mod tests {
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -591,13 +591,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_tags_input_home_end_keys() {
|
fn test_add_movie_tags_input_home_end_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal {
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..AddMovieModal::default()
|
..AddMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -618,7 +618,7 @@ mod tests {
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -651,23 +651,23 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
AddMovieHandler::with(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
AddMovieHandler::new(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
AddMovieHandler::with(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
AddMovieHandler::new(key, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_left_right_keys() {
|
fn test_add_movie_search_input_left_right_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_search = Some("Test".into());
|
app.data.radarr_data.add_movie_search = Some("Test".into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -687,7 +687,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -710,13 +710,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_tags_input_left_right_keys() {
|
fn test_add_movie_tags_input_left_right_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal {
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..AddMovieModal::default()
|
..AddMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -737,7 +737,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -781,11 +781,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_submit() {
|
fn test_add_movie_search_input_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.add_movie_search = Some("test".into());
|
app.data.radarr_data.add_movie_search = Some("test".into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -793,7 +793,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchResults.into()
|
ActiveRadarrBlock::AddMovieSearchResults.into()
|
||||||
@@ -802,12 +802,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_submit_noop_on_empty_search() {
|
fn test_add_movie_search_input_submit_noop_on_empty_search() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -815,7 +815,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchInput.into()
|
ActiveRadarrBlock::AddMovieSearchInput.into()
|
||||||
@@ -824,14 +824,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_results_submit() {
|
fn test_add_movie_search_results_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut add_searched_movies = StatefulTable::default();
|
let mut add_searched_movies = StatefulTable::default();
|
||||||
add_searched_movies.set_items(vec![AddMovieSearchResult::default()]);
|
add_searched_movies.set_items(vec![AddMovieSearchResult::default()]);
|
||||||
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
||||||
app.data.radarr_data.quality_profile_map =
|
app.data.radarr_data.quality_profile_map =
|
||||||
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
|
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
@@ -890,13 +890,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_results_submit_no_op_when_not_ready() {
|
fn test_add_movie_search_results_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
||||||
let mut add_searched_movies = StatefulTable::default();
|
let mut add_searched_movies = StatefulTable::default();
|
||||||
add_searched_movies.set_items(vec![AddMovieSearchResult::default()]);
|
add_searched_movies.set_items(vec![AddMovieSearchResult::default()]);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
@@ -913,9 +913,9 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_results_submit_does_nothing_on_empty_table() {
|
fn test_add_movie_search_results_submit_does_nothing_on_empty_table() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
@@ -931,7 +931,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_results_submit_movie_already_in_library() {
|
fn test_add_movie_search_results_submit_movie_already_in_library() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut add_searched_movies = StatefulTable::default();
|
let mut add_searched_movies = StatefulTable::default();
|
||||||
add_searched_movies.set_items(vec![AddMovieSearchResult::default()]);
|
add_searched_movies.set_items(vec![AddMovieSearchResult::default()]);
|
||||||
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
||||||
@@ -941,7 +941,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
@@ -957,7 +957,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_prompt_prompt_decline_submit() {
|
fn test_add_movie_prompt_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
||||||
@@ -967,7 +967,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, ADD_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -983,7 +983,7 @@ mod tests {
|
|||||||
fn test_add_movie_confirm_prompt_prompt_confirmation_submit(
|
fn test_add_movie_confirm_prompt_prompt_confirmation_submit(
|
||||||
#[values(true, false)] movie_details_context: bool,
|
#[values(true, false)] movie_details_context: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
@@ -1041,7 +1041,7 @@ mod tests {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1067,7 +1067,7 @@ mod tests {
|
|||||||
#[case] selected_block: ActiveRadarrBlock,
|
#[case] selected_block: ActiveRadarrBlock,
|
||||||
#[case] y_index: usize,
|
#[case] y_index: usize,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(
|
app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1078,7 +1078,7 @@ mod tests {
|
|||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(ADD_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(0, y_index);
|
app.data.radarr_data.selected_block.set_index(0, y_index);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1093,7 +1093,7 @@ mod tests {
|
|||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
|
|
||||||
if selected_block == ActiveRadarrBlock::AddMovieTagsInput {
|
if selected_block == ActiveRadarrBlock::AddMovieTagsInput {
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,11 +1108,11 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -1126,7 +1126,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput {
|
if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput {
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1146,13 +1146,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_add_movie_search_input_esc(#[values(true, false)] is_ready: bool) {
|
fn test_add_movie_search_input_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -1160,20 +1160,20 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert_eq!(app.data.radarr_data.add_movie_search, None);
|
assert_eq!(app.data.radarr_data.add_movie_search, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_input_esc() {
|
fn test_add_movie_input_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -1181,7 +1181,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMoviePrompt.into()
|
ActiveRadarrBlock::AddMoviePrompt.into()
|
||||||
@@ -1196,7 +1196,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
let mut add_searched_movies = StatefulTable::default();
|
let mut add_searched_movies = StatefulTable::default();
|
||||||
@@ -1206,24 +1206,24 @@ mod tests {
|
|||||||
));
|
));
|
||||||
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
app.data.radarr_data.add_searched_movies = Some(add_searched_movies);
|
||||||
|
|
||||||
AddMovieHandler::with(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
AddMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchInput.into()
|
ActiveRadarrBlock::AddMovieSearchInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.data.radarr_data.add_searched_movies.is_none());
|
assert!(app.data.radarr_data.add_searched_movies.is_none());
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_already_in_library_esc() {
|
fn test_add_movie_already_in_library_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieAlreadyInLibrary.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieAlreadyInLibrary.into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieAlreadyInLibrary,
|
ActiveRadarrBlock::AddMovieAlreadyInLibrary,
|
||||||
@@ -1239,13 +1239,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_prompt_esc() {
|
fn test_add_movie_prompt_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
|
|
||||||
AddMovieHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
AddMovieHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::AddMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1257,13 +1257,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_tags_input_esc() {
|
fn test_add_movie_tags_input_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -1271,7 +1271,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMoviePrompt.into()
|
ActiveRadarrBlock::AddMoviePrompt.into()
|
||||||
@@ -1288,7 +1288,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(
|
app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1304,7 +1304,7 @@ mod tests {
|
|||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -1343,10 +1343,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_backspace() {
|
fn test_add_movie_search_input_backspace() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_search = Some("Test".into());
|
app.data.radarr_data.add_movie_search = Some("Test".into());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.backspace.key,
|
DEFAULT_KEYBINDINGS.backspace.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
@@ -1362,13 +1362,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_tags_input_backspace() {
|
fn test_add_movie_tags_input_backspace() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal {
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..AddMovieModal::default()
|
..AddMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.backspace.key,
|
DEFAULT_KEYBINDINGS.backspace.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
@@ -1391,11 +1391,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_char_key() {
|
fn test_add_movie_search_input_char_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
None,
|
None,
|
||||||
@@ -1404,17 +1404,17 @@ mod tests {
|
|||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
app.data.radarr_data.add_movie_search.as_ref().unwrap().text,
|
app.data.radarr_data.add_movie_search.as_ref().unwrap().text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_tags_input_char_key() {
|
fn test_add_movie_tags_input_char_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1430,7 +1430,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1438,7 +1438,7 @@ mod tests {
|
|||||||
fn test_add_movie_confirm_prompt_prompt_confirmation_confirm(
|
fn test_add_movie_confirm_prompt_prompt_confirmation_confirm(
|
||||||
#[values(true, false)] movie_details_context: bool,
|
#[values(true, false)] movie_details_context: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
@@ -1495,7 +1495,7 @@ mod tests {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1523,12 +1523,31 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_add_movie_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = AddMovieHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_no_panic_on_none_search_result() {
|
fn test_add_movie_search_no_panic_on_none_search_result() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_searched_movies = None;
|
app.data.radarr_data.add_searched_movies = None;
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
@@ -1539,7 +1558,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_build_add_movie_body(#[values(true, false)] movie_details_context: bool) {
|
fn test_build_add_movie_body(#[values(true, false)] movie_details_context: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut add_movie_modal = AddMovieModal {
|
let mut add_movie_modal = AddMovieModal {
|
||||||
tags: "usenet, testing".into(),
|
tags: "usenet, testing".into(),
|
||||||
..AddMovieModal::default()
|
..AddMovieModal::default()
|
||||||
@@ -1586,7 +1605,7 @@ mod tests {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let actual_add_movie_body = AddMovieHandler::with(
|
let actual_add_movie_body = AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1599,10 +1618,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_handler_is_not_ready_when_loading() {
|
fn test_add_movie_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = AddMovieHandler::with(
|
let handler = AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
@@ -1614,10 +1633,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_handler_is_ready_when_not_loading() {
|
fn test_add_movie_handler_is_ready_when_not_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = AddMovieHandler::with(
|
let handler = AddMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::radarr_models::DeleteMovieParams;
|
use crate::models::radarr_models::DeleteMovieParams;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
@@ -17,7 +17,7 @@ pub(super) struct DeleteMovieHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DeleteMovieHandler<'a, 'b> {
|
impl DeleteMovieHandler<'_, '_> {
|
||||||
fn build_delete_movie_params(&mut self) -> DeleteMovieParams {
|
fn build_delete_movie_params(&mut self) -> DeleteMovieParams {
|
||||||
let id = self.app.data.radarr_data.movies.current_selection().id;
|
let id = self.app.data.radarr_data.movies.current_selection().id;
|
||||||
let delete_movie_files = self.app.data.radarr_data.delete_movie_files;
|
let delete_movie_files = self.app.data.radarr_data.delete_movie_files;
|
||||||
@@ -37,7 +37,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
|
|||||||
DELETE_MOVIE_BLOCKS.contains(&active_block)
|
DELETE_MOVIE_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -122,7 +126,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
|
|||||||
if self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt
|
if self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt
|
||||||
&& self.app.data.radarr_data.selected_block.get_active_block()
|
&& self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::DeleteMovieConfirmPrompt
|
== ActiveRadarrBlock::DeleteMovieConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -23,11 +24,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_delete_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
DeleteMovieHandler::with(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
DeleteMovieHandler::new(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -46,12 +47,12 @@ mod tests {
|
|||||||
fn test_delete_movie_prompt_scroll_no_op_when_not_ready(
|
fn test_delete_movie_prompt_scroll_no_op_when_not_ready(
|
||||||
#[values(Key::Up, Key::Down)] key: Key,
|
#[values(Key::Up, Key::Down)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
DeleteMovieHandler::with(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
DeleteMovieHandler::new(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.selected_block.get_active_block(),
|
app.data.radarr_data.selected_block.get_active_block(),
|
||||||
@@ -67,13 +68,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
DeleteMovieHandler::with(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
DeleteMovieHandler::new(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
DeleteMovieHandler::with(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
DeleteMovieHandler::new(key, &mut app, ActiveRadarrBlock::DeleteMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_prompt_prompt_decline_submit() {
|
fn test_delete_movie_prompt_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
||||||
@@ -104,7 +105,7 @@ mod tests {
|
|||||||
app.data.radarr_data.delete_movie_files = true;
|
app.data.radarr_data.delete_movie_files = true;
|
||||||
app.data.radarr_data.add_list_exclusion = true;
|
app.data.radarr_data.add_list_exclusion = true;
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -121,7 +122,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit() {
|
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let expected_delete_movie_params = DeleteMovieParams {
|
let expected_delete_movie_params = DeleteMovieParams {
|
||||||
id: 1,
|
id: 1,
|
||||||
delete_movie_files: true,
|
delete_movie_files: true,
|
||||||
@@ -140,7 +141,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -161,7 +162,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
fn test_delete_movie_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
||||||
@@ -169,7 +170,7 @@ mod tests {
|
|||||||
app.data.radarr_data.delete_movie_files = true;
|
app.data.radarr_data.delete_movie_files = true;
|
||||||
app.data.radarr_data.add_list_exclusion = true;
|
app.data.radarr_data.add_list_exclusion = true;
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -191,11 +192,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_toggle_delete_files_submit() {
|
fn test_delete_movie_toggle_delete_files_submit() {
|
||||||
let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into();
|
let current_route = ActiveRadarrBlock::DeleteMoviePrompt.into();
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(DELETE_MOVIE_SELECTION_BLOCKS);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -206,7 +207,7 @@ mod tests {
|
|||||||
assert_eq!(app.get_current_route(), current_route);
|
assert_eq!(app.get_current_route(), current_route);
|
||||||
assert_eq!(app.data.radarr_data.delete_movie_files, true);
|
assert_eq!(app.data.radarr_data.delete_movie_files, true);
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -228,7 +229,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_delete_movie_prompt_esc(#[values(true, false)] is_ready: bool) {
|
fn test_delete_movie_prompt_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::DeleteMoviePrompt.into());
|
||||||
@@ -236,7 +237,7 @@ mod tests {
|
|||||||
app.data.radarr_data.delete_movie_files = true;
|
app.data.radarr_data.delete_movie_files = true;
|
||||||
app.data.radarr_data.add_list_exclusion = true;
|
app.data.radarr_data.add_list_exclusion = true;
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -264,7 +265,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_confirm_prompt_prompt_confirm() {
|
fn test_delete_movie_confirm_prompt_prompt_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let expected_delete_movie_params = DeleteMovieParams {
|
let expected_delete_movie_params = DeleteMovieParams {
|
||||||
id: 1,
|
id: 1,
|
||||||
delete_movie_files: true,
|
delete_movie_files: true,
|
||||||
@@ -282,7 +283,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, DELETE_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
DeleteMovieHandler::with(
|
DeleteMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -313,9 +314,28 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_movie_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DeleteMovieHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_delete_movie_params() {
|
fn test_build_delete_movie_params() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||||
app.data.radarr_data.delete_movie_files = true;
|
app.data.radarr_data.delete_movie_files = true;
|
||||||
app.data.radarr_data.add_list_exclusion = true;
|
app.data.radarr_data.add_list_exclusion = true;
|
||||||
@@ -325,7 +345,7 @@ mod tests {
|
|||||||
add_list_exclusion: true,
|
add_list_exclusion: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let delete_movie_params = DeleteMovieHandler::with(
|
let delete_movie_params = DeleteMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -340,10 +360,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_handler_not_ready_when_loading() {
|
fn test_delete_movie_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = DeleteMovieHandler::with(
|
let handler = DeleteMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
@@ -355,10 +375,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_delete_movie_handler_ready_when_not_loading() {
|
fn test_delete_movie_handler_ready_when_not_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = DeleteMovieHandler::with(
|
let handler = DeleteMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,7 @@ use crate::models::servarr_data::radarr::modals::EditMovieModal;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_movie_handler_tests.rs"]
|
#[path = "edit_movie_handler_tests.rs"]
|
||||||
@@ -20,54 +19,46 @@ pub(super) struct EditMovieHandler<'a, 'b> {
|
|||||||
context: Option<ActiveRadarrBlock>,
|
context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> EditMovieHandler<'a, 'b> {
|
impl EditMovieHandler<'_, '_> {
|
||||||
fn build_edit_movie_params(&mut self) -> EditMovieParams {
|
fn build_edit_movie_params(&mut self) -> EditMovieParams {
|
||||||
let movie_id = self.app.data.radarr_data.movies.current_selection().id;
|
let movie_id = self.app.data.radarr_data.movies.current_selection().id;
|
||||||
let tags = self
|
let edit_movie_modal = self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.edit_movie_modal
|
.edit_movie_modal
|
||||||
.as_ref()
|
.take()
|
||||||
.unwrap()
|
.expect("Edit movie modal is None");
|
||||||
.tags
|
let tags = edit_movie_modal.tags.text;
|
||||||
.text
|
let EditMovieModal {
|
||||||
.clone();
|
monitored,
|
||||||
let params = {
|
path,
|
||||||
let EditMovieModal {
|
minimum_availability_list,
|
||||||
monitored,
|
quality_profile_list,
|
||||||
path,
|
..
|
||||||
minimum_availability_list,
|
} = edit_movie_modal;
|
||||||
quality_profile_list,
|
let quality_profile = quality_profile_list.current_selection();
|
||||||
..
|
let quality_profile_id = *self
|
||||||
} = self.app.data.radarr_data.edit_movie_modal.as_ref().unwrap();
|
.app
|
||||||
let quality_profile = quality_profile_list.current_selection();
|
.data
|
||||||
let quality_profile_id = *self
|
.radarr_data
|
||||||
.app
|
.quality_profile_map
|
||||||
.data
|
.iter()
|
||||||
.radarr_data
|
.filter(|(_, value)| *value == quality_profile)
|
||||||
.quality_profile_map
|
.map(|(key, _)| key)
|
||||||
.iter()
|
.next()
|
||||||
.filter(|(_, value)| *value == quality_profile)
|
.unwrap();
|
||||||
.map(|(key, _)| key)
|
|
||||||
.next()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
EditMovieParams {
|
EditMovieParams {
|
||||||
movie_id,
|
movie_id,
|
||||||
monitored: *monitored,
|
monitored,
|
||||||
minimum_availability: Some(*minimum_availability_list.current_selection()),
|
minimum_availability: Some(*minimum_availability_list.current_selection()),
|
||||||
quality_profile_id: Some(quality_profile_id),
|
quality_profile_id: Some(quality_profile_id),
|
||||||
root_folder_path: Some(path.text.clone()),
|
root_folder_path: Some(path.text),
|
||||||
tags: None,
|
tags: None,
|
||||||
tag_input_string: Some(tags),
|
tag_input_string: Some(tags),
|
||||||
clear_tags: false,
|
clear_tags: false,
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
self.app.data.radarr_data.edit_movie_modal = None;
|
|
||||||
|
|
||||||
params
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +67,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
EDIT_MOVIE_BLOCKS.contains(&active_block)
|
EDIT_MOVIE_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -298,7 +293,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditMovieToggleMonitored => {
|
ActiveRadarrBlock::EditMovieToggleMonitored => {
|
||||||
self
|
self
|
||||||
@@ -327,7 +322,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
|
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -337,7 +332,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::EditMovieTagsInput | ActiveRadarrBlock::EditMoviePathInput => {
|
ActiveRadarrBlock::EditMovieTagsInput | ActiveRadarrBlock::EditMoviePathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditMoviePrompt => {
|
ActiveRadarrBlock::EditMoviePrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -384,7 +379,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
ActiveRadarrBlock::EditMoviePrompt => {
|
ActiveRadarrBlock::EditMoviePrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::EditMovieConfirmPrompt
|
== ActiveRadarrBlock::EditMovieConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -30,7 +31,7 @@ mod tests {
|
|||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -43,7 +44,7 @@ mod tests {
|
|||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
for i in (0..minimum_availability_vec.len()).rev() {
|
for i in (0..minimum_availability_vec.len()).rev() {
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
||||||
@@ -65,7 +66,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..minimum_availability_vec.len() {
|
for i in 0..minimum_availability_vec.len() {
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
||||||
@@ -92,7 +93,7 @@ mod tests {
|
|||||||
fn test_edit_movie_select_quality_profile_scroll(
|
fn test_edit_movie_select_quality_profile_scroll(
|
||||||
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -103,7 +104,7 @@ mod tests {
|
|||||||
.quality_profile_list
|
.quality_profile_list
|
||||||
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
||||||
@@ -123,7 +124,7 @@ mod tests {
|
|||||||
"Test 2"
|
"Test 2"
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
||||||
@@ -146,12 +147,12 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_edit_movie_prompt_scroll(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
EditMovieHandler::with(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
EditMovieHandler::new(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
||||||
|
|
||||||
if key == Key::Up {
|
if key == Key::Up {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -168,13 +169,13 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_edit_movie_prompt_scroll_no_op_when_not_ready(#[values(Key::Up, Key::Down)] key: Key) {
|
fn test_edit_movie_prompt_scroll_no_op_when_not_ready(#[values(Key::Up, Key::Down)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.down();
|
app.data.radarr_data.selected_block.down();
|
||||||
|
|
||||||
EditMovieHandler::with(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
EditMovieHandler::new(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.selected_block.get_active_block(),
|
app.data.radarr_data.selected_block.get_active_block(),
|
||||||
@@ -195,7 +196,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_select_minimum_availability_home_end() {
|
fn test_edit_movie_select_minimum_availability_home_end() {
|
||||||
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
let minimum_availability_vec = Vec::from_iter(MinimumAvailability::iter());
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -206,7 +207,7 @@ mod tests {
|
|||||||
.minimum_availability_list
|
.minimum_availability_list
|
||||||
.set_items(minimum_availability_vec.clone());
|
.set_items(minimum_availability_vec.clone());
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
||||||
@@ -226,7 +227,7 @@ mod tests {
|
|||||||
&minimum_availability_vec[minimum_availability_vec.len() - 1]
|
&minimum_availability_vec[minimum_availability_vec.len() - 1]
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::EditMovieSelectMinimumAvailability,
|
||||||
@@ -249,7 +250,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_select_quality_profile_scroll() {
|
fn test_edit_movie_select_quality_profile_scroll() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -264,7 +265,7 @@ mod tests {
|
|||||||
"Test 3".to_owned(),
|
"Test 3".to_owned(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
||||||
@@ -284,7 +285,7 @@ mod tests {
|
|||||||
"Test 3"
|
"Test 3"
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
ActiveRadarrBlock::EditMovieSelectQualityProfile,
|
||||||
@@ -307,13 +308,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_path_input_home_end_keys() {
|
fn test_edit_movie_path_input_home_end_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
path: "Test".into(),
|
path: "Test".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
@@ -334,7 +335,7 @@ mod tests {
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
@@ -358,13 +359,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_tags_input_home_end_keys() {
|
fn test_edit_movie_tags_input_home_end_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
@@ -385,7 +386,7 @@ mod tests {
|
|||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
@@ -418,26 +419,26 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
EditMovieHandler::with(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
EditMovieHandler::new(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
EditMovieHandler::with(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
EditMovieHandler::new(key, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_path_input_left_right_keys() {
|
fn test_edit_movie_path_input_left_right_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
path: "Test".into(),
|
path: "Test".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
@@ -458,7 +459,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
@@ -482,13 +483,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_tags_input_left_right_keys() {
|
fn test_edit_movie_tags_input_left_right_keys() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
@@ -509,7 +510,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
@@ -547,8 +548,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_path_input_submit() {
|
fn test_edit_movie_path_input_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
path: "Test Path".into(),
|
path: "Test Path".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
@@ -556,7 +557,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
@@ -564,7 +565,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -582,8 +583,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_tags_input_submit() {
|
fn test_edit_movie_tags_input_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
tags: "Test Tags".into(),
|
tags: "Test Tags".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
@@ -591,7 +592,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePathInput.into());
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
@@ -599,7 +600,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -617,7 +618,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_prompt_prompt_decline_submit() {
|
fn test_edit_movie_prompt_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
@@ -628,7 +629,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -642,7 +643,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit() {
|
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut edit_movie = EditMovieModal {
|
let mut edit_movie = EditMovieModal {
|
||||||
tags: "usenet, testing".to_owned().into(),
|
tags: "usenet, testing".to_owned().into(),
|
||||||
path: "/nfs/Test Path".to_owned().into(),
|
path: "/nfs/Test Path".to_owned().into(),
|
||||||
@@ -681,7 +682,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -700,14 +701,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
fn test_edit_movie_confirm_prompt_prompt_confirmation_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -729,12 +730,12 @@ mod tests {
|
|||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
Some(ActiveRadarrBlock::Movies),
|
Some(ActiveRadarrBlock::Movies),
|
||||||
));
|
));
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
app.push_navigation_stack(current_route);
|
app.push_navigation_stack(current_route);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -754,7 +755,7 @@ mod tests {
|
|||||||
Some(true)
|
Some(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -784,7 +785,7 @@ mod tests {
|
|||||||
#[case] selected_block: ActiveRadarrBlock,
|
#[case] selected_block: ActiveRadarrBlock,
|
||||||
#[case] y_index: usize,
|
#[case] y_index: usize,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.push_navigation_stack(
|
app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
@@ -796,7 +797,7 @@ mod tests {
|
|||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(0, y_index);
|
app.data.radarr_data.selected_block.set_index(0, y_index);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -813,7 +814,7 @@ mod tests {
|
|||||||
if selected_block == ActiveRadarrBlock::EditMoviePathInput
|
if selected_block == ActiveRadarrBlock::EditMoviePathInput
|
||||||
|| selected_block == ActiveRadarrBlock::EditMovieTagsInput
|
|| selected_block == ActiveRadarrBlock::EditMovieTagsInput
|
||||||
{
|
{
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -821,7 +822,7 @@ mod tests {
|
|||||||
fn test_edit_movie_prompt_selected_block_submit_no_op_when_not_ready(
|
fn test_edit_movie_prompt_selected_block_submit_no_op_when_not_ready(
|
||||||
#[values(1, 2, 3, 4)] y_index: usize,
|
#[values(1, 2, 3, 4)] y_index: usize,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.push_navigation_stack(
|
app.push_navigation_stack(
|
||||||
@@ -834,7 +835,7 @@ mod tests {
|
|||||||
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
app.data.radarr_data.selected_block = BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
app.data.radarr_data.selected_block.set_index(0, y_index);
|
app.data.radarr_data.selected_block.set_index(0, y_index);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -851,7 +852,7 @@ mod tests {
|
|||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
@@ -864,12 +865,12 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -885,7 +886,7 @@ mod tests {
|
|||||||
if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput
|
if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput
|
||||||
|| active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput
|
|| active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput
|
||||||
{
|
{
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -909,15 +910,15 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
EditMovieHandler::with(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
EditMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::EditMoviePrompt.into()
|
ActiveRadarrBlock::EditMoviePrompt.into()
|
||||||
@@ -926,12 +927,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_prompt_esc() {
|
fn test_edit_movie_prompt_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
|
|
||||||
EditMovieHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
EditMovieHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::EditMoviePrompt, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
|
|
||||||
@@ -948,12 +949,12 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
#[values(true, false)] is_ready: bool,
|
#[values(true, false)] is_ready: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
EditMovieHandler::with(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
EditMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
}
|
}
|
||||||
@@ -971,13 +972,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_path_input_backspace() {
|
fn test_edit_movie_path_input_backspace() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
path: "Test".into(),
|
path: "Test".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.backspace.key,
|
DEFAULT_KEYBINDINGS.backspace.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
@@ -1000,13 +1001,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_tags_input_backspace() {
|
fn test_edit_movie_tags_input_backspace() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.backspace.key,
|
DEFAULT_KEYBINDINGS.backspace.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
@@ -1029,11 +1030,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_path_input_char_key() {
|
fn test_edit_movie_path_input_char_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
None,
|
None,
|
||||||
@@ -1049,17 +1050,17 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.path
|
.path
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_tags_input_char_key() {
|
fn test_edit_movie_tags_input_char_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1075,13 +1076,13 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_confirm_prompt_prompt_confirm() {
|
fn test_edit_movie_confirm_prompt_prompt_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut edit_movie = EditMovieModal {
|
let mut edit_movie = EditMovieModal {
|
||||||
tags: "usenet, testing".to_owned().into(),
|
tags: "usenet, testing".to_owned().into(),
|
||||||
path: "/nfs/Test Path".to_owned().into(),
|
path: "/nfs/Test Path".to_owned().into(),
|
||||||
@@ -1119,7 +1120,7 @@ mod tests {
|
|||||||
.selected_block
|
.selected_block
|
||||||
.set_index(0, EDIT_MOVIE_SELECTION_BLOCKS.len() - 1);
|
.set_index(0, EDIT_MOVIE_SELECTION_BLOCKS.len() - 1);
|
||||||
|
|
||||||
EditMovieHandler::with(
|
EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -1148,9 +1149,28 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_movie_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditMovieHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_movie_params() {
|
fn test_build_edit_movie_params() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut edit_movie = EditMovieModal {
|
let mut edit_movie = EditMovieModal {
|
||||||
tags: "usenet, testing".to_owned().into(),
|
tags: "usenet, testing".to_owned().into(),
|
||||||
path: "/nfs/Test Path".to_owned().into(),
|
path: "/nfs/Test Path".to_owned().into(),
|
||||||
@@ -1180,7 +1200,7 @@ mod tests {
|
|||||||
..EditMovieParams::default()
|
..EditMovieParams::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let edit_movie_params = EditMovieHandler::with(
|
let edit_movie_params = EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -1194,10 +1214,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_handler_is_not_ready_when_loading() {
|
fn test_edit_movie_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = EditMovieHandler::with(
|
let handler = EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -1209,10 +1229,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_handler_is_not_ready_when_edit_movie_modal_is_none() {
|
fn test_edit_movie_handler_is_not_ready_when_edit_movie_modal_is_none() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = EditMovieHandler::with(
|
let handler = EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -1224,11 +1244,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_handler_is_ready_when_edit_movie_modal_is_some() {
|
fn test_edit_movie_handler_is_ready_when_edit_movie_modal_is_some() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
|
|
||||||
let handler = EditMovieHandler::with(
|
let handler = EditMovieHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ mod tests {
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::radarr_handlers::library::{movies_sorting_options, LibraryHandler};
|
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::KeyEventHandler;
|
||||||
use crate::models::radarr_models::Movie;
|
use crate::models::radarr_models::Movie;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{
|
use crate::models::servarr_data::radarr::radarr_data::{
|
||||||
@@ -30,7 +31,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movies_delete() {
|
fn test_movies_delete() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -51,7 +52,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movies_delete_no_op_when_not_ready() {
|
fn test_movies_delete_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app
|
app
|
||||||
@@ -60,7 +61,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(DELETE_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
LibraryHandler::new(DELETE_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
}
|
}
|
||||||
@@ -74,11 +75,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_movie_tab_left(#[values(true, false)] is_ready: bool) {
|
fn test_movie_tab_left(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(0);
|
app.data.radarr_data.main_tabs.set_index(0);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.left.key,
|
DEFAULT_KEYBINDINGS.left.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -95,11 +96,11 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_movie_tab_right(#[values(true, false)] is_ready: bool) {
|
fn test_movie_tab_right(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.main_tabs.set_index(0);
|
app.data.radarr_data.main_tabs.set_index(0);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.right.key,
|
DEFAULT_KEYBINDINGS.right.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -121,9 +122,9 @@ mod tests {
|
|||||||
fn test_left_right_update_all_movies_prompt_toggle(
|
fn test_left_right_update_all_movies_prompt_toggle(
|
||||||
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||||
@@ -133,7 +134,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
key,
|
key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||||
@@ -156,14 +157,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_submit() {
|
fn test_movie_details_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
LibraryHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -173,7 +174,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_submit_no_op_when_not_ready() {
|
fn test_movie_details_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app
|
app
|
||||||
@@ -182,14 +183,14 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
LibraryHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_movies_prompt_confirm_submit() {
|
fn test_update_all_movies_prompt_confirm_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -199,7 +200,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||||
@@ -217,7 +218,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_movies_prompt_decline_submit() {
|
fn test_update_all_movies_prompt_decline_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -226,7 +227,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||||
@@ -253,12 +254,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_movies_prompt_blocks_esc() {
|
fn test_update_all_movies_prompt_blocks_esc() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||||
@@ -272,7 +273,7 @@ mod tests {
|
|||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
fn test_default_esc(#[values(true, false)] is_ready: bool) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.error = "test error".to_owned().into();
|
app.error = "test error".to_owned().into();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
@@ -286,7 +287,7 @@ mod tests {
|
|||||||
..StatefulTable::default()
|
..StatefulTable::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
LibraryHandler::with(ESC_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
LibraryHandler::new(ESC_KEY, &mut app, ActiveRadarrBlock::Movies, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(app.error.text.is_empty());
|
assert!(app.error.text.is_empty());
|
||||||
@@ -312,14 +313,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_add_key() {
|
fn test_movie_add_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.add.key,
|
DEFAULT_KEYBINDINGS.add.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -331,13 +332,13 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchInput.into()
|
ActiveRadarrBlock::AddMovieSearchInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.add_movie_search.is_some());
|
assert!(app.data.radarr_data.add_movie_search.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_add_key_no_op_when_not_ready() {
|
fn test_movie_add_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app
|
app
|
||||||
@@ -346,7 +347,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.add.key,
|
DEFAULT_KEYBINDINGS.add.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -355,7 +356,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.add_movie_search.is_none());
|
assert!(app.data.radarr_data.add_movie_search.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +371,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_edit_key_no_op_when_not_ready() {
|
fn test_movie_edit_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app
|
app
|
||||||
@@ -379,7 +380,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.edit.key,
|
DEFAULT_KEYBINDINGS.edit.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -391,16 +392,61 @@ mod tests {
|
|||||||
assert!(app.data.radarr_data.edit_movie_modal.is_none());
|
assert!(app.data.radarr_data.edit_movie_modal.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toggle_monitoring_key() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
|
app.is_routing = false;
|
||||||
|
|
||||||
|
LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.toggle_monitoring.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::Movies,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
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))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toggle_monitoring_key_no_op_when_not_ready() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
|
app.is_routing = false;
|
||||||
|
|
||||||
|
LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.toggle_monitoring.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::Movies,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.handle();
|
||||||
|
|
||||||
|
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!(!app.is_routing);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_movies_key() {
|
fn test_update_all_movies_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -416,7 +462,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_movies_key_no_op_when_not_ready() {
|
fn test_update_all_movies_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app
|
app
|
||||||
@@ -425,7 +471,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -438,7 +484,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_movies_key() {
|
fn test_refresh_movies_key() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -446,7 +492,7 @@ mod tests {
|
|||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -460,7 +506,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_refresh_movies_key_no_op_when_not_ready() {
|
fn test_refresh_movies_key_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -469,7 +515,7 @@ mod tests {
|
|||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -483,7 +529,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_all_movies_prompt_confirm() {
|
fn test_update_all_movies_prompt_confirm() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -492,7 +538,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||||
|
|
||||||
LibraryHandler::with(
|
LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||||
@@ -580,6 +626,22 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_movie_id() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||||
|
|
||||||
|
let movie_id = LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::Movies,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.extract_movie_id();
|
||||||
|
|
||||||
|
assert_eq!(movie_id, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movies_sorting_options_title() {
|
fn test_movies_sorting_options_title() {
|
||||||
let expected_cmp_fn: fn(&Movie, &Movie) -> Ordering = |a, b| {
|
let expected_cmp_fn: fn(&Movie, &Movie) -> Ordering = |a, b| {
|
||||||
@@ -615,8 +677,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movies_sorting_options_studio() {
|
fn test_movies_sorting_options_studio() {
|
||||||
let expected_cmp_fn: fn(&Movie, &Movie) -> Ordering =
|
let expected_cmp_fn: fn(&Movie, &Movie) -> Ordering = |a, b| {
|
||||||
|a, b| a.studio.to_lowercase().cmp(&b.studio.to_lowercase());
|
a.studio
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&String::new())
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.studio.as_ref().unwrap_or(&String::new()).to_lowercase())
|
||||||
|
};
|
||||||
let mut expected_movies_vec = movies_vec();
|
let mut expected_movies_vec = movies_vec();
|
||||||
expected_movies_vec.sort_by(expected_cmp_fn);
|
expected_movies_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
@@ -777,12 +844,31 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_library_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_library_handler_not_ready_when_loading() {
|
fn test_library_handler_not_ready_when_loading() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = LibraryHandler::with(
|
let handler = LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -794,10 +880,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_library_handler_not_ready_when_movies_is_empty() {
|
fn test_library_handler_not_ready_when_movies_is_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
|
|
||||||
let handler = LibraryHandler::with(
|
let handler = LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -809,7 +895,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_library_handler_ready_when_not_loading_and_movies_is_not_empty() {
|
fn test_library_handler_ready_when_not_loading_and_movies_is_not_empty() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -817,7 +903,7 @@ mod tests {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![Movie::default()]);
|
.set_items(vec![Movie::default()]);
|
||||||
|
|
||||||
let handler = LibraryHandler::with(
|
let handler = LibraryHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Movies,
|
ActiveRadarrBlock::Movies,
|
||||||
@@ -837,7 +923,7 @@ mod tests {
|
|||||||
name: "English".to_owned(),
|
name: "English".to_owned(),
|
||||||
},
|
},
|
||||||
size_on_disk: 1024,
|
size_on_disk: 1024,
|
||||||
studio: "Studio 1".to_owned(),
|
studio: Some("Studio 1".to_owned()),
|
||||||
year: 2024,
|
year: 2024,
|
||||||
monitored: false,
|
monitored: false,
|
||||||
runtime: 12.into(),
|
runtime: 12.into(),
|
||||||
@@ -854,7 +940,7 @@ mod tests {
|
|||||||
name: "Chinese".to_owned(),
|
name: "Chinese".to_owned(),
|
||||||
},
|
},
|
||||||
size_on_disk: 2048,
|
size_on_disk: 2048,
|
||||||
studio: "Studio 2".to_owned(),
|
studio: Some("Studio 2".to_owned()),
|
||||||
year: 1998,
|
year: 1998,
|
||||||
monitored: false,
|
monitored: false,
|
||||||
runtime: 60.into(),
|
runtime: 60.into(),
|
||||||
@@ -871,7 +957,7 @@ mod tests {
|
|||||||
name: "Japanese".to_owned(),
|
name: "Japanese".to_owned(),
|
||||||
},
|
},
|
||||||
size_on_disk: 512,
|
size_on_disk: 512,
|
||||||
studio: "studio 3".to_owned(),
|
studio: Some("studio 3".to_owned()),
|
||||||
year: 1954,
|
year: 1954,
|
||||||
monitored: true,
|
monitored: true,
|
||||||
runtime: 120.into(),
|
runtime: 120.into(),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
@@ -8,7 +7,6 @@ use crate::handlers::radarr_handlers::library::edit_movie_handler::EditMovieHand
|
|||||||
use crate::handlers::radarr_handlers::library::movie_details_handler::MovieDetailsHandler;
|
use crate::handlers::radarr_handlers::library::movie_details_handler::MovieDetailsHandler;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
|
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::models::radarr_models::Movie;
|
use crate::models::radarr_models::Movie;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{
|
use crate::models::servarr_data::radarr::radarr_data::{
|
||||||
@@ -17,6 +15,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::{BlockSelectionState, HorizontallyScrollableText};
|
use crate::models::{BlockSelectionState, HorizontallyScrollableText};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod add_movie_handler;
|
mod add_movie_handler;
|
||||||
mod delete_movie_handler;
|
mod delete_movie_handler;
|
||||||
@@ -34,8 +33,11 @@ pub(super) struct LibraryHandler<'a, 'b> {
|
|||||||
context: Option<ActiveRadarrBlock>,
|
context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> LibraryHandler<'a, 'b> {
|
impl LibraryHandler<'_, '_> {
|
||||||
handle_table_events!(self, movies, self.app.data.radarr_data.movies, Movie);
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, 'b> {
|
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, 'b> {
|
||||||
@@ -54,19 +56,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
if !self.handle_movies_table_events(movie_table_handling_config) {
|
if !self.handle_movies_table_events(movie_table_handling_config) {
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
_ if AddMovieHandler::accepts(self.active_radarr_block) => {
|
_ if AddMovieHandler::accepts(self.active_radarr_block) => {
|
||||||
AddMovieHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
AddMovieHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle();
|
||||||
.handle();
|
|
||||||
}
|
}
|
||||||
_ if DeleteMovieHandler::accepts(self.active_radarr_block) => {
|
_ if DeleteMovieHandler::accepts(self.active_radarr_block) => {
|
||||||
DeleteMovieHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
DeleteMovieHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle();
|
.handle();
|
||||||
}
|
}
|
||||||
_ if EditMovieHandler::accepts(self.active_radarr_block) => {
|
_ if EditMovieHandler::accepts(self.active_radarr_block) => {
|
||||||
EditMovieHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
EditMovieHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle();
|
.handle();
|
||||||
}
|
}
|
||||||
_ if MovieDetailsHandler::accepts(self.active_radarr_block) => {
|
_ if MovieDetailsHandler::accepts(self.active_radarr_block) => {
|
||||||
MovieDetailsHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
MovieDetailsHandler::new(self.key, self.app, self.active_radarr_block, self.context)
|
||||||
.handle();
|
.handle();
|
||||||
}
|
}
|
||||||
_ => self.handle_key_event(),
|
_ => self.handle_key_event(),
|
||||||
@@ -82,7 +83,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
|| LIBRARY_BLOCKS.contains(&active_block)
|
|| LIBRARY_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -162,7 +167,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Movies => match self.key {
|
ActiveRadarrBlock::Movies => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -174,25 +179,34 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
self.app.data.radarr_data.selected_block =
|
self.app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.add.key => {
|
_ if matches_key!(add, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
self.app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
self.app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(toggle_monitoring, key) => {
|
||||||
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
Some(RadarrEvent::ToggleMovieMonitoring(self.extract_movie_id()));
|
||||||
|
|
||||||
|
self
|
||||||
|
.app
|
||||||
|
.pop_and_push_navigation_stack(self.active_radarr_block.into());
|
||||||
|
}
|
||||||
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt => {
|
ActiveRadarrBlock::UpdateAllMoviesPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAllMovies);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAllMovies);
|
||||||
|
|
||||||
@@ -221,7 +235,13 @@ fn movies_sorting_options() -> Vec<SortOption<Movie>> {
|
|||||||
},
|
},
|
||||||
SortOption {
|
SortOption {
|
||||||
name: "Studio",
|
name: "Studio",
|
||||||
cmp_fn: Some(|a, b| a.studio.to_lowercase().cmp(&b.studio.to_lowercase())),
|
cmp_fn: Some(|a, b| {
|
||||||
|
a.studio
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&String::new())
|
||||||
|
.to_lowercase()
|
||||||
|
.cmp(&b.studio.as_ref().unwrap_or(&String::new()).to_lowercase())
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
SortOption {
|
SortOption {
|
||||||
name: "Runtime",
|
name: "Runtime",
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
use serde_json::Number;
|
use serde_json::Number;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
@@ -16,6 +14,7 @@ use crate::models::servarr_models::Language;
|
|||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::{BlockSelectionState, Scrollable};
|
use crate::models::{BlockSelectionState, Scrollable};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "movie_details_handler_tests.rs"]
|
#[path = "movie_details_handler_tests.rs"]
|
||||||
@@ -28,7 +27,7 @@ pub(super) struct MovieDetailsHandler<'a, 'b> {
|
|||||||
_context: Option<ActiveRadarrBlock>,
|
_context: Option<ActiveRadarrBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> MovieDetailsHandler<'a, 'b> {
|
impl MovieDetailsHandler<'_, '_> {
|
||||||
handle_table_events!(
|
handle_table_events!(
|
||||||
self,
|
self,
|
||||||
movie_releases,
|
movie_releases,
|
||||||
@@ -136,7 +135,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
MOVIE_DETAILS_BLOCKS.contains(&active_block)
|
MOVIE_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -245,13 +248,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
| ActiveRadarrBlock::Cast
|
| ActiveRadarrBlock::Cast
|
||||||
| ActiveRadarrBlock::Crew
|
| ActiveRadarrBlock::Crew
|
||||||
| ActiveRadarrBlock::ManualSearch => match self.key {
|
| ActiveRadarrBlock::ManualSearch => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, self.key) => {
|
||||||
self.app.data.radarr_data.movie_info_tabs.previous();
|
self.app.data.radarr_data.movie_info_tabs.previous();
|
||||||
self.app.pop_and_push_navigation_stack(
|
self.app.pop_and_push_navigation_stack(
|
||||||
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, self.key) => {
|
||||||
self.app.data.radarr_data.movie_info_tabs.next();
|
self.app.data.radarr_data.movie_info_tabs.next();
|
||||||
self.app.pop_and_push_navigation_stack(
|
self.app.pop_and_push_navigation_stack(
|
||||||
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
||||||
@@ -332,12 +335,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
| ActiveRadarrBlock::Cast
|
| ActiveRadarrBlock::Cast
|
||||||
| ActiveRadarrBlock::Crew
|
| ActiveRadarrBlock::Crew
|
||||||
| ActiveRadarrBlock::ManualSearch => match self.key {
|
| ActiveRadarrBlock::ManualSearch => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.auto_search.key => {
|
_ if matches_key!(auto_search, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -349,35 +352,33 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
self.app.data.radarr_data.selected_block =
|
self.app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAndScanPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateAndScanPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.pop_and_push_navigation_stack(self.active_radarr_block.into());
|
.pop_and_push_navigation_stack(self.active_radarr_block.into());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt
|
ActiveRadarrBlock::AutomaticallySearchMoviePrompt if matches_key!(confirm, key) => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
|
||||||
{
|
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::TriggerAutomaticSearch(self.extract_movie_id()));
|
Some(RadarrEvent::TriggerAutomaticSearch(self.extract_movie_id()));
|
||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::UpdateAndScanPrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
ActiveRadarrBlock::UpdateAndScanPrompt if matches_key!(confirm, key) => {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::UpdateAndScan(self.extract_movie_id()));
|
Some(RadarrEvent::UpdateAndScan(self.extract_movie_id()));
|
||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::ManualSearchConfirmPrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
ActiveRadarrBlock::ManualSearchConfirmPrompt if matches_key!(confirm, key) => {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(
|
||||||
self.build_radarr_release_download_body(),
|
self.build_radarr_release_download_body(),
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_scroll() {
|
fn test_movie_details_scroll() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.up.key,
|
DEFAULT_KEYBINDINGS.up.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -57,7 +57,7 @@ mod tests {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.down.key,
|
DEFAULT_KEYBINDINGS.down.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -80,14 +80,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_scroll_no_op_if_not_ready() {
|
fn test_movie_details_scroll_no_op_if_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.up.key,
|
DEFAULT_KEYBINDINGS.up.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -107,7 +107,7 @@ mod tests {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.down.key,
|
DEFAULT_KEYBINDINGS.down.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -137,14 +137,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_home_end() {
|
fn test_movie_details_home_end() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let movie_details_modal = MovieDetailsModal {
|
let movie_details_modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
};
|
};
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -164,7 +164,7 @@ mod tests {
|
|||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -187,7 +187,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_home_end_no_op_when_not_ready() {
|
fn test_movie_details_home_end_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
let movie_details_modal = MovieDetailsModal {
|
let movie_details_modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
movie_details: ScrollableText::with_string("Test 1\nTest 2".to_owned()),
|
||||||
@@ -195,7 +195,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.end.key,
|
DEFAULT_KEYBINDINGS.end.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -215,7 +215,7 @@ mod tests {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.home.key,
|
DEFAULT_KEYBINDINGS.home.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -253,13 +253,13 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
#[values(Key::Left, Key::Right)] key: Key,
|
#[values(Key::Left, Key::Right)] key: Key,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
|
|
||||||
MovieDetailsHandler::with(key, &mut app, active_radarr_block, None).handle();
|
MovieDetailsHandler::new(key, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
|
|
||||||
MovieDetailsHandler::with(key, &mut app, active_radarr_block, None).handle();
|
MovieDetailsHandler::new(key, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ mod tests {
|
|||||||
#[case] right_block: ActiveRadarrBlock,
|
#[case] right_block: ActiveRadarrBlock,
|
||||||
#[values(true, false)] is_ready: bool,
|
#[values(true, false)] is_ready: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.push_navigation_stack(right_block.into());
|
app.push_navigation_stack(right_block.into());
|
||||||
app.data.radarr_data.movie_info_tabs.index = app
|
app.data.radarr_data.movie_info_tabs.index = app
|
||||||
@@ -288,7 +288,7 @@ mod tests {
|
|||||||
.position(|tab_route| tab_route.route == right_block.into())
|
.position(|tab_route| tab_route.route == right_block.into())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
MovieDetailsHandler::with(DEFAULT_KEYBINDINGS.left.key, &mut app, right_block, None).handle();
|
MovieDetailsHandler::new(DEFAULT_KEYBINDINGS.left.key, &mut app, right_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -296,7 +296,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(app.get_current_route(), left_block.into());
|
assert_eq!(app.get_current_route(), left_block.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle();
|
MovieDetailsHandler::new(DEFAULT_KEYBINDINGS.right.key, &mut app, left_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -319,7 +319,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_manual_search_submit() {
|
fn test_manual_search_submit() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut modal = MovieDetailsModal {
|
let mut modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -330,7 +330,7 @@ mod tests {
|
|||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
|
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::ManualSearch, None)
|
MovieDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::ManualSearch, None)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -341,7 +341,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_manual_search_submit_no_op_when_not_ready() {
|
fn test_manual_search_submit_no_op_when_not_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||||
@@ -349,7 +349,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
|
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(SUBMIT_KEY, &mut app, ActiveRadarrBlock::ManualSearch, None)
|
MovieDetailsHandler::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::ManualSearch, None)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -376,7 +376,7 @@ mod tests {
|
|||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
#[case] expected_action: RadarrEvent,
|
#[case] expected_action: RadarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut movie_details_modal = MovieDetailsModal {
|
let mut movie_details_modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -390,7 +390,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
MovieDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -412,7 +412,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
prompt_block: ActiveRadarrBlock,
|
prompt_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -420,7 +420,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
MovieDetailsHandler::new(SUBMIT_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -455,13 +455,13 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
#[values(true, false)] is_ready: bool,
|
#[values(true, false)] is_ready: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
MovieDetailsHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert_movie_info_tabs_reset!(app.data.radarr_data);
|
assert_movie_info_tabs_reset!(app.data.radarr_data);
|
||||||
@@ -477,14 +477,14 @@ mod tests {
|
|||||||
prompt_block: ActiveRadarrBlock,
|
prompt_block: ActiveRadarrBlock,
|
||||||
#[values(true, false)] is_ready: bool,
|
#[values(true, false)] is_ready: bool,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(ESC_KEY, &mut app, prompt_block, None).handle();
|
MovieDetailsHandler::new(ESC_KEY, &mut app, prompt_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
@@ -521,7 +521,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut modal = MovieDetailsModal {
|
let mut modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test".to_owned()),
|
movie_details: ScrollableText::with_string("Test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -536,7 +536,7 @@ mod tests {
|
|||||||
.set_items(vec![RadarrRelease::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.auto_search.key,
|
DEFAULT_KEYBINDINGS.auto_search.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -562,7 +562,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
@@ -570,7 +570,7 @@ mod tests {
|
|||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.auto_search.key,
|
DEFAULT_KEYBINDINGS.auto_search.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -612,7 +612,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
@@ -620,7 +620,7 @@ mod tests {
|
|||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.edit.key,
|
DEFAULT_KEYBINDINGS.edit.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -644,7 +644,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut modal = MovieDetailsModal {
|
let mut modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test".to_owned()),
|
movie_details: ScrollableText::with_string("Test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -659,7 +659,7 @@ mod tests {
|
|||||||
.set_items(vec![RadarrRelease::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -685,7 +685,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
@@ -693,7 +693,7 @@ mod tests {
|
|||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.update.key,
|
DEFAULT_KEYBINDINGS.update.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -716,7 +716,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut modal = MovieDetailsModal {
|
let mut modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test".to_owned()),
|
movie_details: ScrollableText::with_string("Test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -731,7 +731,7 @@ mod tests {
|
|||||||
.set_items(vec![RadarrRelease::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -755,7 +755,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.is_routing = false;
|
app.is_routing = false;
|
||||||
@@ -764,7 +764,7 @@ mod tests {
|
|||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.refresh.key,
|
DEFAULT_KEYBINDINGS.refresh.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
active_radarr_block,
|
active_radarr_block,
|
||||||
@@ -794,7 +794,7 @@ mod tests {
|
|||||||
#[case] prompt_block: ActiveRadarrBlock,
|
#[case] prompt_block: ActiveRadarrBlock,
|
||||||
#[case] expected_action: RadarrEvent,
|
#[case] expected_action: RadarrEvent,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut movie_details_modal = MovieDetailsModal {
|
let mut movie_details_modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
@@ -808,7 +808,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
|
||||||
app.push_navigation_stack(prompt_block.into());
|
app.push_navigation_stack(prompt_block.into());
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.confirm.key,
|
DEFAULT_KEYBINDINGS.confirm.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
prompt_block,
|
prompt_block,
|
||||||
@@ -830,7 +830,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_radarr_release_download_body() {
|
fn test_build_radarr_release_download_body() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut movie_details_modal = MovieDetailsModal::default();
|
let mut movie_details_modal = MovieDetailsModal::default();
|
||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
@@ -843,7 +843,7 @@ mod tests {
|
|||||||
movie_id: 1,
|
movie_id: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = MovieDetailsHandler::with(
|
let body = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||||
@@ -856,10 +856,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_movie_id() {
|
fn test_extract_movie_id() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.movies.set_items(vec![movie()]);
|
app.data.radarr_data.movies.set_items(vec![movie()]);
|
||||||
|
|
||||||
let movie_id = MovieDetailsHandler::with(
|
let movie_id = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||||
@@ -1042,6 +1042,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_movie_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = MovieDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_movie_details_handler_is_not_ready_when_loading(
|
fn test_movie_details_handler_is_not_ready_when_loading(
|
||||||
#[values(
|
#[values(
|
||||||
@@ -1055,7 +1074,7 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
movie_details_block: ActiveRadarrBlock,
|
movie_details_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
let mut modal = MovieDetailsModal {
|
let mut modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test".to_owned()),
|
movie_details: ScrollableText::with_string("Test".to_owned()),
|
||||||
@@ -1071,7 +1090,7 @@ mod tests {
|
|||||||
.set_items(vec![RadarrRelease::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
movie_details_block,
|
movie_details_block,
|
||||||
@@ -1083,11 +1102,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_handler_is_not_ready_when_no_movie_details_are_in_modal() {
|
fn test_movie_details_handler_is_not_ready_when_no_movie_details_are_in_modal() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default());
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default());
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -1099,14 +1118,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_handler_is_ready_when_movie_details_are_in_modal() {
|
fn test_movie_details_handler_is_ready_when_movie_details_are_in_modal() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test".to_owned()),
|
movie_details: ScrollableText::with_string("Test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieDetails,
|
ActiveRadarrBlock::MovieDetails,
|
||||||
@@ -1118,7 +1137,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_handler_is_ready_when_movie_history_is_in_modal() {
|
fn test_movie_details_handler_is_ready_when_movie_history_is_in_modal() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
let mut modal = MovieDetailsModal::default();
|
let mut modal = MovieDetailsModal::default();
|
||||||
modal
|
modal
|
||||||
@@ -1126,7 +1145,7 @@ mod tests {
|
|||||||
.set_items(vec![MovieHistoryItem::default()]);
|
.set_items(vec![MovieHistoryItem::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::MovieHistory,
|
ActiveRadarrBlock::MovieHistory,
|
||||||
@@ -1138,13 +1157,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_handler_is_ready_when_movie_cast_is_in_modal() {
|
fn test_movie_details_handler_is_ready_when_movie_cast_is_in_modal() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
let mut modal = MovieDetailsModal::default();
|
let mut modal = MovieDetailsModal::default();
|
||||||
modal.movie_cast.set_items(vec![Credit::default()]);
|
modal.movie_cast.set_items(vec![Credit::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Cast,
|
ActiveRadarrBlock::Cast,
|
||||||
@@ -1156,13 +1175,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_handler_is_ready_when_movie_crew_is_in_modal() {
|
fn test_movie_details_handler_is_ready_when_movie_crew_is_in_modal() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
let mut modal = MovieDetailsModal::default();
|
let mut modal = MovieDetailsModal::default();
|
||||||
modal.movie_crew.set_items(vec![Credit::default()]);
|
modal.movie_crew.set_items(vec![Credit::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::Crew,
|
ActiveRadarrBlock::Crew,
|
||||||
@@ -1174,7 +1193,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_handler_is_ready_when_movie_releases_is_in_modal() {
|
fn test_movie_details_handler_is_ready_when_movie_releases_is_in_modal() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
let mut modal = MovieDetailsModal::default();
|
let mut modal = MovieDetailsModal::default();
|
||||||
modal
|
modal
|
||||||
@@ -1182,7 +1201,7 @@ mod tests {
|
|||||||
.set_items(vec![RadarrRelease::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::ManualSearch,
|
ActiveRadarrBlock::ManualSearch,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::handlers::radarr_handlers::blocklist::BlocklistHandler;
|
use crate::handlers::radarr_handlers::blocklist::BlocklistHandler;
|
||||||
use crate::handlers::radarr_handlers::collections::CollectionsHandler;
|
use crate::handlers::radarr_handlers::collections::CollectionsHandler;
|
||||||
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
||||||
@@ -8,7 +7,7 @@ use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler;
|
|||||||
use crate::handlers::radarr_handlers::system::SystemHandler;
|
use crate::handlers::radarr_handlers::system::SystemHandler;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
use crate::{App, Key};
|
use crate::{matches_key, App, Key};
|
||||||
|
|
||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod collections;
|
mod collections;
|
||||||
@@ -37,27 +36,25 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b
|
|||||||
fn handle(&mut self) {
|
fn handle(&mut self) {
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
_ if LibraryHandler::accepts(self.active_radarr_block) => {
|
_ if LibraryHandler::accepts(self.active_radarr_block) => {
|
||||||
LibraryHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle();
|
LibraryHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle();
|
||||||
}
|
}
|
||||||
_ if CollectionsHandler::accepts(self.active_radarr_block) => {
|
_ if CollectionsHandler::accepts(self.active_radarr_block) => {
|
||||||
CollectionsHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
CollectionsHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
.handle()
|
|
||||||
}
|
}
|
||||||
_ if IndexersHandler::accepts(self.active_radarr_block) => {
|
_ if IndexersHandler::accepts(self.active_radarr_block) => {
|
||||||
IndexersHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle()
|
IndexersHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
}
|
}
|
||||||
_ if SystemHandler::accepts(self.active_radarr_block) => {
|
_ if SystemHandler::accepts(self.active_radarr_block) => {
|
||||||
SystemHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle()
|
SystemHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
}
|
}
|
||||||
_ if DownloadsHandler::accepts(self.active_radarr_block) => {
|
_ if DownloadsHandler::accepts(self.active_radarr_block) => {
|
||||||
DownloadsHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle()
|
DownloadsHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
}
|
}
|
||||||
_ if RootFoldersHandler::accepts(self.active_radarr_block) => {
|
_ if RootFoldersHandler::accepts(self.active_radarr_block) => {
|
||||||
RootFoldersHandler::with(self.key, self.app, self.active_radarr_block, self.context)
|
RootFoldersHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
.handle()
|
|
||||||
}
|
}
|
||||||
_ if BlocklistHandler::accepts(self.active_radarr_block) => {
|
_ if BlocklistHandler::accepts(self.active_radarr_block) => {
|
||||||
BlocklistHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle()
|
BlocklistHandler::new(self.key, self.app, self.active_radarr_block, self.context).handle()
|
||||||
}
|
}
|
||||||
_ => self.handle_key_event(),
|
_ => self.handle_key_event(),
|
||||||
}
|
}
|
||||||
@@ -67,7 +64,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with(
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
active_block: ActiveRadarrBlock,
|
active_block: ActiveRadarrBlock,
|
||||||
@@ -111,11 +112,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b
|
|||||||
pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
||||||
let key_ref = key;
|
let key_ref = key;
|
||||||
match key_ref {
|
match key_ref {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, key, app.ignore_special_keys_for_textbox_input) => {
|
||||||
app.data.radarr_data.main_tabs.previous();
|
app.data.radarr_data.main_tabs.previous();
|
||||||
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, key, app.ignore_special_keys_for_textbox_input) => {
|
||||||
app.data.radarr_data.main_tabs.next();
|
app.data.radarr_data.main_tabs.next();
|
||||||
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
||||||
}
|
}
|
||||||
@@ -126,10 +127,8 @@ pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! search_table {
|
macro_rules! search_table {
|
||||||
($app:expr, $data_ref:ident, $error_block:expr) => {
|
($app:expr, $data_ref:ident, $error_block:expr) => {
|
||||||
let search_index = if let Some(search_str) = $app.data.radarr_data.search.as_ref() {
|
let search_index = if let Some(search_str) = $app.data.radarr_data.search.take() {
|
||||||
let search_string = search_str.text.clone().to_lowercase();
|
let search_string = search_str.text.to_lowercase();
|
||||||
|
|
||||||
$app.data.radarr_data.search = None;
|
|
||||||
|
|
||||||
$app
|
$app
|
||||||
.data
|
.data
|
||||||
@@ -143,7 +142,7 @@ macro_rules! search_table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$app.data.radarr_data.is_searching = false;
|
$app.data.radarr_data.is_searching = false;
|
||||||
$app.should_ignore_quit_key = false;
|
$app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
|
||||||
if search_index.is_some() {
|
if search_index.is_some() {
|
||||||
$app.pop_navigation_stack();
|
$app.pop_navigation_stack();
|
||||||
@@ -153,10 +152,8 @@ macro_rules! search_table {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
($app:expr, $data_ref:ident, $error_block:expr, $option:ident) => {
|
($app:expr, $data_ref:ident, $error_block:expr, $option:ident) => {
|
||||||
let search_index = if let Some(search_str) = $app.data.radarr_data.search.as_ref() {
|
let search_index = if let Some(search_str) = $app.data.radarr_data.search.take() {
|
||||||
let search_string = search_str.text.clone().to_lowercase();
|
let search_string = search_str.text.to_lowercase();
|
||||||
|
|
||||||
$app.data.radarr_data.search = None;
|
|
||||||
|
|
||||||
$app
|
$app
|
||||||
.data
|
.data
|
||||||
@@ -172,7 +169,7 @@ macro_rules! search_table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$app.data.radarr_data.is_searching = false;
|
$app.data.radarr_data.is_searching = false;
|
||||||
$app.should_ignore_quit_key = false;
|
$app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
|
||||||
if search_index.is_some() {
|
if search_index.is_some() {
|
||||||
$app.pop_navigation_stack();
|
$app.pop_navigation_stack();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub(in crate::handlers::radarr_handlers) mod utils {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! test_edit_movie_key {
|
macro_rules! test_edit_movie_key {
|
||||||
($handler:ident, $block:expr, $context:expr) => {
|
($handler:ident, $block:expr, $context:expr) => {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut radarr_data = RadarrData {
|
let mut radarr_data = RadarrData {
|
||||||
quality_profile_map: BiMap::from_iter([
|
quality_profile_map: BiMap::from_iter([
|
||||||
(2222, "HD - 1080p".to_owned()),
|
(2222, "HD - 1080p".to_owned()),
|
||||||
@@ -35,7 +35,7 @@ pub(in crate::handlers::radarr_handlers) mod utils {
|
|||||||
}]);
|
}]);
|
||||||
app.data.radarr_data = radarr_data;
|
app.data.radarr_data = radarr_data;
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.edit.key, &mut app, $block, None).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.edit.key, &mut app, $block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -131,7 +131,7 @@ pub(in crate::handlers::radarr_handlers) mod utils {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! test_edit_collection_key {
|
macro_rules! test_edit_collection_key {
|
||||||
($handler:ident, $block:expr, $context:expr) => {
|
($handler:ident, $block:expr, $context:expr) => {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
let mut radarr_data = RadarrData {
|
let mut radarr_data = RadarrData {
|
||||||
quality_profile_map: BiMap::from_iter([
|
quality_profile_map: BiMap::from_iter([
|
||||||
(2222, "HD - 1080p".to_owned()),
|
(2222, "HD - 1080p".to_owned()),
|
||||||
@@ -149,7 +149,7 @@ pub(in crate::handlers::radarr_handlers) mod utils {
|
|||||||
}]);
|
}]);
|
||||||
app.data.radarr_data = radarr_data;
|
app.data.radarr_data = radarr_data;
|
||||||
|
|
||||||
$handler::with(DEFAULT_KEYBINDINGS.edit.key, &mut app, $block, None).handle();
|
$handler::new(DEFAULT_KEYBINDINGS.edit.key, &mut app, $block, None).handle();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -275,7 +275,7 @@ pub(in crate::handlers::radarr_handlers) mod utils {
|
|||||||
audio_stream_count: 1,
|
audio_stream_count: 1,
|
||||||
video_bit_depth: 10,
|
video_bit_depth: 10,
|
||||||
video_bitrate: 0,
|
video_bitrate: 0,
|
||||||
video_codec: "x265".to_owned(),
|
video_codec: Some("x265".to_owned()),
|
||||||
video_fps: Number::from_f64(23.976).unwrap(),
|
video_fps: Number::from_f64(23.976).unwrap(),
|
||||||
resolution: "1920x804".to_owned(),
|
resolution: "1920x804".to_owned(),
|
||||||
run_time: "2:00:00".to_owned(),
|
run_time: "2:00:00".to_owned(),
|
||||||
@@ -327,7 +327,7 @@ pub(in crate::handlers::radarr_handlers) mod utils {
|
|||||||
status: "Downloaded".to_owned(),
|
status: "Downloaded".to_owned(),
|
||||||
overview: "Blah blah blah".to_owned(),
|
overview: "Blah blah blah".to_owned(),
|
||||||
path: "/nfs/movies".to_owned(),
|
path: "/nfs/movies".to_owned(),
|
||||||
studio: "21st Century Alex".to_owned(),
|
studio: Some("21st Century Alex".to_owned()),
|
||||||
genres: genres(),
|
genres: genres(),
|
||||||
year: 2023,
|
year: 2023,
|
||||||
monitored: true,
|
monitored: true,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ mod tests {
|
|||||||
#[case] left_block: ActiveRadarrBlock,
|
#[case] left_block: ActiveRadarrBlock,
|
||||||
#[case] right_block: ActiveRadarrBlock,
|
#[case] right_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.main_tabs.set_index(index);
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.key);
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.key);
|
||||||
@@ -46,6 +46,76 @@ mod tests {
|
|||||||
assert_eq!(app.get_current_route(), right_block.into());
|
assert_eq!(app.get_current_route(), right_block.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveRadarrBlock::System, ActiveRadarrBlock::Collections)]
|
||||||
|
#[case(1, ActiveRadarrBlock::Movies, ActiveRadarrBlock::Downloads)]
|
||||||
|
#[case(2, ActiveRadarrBlock::Collections, ActiveRadarrBlock::Blocklist)]
|
||||||
|
#[case(3, ActiveRadarrBlock::Downloads, ActiveRadarrBlock::RootFolders)]
|
||||||
|
#[case(4, ActiveRadarrBlock::Blocklist, ActiveRadarrBlock::Indexers)]
|
||||||
|
#[case(5, ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::System)]
|
||||||
|
#[case(6, ActiveRadarrBlock::Indexers, ActiveRadarrBlock::Movies)]
|
||||||
|
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] left_block: ActiveRadarrBlock,
|
||||||
|
#[case] right_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
left_block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), left_block.into());
|
||||||
|
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.right.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
right_block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), right_block.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveRadarrBlock::Movies)]
|
||||||
|
#[case(1, ActiveRadarrBlock::Collections)]
|
||||||
|
#[case(2, ActiveRadarrBlock::Downloads)]
|
||||||
|
#[case(3, ActiveRadarrBlock::Blocklist)]
|
||||||
|
#[case(4, ActiveRadarrBlock::RootFolders)]
|
||||||
|
#[case(5, ActiveRadarrBlock::Indexers)]
|
||||||
|
#[case(6, ActiveRadarrBlock::System)]
|
||||||
|
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation_no_op_when_ignoring_quit_key(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
app.push_navigation_stack(block.into());
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.right.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_delegates_system_blocks_to_system_handler(
|
fn test_delegates_system_blocks_to_system_handler(
|
||||||
#[values(
|
#[values(
|
||||||
@@ -217,12 +287,31 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = RadarrHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::Movies,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_radarr_handler_is_ready() {
|
fn test_radarr_handler_is_ready() {
|
||||||
let mut app = App::default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = true;
|
app.is_loading = true;
|
||||||
|
|
||||||
let handler = RadarrHandler::with(
|
let handler = RadarrHandler::new(
|
||||||
DEFAULT_KEYBINDINGS.esc.key,
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::System,
|
ActiveRadarrBlock::System,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user