"""Tests for src/TVDBProvider/tvdb_client.py.""" import sys from pathlib import Path from unittest.mock import patch, MagicMock, PropertyMock sys.path.insert(0, str(Path(__file__).parent.parent)) import pytest from src.TVDBProvider.tvdb_client import TVDBClient, MockTVDBClient class TestTVDBClientInit: def test_init(self): client = TVDBClient() assert client.base_url == "https://api4.thetvdb.com/v4" assert client.token is None assert "Content-Type" in client.headers def test_init_has_cache(self): client = TVDBClient() assert client.cache is not None class TestTVDBClientAuthenticate: @patch("src.TVDBProvider.tvdb_client.requests.post") def test_auth_success(self, mock_post): mock_post.return_value.status_code = 200 mock_post.return_value.json.return_value = {"data": {"token": "abc123"}} client = TVDBClient() assert client.authenticate("my_api_key") is True assert client.token == "abc123" assert "Bearer abc123" in client.headers["Authorization"] @patch("src.TVDBProvider.tvdb_client.requests.post") def test_auth_failure_status(self, mock_post): mock_post.return_value.status_code = 401 client = TVDBClient() assert client.authenticate("bad_key") is False assert client.token is None @patch("src.TVDBProvider.tvdb_client.requests.post") def test_auth_exception(self, mock_post): mock_post.side_effect = Exception("network error") client = TVDBClient() assert client.authenticate("key") is False class TestTVDBClientSearch: @patch("src.TVDBProvider.tvdb_client.requests.get") def test_search_success(self, mock_get): mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = { "data": [{"tvdb_id": 123, "name": "Test Show"}] } client = TVDBClient() client.token = "tok" result = client.search_series("Test Show") assert result["tvdb_id"] == 123 @patch("src.TVDBProvider.tvdb_client.requests.get") def test_search_no_results(self, mock_get): mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = {"data": []} client = TVDBClient() client.token = "tok" result = client.search_series("NoMatch") assert result is None def test_search_not_authenticated(self): client = TVDBClient() result = client.search_series("Show") assert result is None @patch("src.TVDBProvider.tvdb_client.requests.get") def test_search_error(self, mock_get): mock_get.side_effect = Exception("timeout") client = TVDBClient() client.token = "tok" result = client.search_series("Show") assert result is None class TestTVDBClientSeasonEpisodes: @patch("src.TVDBProvider.tvdb_client.requests.get") def test_get_season_episodes(self, mock_get): mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = { "data": {"episodes": [{"number": 1, "name": "E1"}]} } client = TVDBClient() client.token = "tok" result = client.get_season_episodes(123, 1) assert len(result) == 1 def test_episodes_not_authenticated(self): client = TVDBClient() result = client.get_season_episodes(123, 1) assert result is None class TestTVDBClientSeriesInfo: @patch.object(TVDBClient, "search_series") def test_get_series_info(self, mock_search): mock_search.return_value = {"tvdb_id": 123, "name": "Test", "slug": "test", "year": 2020} client = TVDBClient() client.token = "tok" result = client.get_series_info("Test") assert result["id"] == 123 assert result["name"] == "Test" @patch.object(TVDBClient, "search_series") def test_get_series_info_no_match(self, mock_search): mock_search.return_value = None client = TVDBClient() client.token = "tok" result = client.get_series_info("NoMatch") assert result is None class TestTVDBClientEpisodeDurations: def test_get_episode_durations(self, tmp_path): with patch("src.TVDBProvider.tvdb_client.TVDBClient.__init__") as mock_init: mock_init.return_value = None client = TVDBClient() client.base_url = "https://api4.thetvdb.com/v4" client.token = "tok" client.headers = {"Content-Type": "application/json"} mock_cache = MagicMock() mock_cache.get_cached_episodes.return_value = None client.cache = mock_cache client.get_series_info = MagicMock(return_value={"id": 123}) client.get_season_episodes = MagicMock(return_value=[ {"number": 1, "name": "E1", "runtime": 45, "aired": "2020-01-01"}, {"number": 2, "name": "E2", "runtime": 50, "aired": "2020-01-08"}, ]) result = client.get_episode_durations("Test", 1) assert len(result) == 2 assert result[0]["episode_number"] == 1 assert result[0]["runtime"] == 45 mock_cache.cache_episodes.assert_called_once() def test_get_episode_durations_cached(self, tmp_path): with patch("src.TVDBProvider.tvdb_client.TVDBClient.__init__") as mock_init: mock_init.return_value = None client = TVDBClient() client.token = "tok" mock_cache = MagicMock() mock_cache.get_cached_episodes.return_value = [ {"episode_number": 1, "runtime": 45} ] client.cache = mock_cache result = client.get_episode_durations("Test", 1) assert len(result) == 1 def test_get_episode_durations_no_series(self, tmp_path): with patch("src.TVDBProvider.tvdb_client.TVDBClient.__init__") as mock_init: mock_init.return_value = None client = TVDBClient() client.token = "tok" mock_cache = MagicMock() mock_cache.get_cached_episodes.return_value = None client.cache = mock_cache client.get_series_info = MagicMock(return_value=None) result = client.get_episode_durations("NoShow", 1) assert result is None class TestMockTVDBClient: def test_mock_auth(self): client = MockTVDBClient() assert client.authenticate() is True assert client.authenticated is True def test_mock_auth_with_key(self): client = MockTVDBClient() assert client.authenticate("some_key") is True def test_mock_episodes_unauthenticated(self): client = MockTVDBClient() result = client.get_episode_durations("Show", 1) assert result is None def test_mock_episodes_drama(self): client = MockTVDBClient() client.authenticate() result = client.get_episode_durations("Game of Thrones", 1) assert len(result) == 10 def test_mock_episodes_sitcom(self): client = MockTVDBClient() client.authenticate() result = client.get_episode_durations("Friends", 1) assert len(result) == 24 def test_mock_episodes_default(self): client = MockTVDBClient() client.authenticate() result = client.get_episode_durations("Unknown Show", 1) assert len(result) == 22 def test_mock_episode_structure(self): client = MockTVDBClient() client.authenticate() result = client.get_episode_durations("Test", 1) ep = result[0] assert ep["episode_number"] == 1 assert ep["runtime"] == 45 assert "name" in ep assert "aired" in ep def test_mock_cached_episodes(self): client = MockTVDBClient() client.authenticate() r1 = client.get_episode_durations("Test", 1) r2 = client.get_episode_durations("Test", 1) assert r1 is not None and r2 is not None