Files
tvh2jellyfin/tests/test_jellyfin.py
Dan Head a8b247a83f Initial commit: TVH2Jellyfin application
A Docker-based Python application that transfers completed recordings
from TVHeadend to Jellyfin media storage via SCP.

Features:
- Monitors TVHeadend for completed recordings via JSON API
- Transfers files via SCP with SSH key authentication
- Organizes files by show name
- Deletes recordings from TVHeadend after successful transfer
- Tracks transferred files to avoid duplicates
- Dry run mode for testing without making changes
2026-04-03 09:31:04 +01:00

151 lines
4.7 KiB
Python

"""Tests for Jellyfin client."""
from unittest.mock import Mock, patch
import pytest
import requests
from tvh2jellyfin.jellyfin import JellyfinClient, JellyfinConfig
class TestJellyfinConfig:
"""Tests for JellyfinConfig dataclass."""
def test_config_defaults(self):
"""Test default values."""
config = JellyfinConfig(
url="http://localhost:8096",
api_key="test_key",
)
assert config.library_id is None
assert config.enabled is True
def test_config_with_library_id(self):
"""Test config with specific library ID."""
config = JellyfinConfig(
url="http://localhost:8096",
api_key="test_key",
library_id="abc123",
)
assert config.library_id == "abc123"
class TestJellyfinClient:
"""Tests for Jellyfin API client."""
@pytest.fixture
def config(self):
return JellyfinConfig(
url="http://localhost:8096",
api_key="test_api_key",
)
@pytest.fixture
def config_with_library(self):
return JellyfinConfig(
url="http://localhost:8096",
api_key="test_api_key",
library_id="lib123",
)
@pytest.fixture
def client(self, config):
return JellyfinClient(config)
@pytest.fixture
def client_with_library(self, config_with_library):
return JellyfinClient(config_with_library)
def test_url_normalization(self):
"""Test that trailing slashes are removed from URL."""
config = JellyfinConfig(
url="http://localhost:8096/",
api_key="test_key",
)
client = JellyfinClient(config)
assert client.base_url == "http://localhost:8096"
def test_headers_set(self, client):
"""Test that auth headers are set correctly."""
assert client.session.headers["X-MediaBrowser-Token"] == "test_api_key"
assert client.session.headers["Content-Type"] == "application/json"
@patch("requests.Session.get")
def test_test_connection_success(self, mock_get, client):
"""Test successful connection test."""
mock_get.return_value.json.return_value = {
"ServerName": "Test Server",
"Version": "10.8.0",
}
mock_get.return_value.raise_for_status = Mock()
result = client.test_connection()
assert result is True
mock_get.assert_called_once()
assert "/System/Info" in mock_get.call_args[0][0]
@patch("requests.Session.get")
def test_test_connection_failure(self, mock_get, client):
"""Test connection test failure."""
mock_get.side_effect = requests.exceptions.ConnectionError("Connection refused")
result = client.test_connection()
assert result is False
@patch("requests.Session.post")
def test_trigger_library_scan_full(self, mock_post, client):
"""Test triggering full library scan."""
mock_post.return_value.raise_for_status = Mock()
result = client.trigger_library_scan()
assert result is True
mock_post.assert_called_once()
assert "/Library/Refresh" in mock_post.call_args[0][0]
@patch("requests.Session.post")
def test_trigger_library_scan_specific_library(self, mock_post, client_with_library):
"""Test triggering scan for specific library."""
mock_post.return_value.raise_for_status = Mock()
result = client_with_library.trigger_library_scan()
assert result is True
mock_post.assert_called_once()
assert "/Items/lib123/Refresh" in mock_post.call_args[0][0]
@patch("requests.Session.post")
def test_trigger_library_scan_failure(self, mock_post, client):
"""Test library scan trigger failure."""
mock_post.side_effect = requests.exceptions.RequestException("API error")
result = client.trigger_library_scan()
assert result is False
@patch("requests.Session.get")
def test_get_libraries_success(self, mock_get, client):
"""Test getting list of libraries."""
mock_get.return_value.json.return_value = [
{"Name": "TV Shows", "ItemId": "tv123"},
{"Name": "Movies", "ItemId": "mov456"},
]
mock_get.return_value.raise_for_status = Mock()
result = client.get_libraries()
assert len(result) == 2
assert result[0] == {"name": "TV Shows", "id": "tv123"}
assert result[1] == {"name": "Movies", "id": "mov456"}
@patch("requests.Session.get")
def test_get_libraries_failure(self, mock_get, client):
"""Test getting libraries when API fails."""
mock_get.side_effect = requests.exceptions.RequestException("API error")
result = client.get_libraries()
assert result == []