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
122 lines
3.9 KiB
Python
122 lines
3.9 KiB
Python
"""Tests for TVmaze client."""
|
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from tvh2jellyfin.tvmaze import TVMazeClient, TVMazeConfig
|
|
|
|
|
|
class TestTVMazeClient:
|
|
"""Tests for TVmaze API client."""
|
|
|
|
@pytest.fixture
|
|
def config(self):
|
|
return TVMazeConfig(cache_ttl=3600, enabled=True)
|
|
|
|
@pytest.fixture
|
|
def client(self, config):
|
|
return TVMazeClient(config)
|
|
|
|
@patch("requests.Session.get")
|
|
def test_search_series_success(self, mock_get, client):
|
|
"""Test successful series search."""
|
|
mock_get.return_value.status_code = 200
|
|
mock_get.return_value.json.return_value = {
|
|
"id": 789,
|
|
"name": "Coronation Street",
|
|
}
|
|
mock_get.return_value.raise_for_status = Mock()
|
|
|
|
result = client.search_series("Coronation Street")
|
|
|
|
assert result is not None
|
|
assert result[0] == 789
|
|
assert result[1] == "Coronation Street"
|
|
|
|
@patch("requests.Session.get")
|
|
def test_search_series_not_found(self, mock_get, client):
|
|
"""Test series search with 404 response."""
|
|
mock_get.return_value.status_code = 404
|
|
|
|
result = client.search_series("Nonexistent Show")
|
|
|
|
assert result is None
|
|
|
|
@patch("requests.Session.get")
|
|
def test_get_episode_by_date_success(self, mock_get, client):
|
|
"""Test successful episode lookup by date."""
|
|
mock_get.return_value.status_code = 200
|
|
mock_get.return_value.json.return_value = [
|
|
{"season": 67, "number": 4, "name": "Episode 4"}
|
|
]
|
|
mock_get.return_value.raise_for_status = Mock()
|
|
|
|
result = client.get_episode_by_date(789, "2026-01-06", "Coronation Street")
|
|
|
|
assert result is not None
|
|
assert result.season == 67
|
|
assert result.episode == 4
|
|
assert result.series_name == "Coronation Street"
|
|
|
|
@patch("requests.Session.get")
|
|
def test_get_episode_by_date_not_found(self, mock_get, client):
|
|
"""Test episode lookup with no results."""
|
|
mock_get.return_value.status_code = 404
|
|
|
|
result = client.get_episode_by_date(789, "2026-01-01", "Coronation Street")
|
|
|
|
assert result is None
|
|
|
|
@patch("requests.Session.get")
|
|
def test_lookup_episode_full_flow(self, mock_get, client):
|
|
"""Test full episode lookup flow."""
|
|
# Set up responses for search and episode lookup
|
|
mock_get.return_value.status_code = 200
|
|
mock_get.return_value.json.side_effect = [
|
|
{"id": 789, "name": "Coronation Street"}, # Search response
|
|
[{"season": 67, "number": 4, "name": "Episode 4"}], # Episode response
|
|
]
|
|
mock_get.return_value.raise_for_status = Mock()
|
|
|
|
# Timestamp for 2026-01-06
|
|
result = client.lookup_episode("Coronation Street", 1767744000)
|
|
|
|
assert result is not None
|
|
assert result.series_name == "Coronation Street"
|
|
assert result.formatted_episode == "S67E04"
|
|
|
|
def test_caching_series(self, client):
|
|
"""Test that series cache prevents duplicate calls."""
|
|
import time
|
|
|
|
# Manually populate cache
|
|
client._series_cache["coronation street"] = (789, "Coronation Street", time.time())
|
|
|
|
# Should use cache
|
|
result = client.search_series("coronation street")
|
|
|
|
assert result == (789, "Coronation Street")
|
|
|
|
def test_caching_episodes(self, client):
|
|
"""Test that episode cache prevents duplicate calls."""
|
|
import time
|
|
|
|
from tvh2jellyfin.tvdb import EpisodeInfo
|
|
|
|
cached_episode = EpisodeInfo(
|
|
series_id=789,
|
|
series_name="Coronation Street",
|
|
season=67,
|
|
episode=4,
|
|
episode_name="Episode 4",
|
|
air_date="2026-01-06",
|
|
)
|
|
client._episode_cache["789:2026-01-06"] = (cached_episode, time.time())
|
|
|
|
# Should use cache
|
|
result = client.get_episode_by_date(789, "2026-01-06", "Coronation Street")
|
|
|
|
assert result is not None
|
|
assert result.season == 67
|