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
This commit is contained in:
117
tests/test_episode_resolver.py
Normal file
117
tests/test_episode_resolver.py
Normal file
@@ -0,0 +1,117 @@
|
||||
"""Tests for episode resolver."""
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
|
||||
from tvh2jellyfin.episode_resolver import EpisodeResolver
|
||||
from tvh2jellyfin.tvdb import EpisodeInfo
|
||||
|
||||
|
||||
class TestEpisodeResolver:
|
||||
"""Tests for EpisodeResolver."""
|
||||
|
||||
@pytest.fixture
|
||||
def mock_episode_info(self):
|
||||
return EpisodeInfo(
|
||||
series_id=456,
|
||||
series_name="Test Show",
|
||||
season=1,
|
||||
episode=5,
|
||||
episode_name="Pilot",
|
||||
air_date="2024-01-15",
|
||||
)
|
||||
|
||||
def test_lookup_tvdb_success(self, mock_episode_info):
|
||||
"""Test successful lookup from TVDB."""
|
||||
mock_tvdb = Mock()
|
||||
mock_tvdb.lookup_episode.return_value = mock_episode_info
|
||||
|
||||
resolver = EpisodeResolver(tvdb_client=mock_tvdb, tvmaze_client=None)
|
||||
result, source = resolver.lookup("Test Show", 1705312800)
|
||||
|
||||
assert result is not None
|
||||
assert result.season == 1
|
||||
assert result.episode == 5
|
||||
assert source == "tvdb"
|
||||
|
||||
def test_lookup_tvmaze_fallback(self, mock_episode_info):
|
||||
"""Test fallback to TVmaze when TVDB fails."""
|
||||
mock_tvdb = Mock()
|
||||
mock_tvdb.lookup_episode.return_value = None
|
||||
|
||||
mock_tvmaze = Mock()
|
||||
mock_tvmaze.lookup_episode.return_value = mock_episode_info
|
||||
|
||||
resolver = EpisodeResolver(tvdb_client=mock_tvdb, tvmaze_client=mock_tvmaze)
|
||||
result, source = resolver.lookup("Test Show", 1705312800)
|
||||
|
||||
assert result is not None
|
||||
assert source == "tvmaze"
|
||||
|
||||
def test_lookup_tvdb_exception_fallback(self, mock_episode_info):
|
||||
"""Test fallback to TVmaze when TVDB raises exception."""
|
||||
mock_tvdb = Mock()
|
||||
mock_tvdb.lookup_episode.side_effect = Exception("API Error")
|
||||
|
||||
mock_tvmaze = Mock()
|
||||
mock_tvmaze.lookup_episode.return_value = mock_episode_info
|
||||
|
||||
resolver = EpisodeResolver(tvdb_client=mock_tvdb, tvmaze_client=mock_tvmaze)
|
||||
result, source = resolver.lookup("Test Show", 1705312800)
|
||||
|
||||
assert result is not None
|
||||
assert source == "tvmaze"
|
||||
|
||||
def test_lookup_both_fail(self):
|
||||
"""Test when both sources fail."""
|
||||
mock_tvdb = Mock()
|
||||
mock_tvdb.lookup_episode.return_value = None
|
||||
|
||||
mock_tvmaze = Mock()
|
||||
mock_tvmaze.lookup_episode.return_value = None
|
||||
|
||||
resolver = EpisodeResolver(tvdb_client=mock_tvdb, tvmaze_client=mock_tvmaze)
|
||||
result, source = resolver.lookup("Unknown Show", 1705312800)
|
||||
|
||||
assert result is None
|
||||
assert source == "none"
|
||||
|
||||
def test_lookup_no_clients(self):
|
||||
"""Test when no clients are available."""
|
||||
resolver = EpisodeResolver(tvdb_client=None, tvmaze_client=None)
|
||||
result, source = resolver.lookup("Test Show", 1705312800)
|
||||
|
||||
assert result is None
|
||||
assert source == "none"
|
||||
|
||||
def test_lookup_tvmaze_only(self, mock_episode_info):
|
||||
"""Test with only TVmaze client."""
|
||||
mock_tvmaze = Mock()
|
||||
mock_tvmaze.lookup_episode.return_value = mock_episode_info
|
||||
|
||||
resolver = EpisodeResolver(tvdb_client=None, tvmaze_client=mock_tvmaze)
|
||||
result, source = resolver.lookup("Test Show", 1705312800)
|
||||
|
||||
assert result is not None
|
||||
assert source == "tvmaze"
|
||||
|
||||
def test_is_available_with_tvdb(self):
|
||||
"""Test is_available with TVDB client."""
|
||||
resolver = EpisodeResolver(tvdb_client=Mock(), tvmaze_client=None)
|
||||
assert resolver.is_available() is True
|
||||
|
||||
def test_is_available_with_tvmaze(self):
|
||||
"""Test is_available with TVmaze client."""
|
||||
resolver = EpisodeResolver(tvdb_client=None, tvmaze_client=Mock())
|
||||
assert resolver.is_available() is True
|
||||
|
||||
def test_is_available_with_both(self):
|
||||
"""Test is_available with both clients."""
|
||||
resolver = EpisodeResolver(tvdb_client=Mock(), tvmaze_client=Mock())
|
||||
assert resolver.is_available() is True
|
||||
|
||||
def test_is_available_with_none(self):
|
||||
"""Test is_available with no clients."""
|
||||
resolver = EpisodeResolver(tvdb_client=None, tvmaze_client=None)
|
||||
assert resolver.is_available() is False
|
||||
Reference in New Issue
Block a user