mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-10-01 22:06:39 +01:00
633 lines
22 KiB
Python
633 lines
22 KiB
Python
"""
|
|
Unit tests for the NZBGet client.
|
|
|
|
These tests mock the requests library to test the client logic
|
|
without requiring a running NZBGet instance.
|
|
"""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
import pytest
|
|
|
|
from shelfmark.release_sources.prowlarr.clients import DownloadStatus
|
|
|
|
|
|
class TestNZBGetClientIsConfigured:
|
|
"""Tests for NZBGetClient.is_configured()."""
|
|
|
|
def test_is_configured_when_all_set(self, monkeypatch):
|
|
"""Test is_configured returns True when properly configured."""
|
|
config_values = {
|
|
"PROWLARR_USENET_CLIENT": "nzbget",
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
assert NZBGetClient.is_configured() is True
|
|
|
|
def test_is_configured_wrong_client(self, monkeypatch):
|
|
"""Test is_configured returns False when different client selected."""
|
|
config_values = {
|
|
"PROWLARR_USENET_CLIENT": "sabnzbd",
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
assert NZBGetClient.is_configured() is False
|
|
|
|
def test_is_configured_no_url(self, monkeypatch):
|
|
"""Test is_configured returns False when URL not set."""
|
|
config_values = {
|
|
"PROWLARR_USENET_CLIENT": "nzbget",
|
|
"NZBGET_URL": "",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
assert NZBGetClient.is_configured() is False
|
|
|
|
|
|
class TestNZBGetClientTestConnection:
|
|
"""Tests for NZBGetClient.test_connection()."""
|
|
|
|
def test_test_connection_success(self, monkeypatch):
|
|
"""Test successful connection."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "tegbzn6789",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.json.return_value = {"result": {"Version": "21.1"}}
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.post",
|
|
return_value=mock_response,
|
|
):
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
success, message = client.test_connection()
|
|
|
|
assert success is True
|
|
assert "21.1" in message
|
|
|
|
def test_test_connection_failure(self, monkeypatch):
|
|
"""Test failed connection."""
|
|
import requests
|
|
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "wrong",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.post",
|
|
side_effect=requests.exceptions.ConnectionError("Connection refused"),
|
|
):
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
success, message = client.test_connection()
|
|
|
|
assert success is False
|
|
assert "connect" in message.lower()
|
|
|
|
def test_test_connection_timeout(self, monkeypatch):
|
|
"""Test connection timeout."""
|
|
import requests
|
|
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.post",
|
|
side_effect=requests.exceptions.Timeout("Timeout"),
|
|
):
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
success, message = client.test_connection()
|
|
|
|
assert success is False
|
|
assert "timed" in message.lower() # "Connection timed out"
|
|
|
|
|
|
class TestNZBGetClientRPCCall:
|
|
"""Tests for NZBGetClient._rpc_call()."""
|
|
|
|
def test_rpc_call_success(self, monkeypatch):
|
|
"""Test successful RPC call."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.json.return_value = {"result": "test_result"}
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.post",
|
|
return_value=mock_response,
|
|
) as mock_post:
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
result = client._rpc_call("testmethod", ["arg1", "arg2"])
|
|
|
|
assert result == "test_result"
|
|
# Verify the request was made correctly
|
|
call_args = mock_post.call_args
|
|
assert call_args.kwargs["auth"] == ("nzbget", "password")
|
|
|
|
def test_rpc_call_error_response(self, monkeypatch):
|
|
"""Test RPC call with error response."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.json.return_value = {"error": {"message": "Invalid method"}}
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.post",
|
|
return_value=mock_response,
|
|
):
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
with pytest.raises(Exception) as exc_info:
|
|
client._rpc_call("invalid_method")
|
|
|
|
assert "Invalid method" in str(exc_info.value)
|
|
|
|
|
|
class TestNZBGetClientGetStatus:
|
|
"""Tests for NZBGetClient.get_status()."""
|
|
|
|
def test_get_status_downloading(self, monkeypatch):
|
|
"""Test status for downloading NZB."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "listgroups":
|
|
return [
|
|
{
|
|
"NZBID": 123,
|
|
"FileSizeHi": 0,
|
|
"FileSizeLo": 100000000, # 100MB
|
|
"RemainingSizeHi": 0,
|
|
"RemainingSizeLo": 50000000, # 50MB remaining
|
|
"Status": "DOWNLOADING",
|
|
"DownloadRate": 1024000,
|
|
"RemainingSec": 50,
|
|
}
|
|
]
|
|
return []
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
status = client.get_status("123")
|
|
|
|
assert status.progress == 50.0
|
|
assert status.state_value == "downloading"
|
|
assert status.complete is False
|
|
assert status.download_speed == 1024000
|
|
assert status.eta == 50
|
|
|
|
def test_get_status_complete_in_history(self, monkeypatch):
|
|
"""Test status for completed NZB in history."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "listgroups":
|
|
return [] # Not in queue
|
|
if method == "history":
|
|
return [
|
|
{
|
|
"NZBID": 123,
|
|
"Status": "SUCCESS",
|
|
"DestDir": "/downloads/completed/book",
|
|
}
|
|
]
|
|
return []
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
status = client.get_status("123")
|
|
|
|
assert status.progress == 100.0
|
|
assert status.state_value == "complete"
|
|
assert status.complete is True
|
|
assert status.file_path == "/downloads/completed/book"
|
|
|
|
def test_get_status_failed_in_history(self, monkeypatch):
|
|
"""Test status for failed NZB in history."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "listgroups":
|
|
return []
|
|
if method == "history":
|
|
return [
|
|
{
|
|
"NZBID": 123,
|
|
"Status": "FAILURE/PAR",
|
|
"DestDir": "",
|
|
}
|
|
]
|
|
return []
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
status = client.get_status("123")
|
|
|
|
assert status.state_value == "error"
|
|
assert "failed" in status.message.lower()
|
|
|
|
def test_get_status_not_found(self, monkeypatch):
|
|
"""Test status for non-existent NZB."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
return [] # Empty queue and history
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
status = client.get_status("999")
|
|
|
|
assert status.state_value == "error"
|
|
assert "not found" in status.message.lower()
|
|
|
|
def test_get_status_queued(self, monkeypatch):
|
|
"""Test status for queued NZB."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "listgroups":
|
|
return [
|
|
{
|
|
"NZBID": 123,
|
|
"FileSizeHi": 0,
|
|
"FileSizeLo": 100000000,
|
|
"RemainingSizeHi": 0,
|
|
"RemainingSizeLo": 100000000,
|
|
"Status": "QUEUED",
|
|
"DownloadRate": 0,
|
|
"RemainingSec": 0,
|
|
}
|
|
]
|
|
return []
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
status = client.get_status("123")
|
|
|
|
assert status.state_value == "queued"
|
|
|
|
|
|
class TestNZBGetClientAddDownload:
|
|
"""Tests for NZBGetClient.add_download()."""
|
|
|
|
def test_add_download_success(self, monkeypatch):
|
|
"""Test adding an NZB from URL."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
# Mock requests.get for fetching NZB
|
|
mock_get_response = MagicMock()
|
|
mock_get_response.content = b"<nzb>test</nzb>"
|
|
|
|
# Mock the RPC call result
|
|
mock_post_response = MagicMock()
|
|
mock_post_response.json.return_value = {"result": 456}
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.get",
|
|
return_value=mock_get_response,
|
|
), patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.post",
|
|
return_value=mock_post_response,
|
|
):
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
result = client.add_download(
|
|
"https://example.com/download.nzb",
|
|
"Test Book",
|
|
)
|
|
|
|
assert result == "456"
|
|
|
|
def test_add_download_fetch_failure(self, monkeypatch):
|
|
"""Test handling of NZB fetch failure."""
|
|
import requests
|
|
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
with patch(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.requests.get",
|
|
side_effect=requests.RequestException("Failed to fetch"),
|
|
):
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
client = NZBGetClient()
|
|
with pytest.raises(Exception) as exc_info:
|
|
client.add_download("https://example.com/download.nzb", "Test")
|
|
|
|
assert "fetch" in str(exc_info.value).lower()
|
|
|
|
|
|
class TestNZBGetClientRemove:
|
|
"""Tests for NZBGetClient.remove()."""
|
|
|
|
def test_remove_success(self, monkeypatch):
|
|
"""Test successful NZB removal."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "editqueue":
|
|
return True
|
|
return None
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
result = client.remove("123", delete_files=True)
|
|
|
|
assert result is True
|
|
|
|
def test_remove_with_delete_files(self, monkeypatch):
|
|
"""Test removal uses correct command based on delete_files."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
calls = []
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "editqueue":
|
|
calls.append((method, params))
|
|
return True
|
|
return None
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import (
|
|
NZBGetClient,
|
|
)
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
# Test with delete_files=True
|
|
client.remove("123", delete_files=True)
|
|
assert calls[-1][1][0] == "GroupFinalDelete"
|
|
|
|
# Test with delete_files=False
|
|
client.remove("456", delete_files=False)
|
|
assert calls[-1][1][0] == "GroupDelete"
|
|
|
|
def test_remove_falls_back_to_history_delete(self, monkeypatch):
|
|
"""If HistoryFinalDelete is unsupported, fall back to HistoryDelete."""
|
|
config_values = {
|
|
"NZBGET_URL": "http://localhost:6789",
|
|
"NZBGET_USERNAME": "nzbget",
|
|
"NZBGET_PASSWORD": "password",
|
|
"NZBGET_CATEGORY": "Books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.release_sources.prowlarr.clients.nzbget.config.get",
|
|
lambda key, default="": config_values.get(key, default),
|
|
)
|
|
|
|
calls = []
|
|
|
|
def mock_rpc_call(method, params=None):
|
|
if method == "editqueue":
|
|
calls.append((method, params))
|
|
# Succeed only on HistoryDelete.
|
|
return params is not None and params[0] == "HistoryDelete"
|
|
return None
|
|
|
|
from shelfmark.release_sources.prowlarr.clients.nzbget import NZBGetClient
|
|
|
|
with patch.object(NZBGetClient, "__init__", lambda x: None):
|
|
client = NZBGetClient()
|
|
client.url = "http://localhost:6789"
|
|
client.username = "nzbget"
|
|
client.password = "password"
|
|
client._category = "Books"
|
|
client._rpc_call = mock_rpc_call
|
|
|
|
result = client.remove("123", delete_files=True)
|
|
|
|
assert result is True
|
|
assert [call[1][0] for call in calls] == ["GroupFinalDelete", "HistoryFinalDelete", "HistoryDelete"]
|