mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-09-24 13:40:21 +01:00
- Add certificate validation setting - Fix some OIDC providers not linking emails to local users - Reintroduce sort by peers option for prowlarr results - Fix "All languages" search query reverting to default language - Fix download/request dismissal with multiple admin users - Fix download / request behavior on details modal
743 lines
28 KiB
Python
743 lines
28 KiB
Python
"""
|
|
Unit tests for the Transmission client.
|
|
|
|
These tests mock the transmission-rpc library to test the client logic
|
|
without requiring a running Transmission instance.
|
|
"""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
from datetime import timedelta
|
|
import pytest
|
|
import sys
|
|
import types
|
|
|
|
from shelfmark.download.clients import DownloadStatus
|
|
|
|
|
|
class MockTorrentStatus:
|
|
"""Mock for Transmission's torrent status enum."""
|
|
|
|
def __init__(self, value):
|
|
self.value = value
|
|
|
|
|
|
class MockTorrent:
|
|
"""Mock Transmission torrent object."""
|
|
|
|
def __init__(
|
|
self,
|
|
hash_string="abc123",
|
|
name="Test Torrent",
|
|
percent_done=0.5,
|
|
status="downloading",
|
|
rate_download=1024000,
|
|
eta=None,
|
|
download_dir="/downloads",
|
|
):
|
|
self.hashString = hash_string
|
|
self.name = name
|
|
self.percent_done = percent_done
|
|
self.status = MockTorrentStatus(status)
|
|
self.rate_download = rate_download
|
|
self.download_dir = download_dir
|
|
if eta is not None:
|
|
self.eta = timedelta(seconds=eta)
|
|
else:
|
|
self.eta = None
|
|
|
|
|
|
class MockSession:
|
|
"""Mock Transmission session object."""
|
|
|
|
def __init__(self, version="4.0.0"):
|
|
self.version = version
|
|
|
|
|
|
def make_config_getter(values):
|
|
"""Create a config.get function that returns values from a dict."""
|
|
def getter(key, default=""):
|
|
return values.get(key, default)
|
|
return getter
|
|
|
|
|
|
def create_mock_transmission_rpc_module():
|
|
"""Create a mock transmission_rpc module."""
|
|
mock_module = MagicMock()
|
|
mock_module.Client = MagicMock()
|
|
return mock_module
|
|
|
|
|
|
class TestTransmissionClientIsConfigured:
|
|
"""Tests for TransmissionClient.is_configured()."""
|
|
|
|
def test_is_configured_when_all_set(self, monkeypatch):
|
|
"""Test is_configured returns True when properly configured."""
|
|
config_values = {
|
|
"PROWLARR_TORRENT_CLIENT": "transmission",
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
assert TransmissionClient.is_configured() is True
|
|
|
|
def test_is_configured_wrong_client(self, monkeypatch):
|
|
"""Test is_configured returns False when different client selected."""
|
|
config_values = {
|
|
"PROWLARR_TORRENT_CLIENT": "qbittorrent",
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
assert TransmissionClient.is_configured() is False
|
|
|
|
def test_is_configured_no_url(self, monkeypatch):
|
|
"""Test is_configured returns False when URL not set."""
|
|
config_values = {
|
|
"PROWLARR_TORRENT_CLIENT": "transmission",
|
|
"TRANSMISSION_URL": "",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
assert TransmissionClient.is_configured() is False
|
|
|
|
|
|
class TestTransmissionClientTestConnection:
|
|
"""Tests for TransmissionClient.test_connection()."""
|
|
|
|
def test_init_passes_https_protocol(self, monkeypatch):
|
|
"""Test HTTPS URL causes protocol=https to be passed to transmission-rpc Client."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "https://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_session.return_value = MockSession(version="4.0.5")
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
TransmissionClient()
|
|
assert mock_transmission_rpc.Client.call_args.kwargs.get("protocol") == "https"
|
|
|
|
def test_init_applies_certificate_validation_to_session(self, monkeypatch):
|
|
"""Test Transmission client applies verify mode onto transmission-rpc session."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "https://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_http_session = MagicMock()
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance._http_session = mock_http_session
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients import transmission as transmission_module
|
|
|
|
monkeypatch.setattr(transmission_module, "get_ssl_verify", lambda _url: False)
|
|
transmission_module.TransmissionClient()
|
|
|
|
assert mock_http_session.verify is False
|
|
|
|
def test_init_disables_verify_before_constructor_bootstrap(self, monkeypatch):
|
|
"""verify=False must be in place before transmission-rpc constructor bootstraps RPC session."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "https://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
transmission_pkg = types.ModuleType("transmission_rpc")
|
|
transmission_pkg.__path__ = [] # Mark as package for submodule imports.
|
|
transmission_client_mod = types.ModuleType("transmission_rpc.client")
|
|
|
|
def _base_session_factory():
|
|
return types.SimpleNamespace(verify=True)
|
|
|
|
transmission_client_mod.requests = types.SimpleNamespace(Session=_base_session_factory)
|
|
|
|
def _fake_client_ctor(**_kwargs):
|
|
bootstrap_session = transmission_client_mod.requests.Session()
|
|
if bootstrap_session.verify is not False:
|
|
raise RuntimeError("verify not disabled during constructor bootstrap")
|
|
client = MagicMock()
|
|
client._http_session = bootstrap_session
|
|
client.get_session.return_value = MockSession(version="4.0.5")
|
|
return client
|
|
|
|
transmission_pkg.Client = _fake_client_ctor
|
|
transmission_pkg.client = transmission_client_mod
|
|
|
|
with patch.dict(
|
|
"sys.modules",
|
|
{
|
|
"transmission_rpc": transmission_pkg,
|
|
"transmission_rpc.client": transmission_client_mod,
|
|
},
|
|
):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients import transmission as transmission_module
|
|
|
|
monkeypatch.setattr(transmission_module, "get_ssl_verify", lambda _url: False)
|
|
client = transmission_module.TransmissionClient()
|
|
assert client._client._http_session.verify is False
|
|
|
|
def test_test_connection_success(self, monkeypatch):
|
|
"""Test successful connection."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_session.return_value = MockSession(version="4.0.5")
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
# Force reimport to use mock
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
success, message = client.test_connection()
|
|
|
|
assert success is True
|
|
assert "4.0.5" in message
|
|
|
|
def test_test_connection_failure(self, monkeypatch):
|
|
"""Test failed connection."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "wrong",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_session.side_effect = Exception("Connection refused")
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
success, message = client.test_connection()
|
|
|
|
assert success is False
|
|
assert "failed" in message.lower()
|
|
|
|
|
|
class TestTransmissionClientGetStatus:
|
|
"""Tests for TransmissionClient.get_status()."""
|
|
|
|
def test_get_status_downloading(self, monkeypatch):
|
|
"""Test status for downloading torrent."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(percent_done=0.5, status="downloading", rate_download=1024000)
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
status = client.get_status("abc123")
|
|
|
|
assert status.progress == 50.0
|
|
assert status.state_value == "downloading"
|
|
assert status.complete is False
|
|
assert status.download_speed == 1024000
|
|
|
|
def test_get_status_seeding(self, monkeypatch):
|
|
"""Test status for seeding (complete) torrent."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(
|
|
percent_done=1.0,
|
|
status="seeding",
|
|
download_dir="/downloads",
|
|
)
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
status = client.get_status("abc123")
|
|
|
|
assert status.progress == 100.0
|
|
assert status.complete is True
|
|
assert "/downloads/Test Torrent" in status.file_path
|
|
|
|
def test_get_status_not_found(self, monkeypatch):
|
|
"""Test status for non-existent torrent."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.side_effect = KeyError("not found")
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
status = client.get_status("nonexistent")
|
|
|
|
assert status.state_value == "error"
|
|
assert "not found" in status.message.lower()
|
|
|
|
def test_get_status_paused(self, monkeypatch):
|
|
"""Test status for paused torrent."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(percent_done=0.3, status="stopped")
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
status = client.get_status("abc123")
|
|
|
|
assert status.state_value == "paused"
|
|
|
|
def test_get_status_with_eta(self, monkeypatch):
|
|
"""Test status includes ETA when available."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(percent_done=0.5, status="downloading", eta=3600)
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
status = client.get_status("abc123")
|
|
|
|
assert status.eta == 3600
|
|
|
|
|
|
class TestTransmissionClientAddDownload:
|
|
"""Tests for TransmissionClient.add_download()."""
|
|
|
|
def test_add_download_magnet_success(self, monkeypatch):
|
|
"""Test adding a magnet link."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(hash_string="3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0")
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.add_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
magnet = "magnet:?xt=urn:btih:3B245504CF5F11BBDBE1201CEA6A6BF45AEE1BC0&dn=test"
|
|
result = client.add_download(magnet, "Test Download")
|
|
|
|
assert result == "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0"
|
|
mock_client_instance.add_torrent.assert_called_once()
|
|
|
|
def test_add_download_uses_labels(self, monkeypatch):
|
|
"""Test that add_download sets labels/category."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "mybooks",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(hash_string="abc123")
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.add_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
magnet = "magnet:?xt=urn:btih:abc123&dn=test"
|
|
client.add_download(magnet, "Test")
|
|
|
|
# Verify labels were passed
|
|
call_kwargs = mock_client_instance.add_torrent.call_args
|
|
assert call_kwargs.kwargs.get("labels") == ["mybooks"]
|
|
|
|
def test_add_download_uses_configured_download_dir(self, monkeypatch):
|
|
"""Test that add_download passes configured download directory."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "mybooks",
|
|
"TRANSMISSION_DOWNLOAD_DIR": "/downloads/books",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(hash_string="abc123")
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.add_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
magnet = "magnet:?xt=urn:btih:abc123&dn=test"
|
|
client.add_download(magnet, "Test")
|
|
|
|
call_kwargs = mock_client_instance.add_torrent.call_args
|
|
assert call_kwargs.kwargs.get("labels") == ["mybooks"]
|
|
assert call_kwargs.kwargs.get("download_dir") == "/downloads/books"
|
|
|
|
|
|
class TestTransmissionClientRemove:
|
|
"""Tests for TransmissionClient.remove()."""
|
|
|
|
def test_remove_success(self, monkeypatch):
|
|
"""Test successful torrent removal."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
result = client.remove("abc123", delete_files=True)
|
|
|
|
assert result is True
|
|
mock_client_instance.remove_torrent.assert_called_once_with(
|
|
"abc123", delete_data=True
|
|
)
|
|
|
|
def test_remove_failure(self, monkeypatch):
|
|
"""Test failed torrent removal."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.remove_torrent.side_effect = Exception("Not found")
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
result = client.remove("abc123")
|
|
|
|
assert result is False
|
|
|
|
|
|
class TestTransmissionClientFindExisting:
|
|
"""Tests for TransmissionClient.find_existing()."""
|
|
|
|
def test_find_existing_found(self, monkeypatch):
|
|
"""Test finding existing torrent by magnet hash."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_torrent = MockTorrent(
|
|
hash_string="3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0",
|
|
percent_done=0.5,
|
|
status="downloading",
|
|
)
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.return_value = mock_torrent
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
magnet = "magnet:?xt=urn:btih:3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0&dn=test"
|
|
result = client.find_existing(magnet)
|
|
|
|
assert result is not None
|
|
download_id, status = result
|
|
assert download_id == "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0"
|
|
assert isinstance(status, DownloadStatus)
|
|
|
|
def test_find_existing_not_found(self, monkeypatch):
|
|
"""Test finding non-existent torrent."""
|
|
config_values = {
|
|
"TRANSMISSION_URL": "http://localhost:9091",
|
|
"TRANSMISSION_USERNAME": "admin",
|
|
"TRANSMISSION_PASSWORD": "password",
|
|
"TRANSMISSION_CATEGORY": "test",
|
|
}
|
|
monkeypatch.setattr(
|
|
"shelfmark.download.clients.transmission.config.get",
|
|
make_config_getter(config_values),
|
|
)
|
|
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.get_torrent.side_effect = KeyError("not found")
|
|
|
|
mock_transmission_rpc = create_mock_transmission_rpc_module()
|
|
mock_transmission_rpc.Client.return_value = mock_client_instance
|
|
|
|
with patch.dict("sys.modules", {"transmission_rpc": mock_transmission_rpc}):
|
|
if "shelfmark.download.clients.transmission" in sys.modules:
|
|
del sys.modules["shelfmark.download.clients.transmission"]
|
|
|
|
from shelfmark.download.clients.transmission import (
|
|
TransmissionClient,
|
|
)
|
|
|
|
client = TransmissionClient()
|
|
magnet = "magnet:?xt=urn:btih:abc123&dn=test"
|
|
result = client.find_existing(magnet)
|
|
|
|
assert result is None
|