import uuid from unittest.mock import MagicMock import pytest from media_manager.exceptions import NotFoundError from media_manager.tv.schemas import Show, ShowId, SeasonId from media_manager.tv.service import TvService from media_manager.indexer.schemas import IndexerQueryResult, IndexerQueryResultId from media_manager.metadataProvider.schemas import MetaDataProviderSearchResult @pytest.fixture def mock_tv_repository(): return MagicMock() @pytest.fixture def mock_torrent_service(): return MagicMock() @pytest.fixture def mock_indexer_service(): return MagicMock() @pytest.fixture def tv_service(mock_tv_repository, mock_torrent_service, mock_indexer_service): return TvService( tv_repository=mock_tv_repository, torrent_service=mock_torrent_service, indexer_service=mock_indexer_service, ) def test_add_show(tv_service, mock_tv_repository, mock_torrent_service): external_id = 123 # Now we pass a mock metadata provider object mock_metadata_provider = MagicMock() show_data = Show( id=ShowId(uuid.uuid4()), name="Test Show", overview="Test Overview", year=2022, external_id=external_id, metadata_provider="tmdb", seasons=[], ) mock_metadata_provider.get_show_metadata.return_value = show_data mock_metadata_provider.download_show_poster_image.return_value = True mock_tv_repository.save_show.return_value = show_data result = tv_service.add_show( external_id=external_id, metadata_provider=mock_metadata_provider ) mock_metadata_provider.get_show_metadata.assert_called_once_with(id=external_id) mock_tv_repository.save_show.assert_called_once_with(show=show_data) mock_metadata_provider.download_show_poster_image.assert_called_once_with( show=show_data ) assert result == show_data def test_add_show_with_invalid_metadata( tv_service, mock_tv_repository, mock_torrent_service ): external_id = 123 mock_metadata_provider = MagicMock() # Simulate metadata provider returning None mock_metadata_provider.get_show_metadata.return_value = None mock_metadata_provider.download_show_poster_image.return_value = False mock_tv_repository.save_show.return_value = None result = tv_service.add_show( external_id=external_id, metadata_provider=mock_metadata_provider ) mock_metadata_provider.get_show_metadata.assert_called_once_with(id=external_id) assert result is None def test_check_if_show_exists_by_external_id( tv_service, mock_tv_repository, mock_torrent_service ): external_id = 123 metadata_provider = "tmdb" mock_tv_repository.get_show_by_external_id.return_value = "show_obj" assert tv_service.check_if_show_exists( external_id=external_id, metadata_provider=metadata_provider ) mock_tv_repository.get_show_by_external_id.assert_called_once_with( external_id=external_id, metadata_provider=metadata_provider ) mock_tv_repository.get_show_by_external_id.side_effect = NotFoundError assert not tv_service.check_if_show_exists( external_id=external_id, metadata_provider=metadata_provider ) def test_check_if_show_exists_by_show_id( tv_service, mock_tv_repository, mock_torrent_service ): show_id = ShowId(uuid.uuid4()) mock_tv_repository.get_show_by_id.return_value = "show_obj" assert tv_service.check_if_show_exists(show_id=show_id) mock_tv_repository.get_show_by_id.assert_called_once_with(show_id=show_id) mock_tv_repository.get_show_by_id.side_effect = NotFoundError assert not tv_service.check_if_show_exists(show_id=show_id) def test_check_if_show_exists_with_invalid_uuid( tv_service, mock_tv_repository, mock_torrent_service ): # Simulate NotFoundError for a random UUID show_id = ShowId(uuid.uuid4()) mock_tv_repository.get_show_by_id.side_effect = NotFoundError assert not tv_service.check_if_show_exists(show_id=show_id) def test_check_if_show_exists_raises_value_error(tv_service, mock_torrent_service): with pytest.raises(ValueError): tv_service.check_if_show_exists() def test_add_season_request(tv_service, mock_tv_repository, mock_torrent_service): season_request = MagicMock() mock_tv_repository.add_season_request.return_value = season_request result = tv_service.add_season_request(season_request) mock_tv_repository.add_season_request.assert_called_once_with( season_request=season_request ) assert result == season_request def test_get_season_request_by_id(tv_service, mock_tv_repository, mock_torrent_service): season_request_id = MagicMock() season_request = MagicMock() mock_tv_repository.get_season_request.return_value = season_request result = tv_service.get_season_request_by_id(season_request_id) mock_tv_repository.get_season_request.assert_called_once_with( season_request_id=season_request_id ) assert result == season_request def test_update_season_request(tv_service, mock_tv_repository, mock_torrent_service): season_request = MagicMock() mock_tv_repository.add_season_request.return_value = season_request result = tv_service.update_season_request(season_request) mock_tv_repository.delete_season_request.assert_called_once_with( season_request_id=season_request.id ) mock_tv_repository.add_season_request.assert_called_once_with( season_request=season_request ) assert result == season_request def test_delete_season_request(tv_service, mock_tv_repository, mock_torrent_service): season_request_id = MagicMock() tv_service.delete_season_request(season_request_id) mock_tv_repository.delete_season_request.assert_called_once_with( season_request_id=season_request_id ) def test_get_all_shows(tv_service, mock_tv_repository, mock_torrent_service): shows = [MagicMock(), MagicMock()] mock_tv_repository.get_shows.return_value = shows result = tv_service.get_all_shows() mock_tv_repository.get_shows.assert_called_once() assert result == shows def test_get_show_by_id(tv_service, mock_tv_repository, mock_torrent_service): show_id = MagicMock() show = MagicMock() mock_tv_repository.get_show_by_id.return_value = show result = tv_service.get_show_by_id(show_id) mock_tv_repository.get_show_by_id.assert_called_once_with(show_id=show_id) assert result == show def test_get_show_by_id_not_found(tv_service, mock_tv_repository, mock_torrent_service): show_id = ShowId(uuid.uuid4()) mock_tv_repository.get_show_by_id.side_effect = NotFoundError try: tv_service.get_show_by_id(show_id) except NotFoundError: assert True else: assert False def test_get_show_by_external_id(tv_service, mock_tv_repository, mock_torrent_service): external_id = 123 metadata_provider = "tmdb" show = MagicMock() mock_tv_repository.get_show_by_external_id.return_value = show result = tv_service.get_show_by_external_id(external_id, metadata_provider) mock_tv_repository.get_show_by_external_id.assert_called_once_with( external_id=external_id, metadata_provider=metadata_provider ) assert result == show def test_get_show_by_external_id_not_found( tv_service, mock_tv_repository, mock_torrent_service ): external_id = 123 metadata_provider = "tmdb" mock_tv_repository.get_show_by_external_id.side_effect = NotFoundError try: tv_service.get_show_by_external_id(external_id, metadata_provider) except NotFoundError: assert True else: assert False def test_get_season(tv_service, mock_tv_repository, mock_torrent_service): season_id = MagicMock() season = MagicMock() mock_tv_repository.get_season.return_value = season result = tv_service.get_season(season_id) mock_tv_repository.get_season.assert_called_once_with(season_id=season_id) assert result == season def test_get_season_not_found(tv_service, mock_tv_repository, mock_torrent_service): season_id = SeasonId(uuid.uuid4()) mock_tv_repository.get_season.side_effect = NotFoundError try: tv_service.get_season(season_id) except NotFoundError: assert True else: assert False def test_get_all_season_requests(tv_service, mock_tv_repository, mock_torrent_service): requests = [MagicMock(), MagicMock()] mock_tv_repository.get_season_requests.return_value = requests result = tv_service.get_all_season_requests() mock_tv_repository.get_season_requests.assert_called_once() assert result == requests def test_get_public_season_files_by_season_id_downloaded( monkeypatch, tv_service, mock_tv_repository, mock_torrent_service ): season_id = MagicMock() season_file = MagicMock() public_season_file = MagicMock() public_season_file.downloaded = False mock_tv_repository.get_season_files_by_season_id.return_value = [season_file] monkeypatch.setattr( "media_manager.tv.schemas.PublicSeasonFile.model_validate", lambda x: public_season_file, ) monkeypatch.setattr( tv_service, "season_file_exists_on_file", lambda season_file: True ) result = tv_service.get_public_season_files_by_season_id(season_id) assert result[0].downloaded is True def test_get_public_season_files_by_season_id_not_downloaded( monkeypatch, tv_service, mock_tv_repository, mock_torrent_service ): season_id = MagicMock() season_file = MagicMock() public_season_file = MagicMock() public_season_file.downloaded = False mock_tv_repository.get_season_files_by_season_id.return_value = [season_file] monkeypatch.setattr( "media_manager.tv.schemas.PublicSeasonFile.model_validate", lambda x: public_season_file, ) monkeypatch.setattr( tv_service, "season_file_exists_on_file", lambda season_file: False ) result = tv_service.get_public_season_files_by_season_id(season_id) assert result[0].downloaded is False def test_get_public_season_files_by_season_id_empty( tv_service, mock_tv_repository, mock_torrent_service ): season_id = SeasonId(uuid.uuid4()) mock_tv_repository.get_season_files_by_season_id.return_value = [] result = tv_service.get_public_season_files_by_season_id(season_id) assert result == [] def test_is_season_downloaded_true( monkeypatch, tv_service, mock_tv_repository, mock_torrent_service ): season_id = MagicMock() season_file = MagicMock() mock_tv_repository.get_season_files_by_season_id.return_value = [season_file] monkeypatch.setattr( tv_service, "season_file_exists_on_file", lambda season_file: True ) assert tv_service.is_season_downloaded(season_id) is True def test_is_season_downloaded_false( monkeypatch, tv_service, mock_tv_repository, mock_torrent_service ): season_id = MagicMock() season_file = MagicMock() mock_tv_repository.get_season_files_by_season_id.return_value = [season_file] monkeypatch.setattr( tv_service, "season_file_exists_on_file", lambda season_file: False ) assert tv_service.is_season_downloaded(season_id) is False def test_is_season_downloaded_with_no_files( tv_service, mock_tv_repository, mock_torrent_service ): season_id = SeasonId(uuid.uuid4()) mock_tv_repository.get_season_files_by_season_id.return_value = [] assert tv_service.is_season_downloaded(season_id) is False def test_season_file_exists_on_file_none(monkeypatch, tv_service, mock_torrent_service): season_file = MagicMock() season_file.torrent_id = None assert tv_service.season_file_exists_on_file(season_file) is True def test_season_file_exists_on_file_imported( monkeypatch, tv_service, mock_torrent_service ): season_file = MagicMock() season_file.torrent_id = "torrent_id" torrent_file = MagicMock(imported=True) # Patch the repository method on the torrent_service instance tv_service.torrent_service.torrent_repository.get_torrent_by_id = MagicMock( return_value=torrent_file ) assert tv_service.season_file_exists_on_file(season_file) is True def test_season_file_exists_on_file_not_imported( monkeypatch, tv_service, mock_torrent_service ): season_file = MagicMock() season_file.torrent_id = "torrent_id" torrent_file = MagicMock() torrent_file.torrent_id = "torrent_id" torrent_file.imported = False tv_service.torrent_service.get_torrent_by_id = MagicMock(return_value=torrent_file) assert tv_service.season_file_exists_on_file(season_file) is False def test_season_file_exists_on_file_with_none_imported( monkeypatch, tv_service, mock_torrent_service ): class DummySeasonFile: def __init__(self): self.torrent_id = uuid.uuid4() dummy_file = DummySeasonFile() class DummyTorrent: imported = True tv_service.torrent_service.torrent_repository.get_torrent_by_id = MagicMock( return_value=DummyTorrent() ) assert tv_service.season_file_exists_on_file(dummy_file) is True def test_season_file_exists_on_file_with_none_not_imported( monkeypatch, tv_service, mock_torrent_service ): class DummySeasonFile: def __init__(self): self.torrent_id = uuid.uuid4() dummy_file = DummySeasonFile() class DummyTorrent: imported = False tv_service.torrent_service.get_torrent_by_id = MagicMock( return_value=DummyTorrent() ) assert tv_service.season_file_exists_on_file(dummy_file) is False def test_get_all_available_torrents_for_a_season_with_override( tv_service, mock_tv_repository, mock_torrent_service, mock_indexer_service ): show_id = ShowId(uuid.uuid4()) season_number = 1 override_query = "Custom Query S01" mock_show = Show( id=show_id, name="Test Show", overview="", year=2020, external_id=1, metadata_provider="tmdb", seasons=[], ) mock_tv_repository.get_show_by_id.return_value = mock_show torrent1 = IndexerQueryResult( id=IndexerQueryResultId(uuid.uuid4()), title="Custom Query S01E01", download_url="https://example.com/torrent1", seeders=10, flags=[], size=100, usenet=False, age=1, ) mock_indexer_service.search.return_value = [torrent1] results = tv_service.get_all_available_torrents_for_a_season( season_number=season_number, show_id=show_id, search_query_override=override_query, ) mock_indexer_service.search.assert_called_once_with( query=override_query, is_tv=True ) assert results == [torrent1] def test_get_all_available_torrents_for_a_season_no_results( tv_service, mock_tv_repository, mock_torrent_service, mock_indexer_service ): show_id = ShowId(uuid.uuid4()) season_number = 1 mock_show = Show( id=show_id, name="Test Show", overview="", year=2020, external_id=1, metadata_provider="tmdb", seasons=[], ) mock_tv_repository.get_show_by_id.return_value = mock_show mock_indexer_service.search.return_value = [] results = tv_service.get_all_available_torrents_for_a_season( season_number=season_number, show_id=show_id ) assert results == [] def test_search_for_show_no_existing(tv_service, mock_torrent_service): query = "Test Show" mock_metadata_provider = MagicMock() search_result_item = MetaDataProviderSearchResult( external_id=123, name="Test Show", year=2022, overview="Overview", metadata_provider="tmdb", added=False, poster_path=None, ) mock_metadata_provider.search_show.return_value = [search_result_item] mock_metadata_provider.name = "tmdb" tv_service.check_if_show_exists = MagicMock(return_value=False) results = tv_service.search_for_show( query=query, metadata_provider=mock_metadata_provider ) mock_metadata_provider.search_show.assert_called_once_with(query) assert len(results) == 1 assert results[0] == search_result_item assert results[0].added is False def test_search_for_show_with_existing(tv_service, mock_torrent_service): query = "Test Show" mock_metadata_provider = MagicMock() search_result_item = MetaDataProviderSearchResult( external_id=123, name="Test Show", year=2022, overview="Overview", metadata_provider="tmdb", added=False, poster_path=None, ) mock_metadata_provider.search_show.return_value = [search_result_item] mock_metadata_provider.name = "tmdb" tv_service.check_if_show_exists = MagicMock(return_value=True) results = tv_service.search_for_show( query=query, metadata_provider=mock_metadata_provider ) assert len(results) == 1 assert results[0].added is True def test_search_for_show_empty_results(tv_service, mock_torrent_service): query = "NonExistent Show" mock_metadata_provider = MagicMock() mock_metadata_provider.search_show.return_value = [] tv_service.check_if_show_exists = MagicMock() results = tv_service.search_for_show( query=query, metadata_provider=mock_metadata_provider ) assert results == [] def test_get_popular_shows_none_added(tv_service, mock_torrent_service): mock_metadata_provider = MagicMock() popular_show1 = MetaDataProviderSearchResult( external_id=123, name="Popular Show 1", year=2022, overview="Overview1", metadata_provider="tmdb", added=False, poster_path=None, ) popular_show2 = MetaDataProviderSearchResult( external_id=456, name="Popular Show 2", year=2023, overview="Overview2", metadata_provider="tmdb", added=False, poster_path=None, ) mock_metadata_provider.search_show.return_value = [popular_show1, popular_show2] mock_metadata_provider.name = "tmdb" tv_service.check_if_show_exists = MagicMock(return_value=False) results = tv_service.get_popular_shows(metadata_provider=mock_metadata_provider) assert len(results) == 2 assert popular_show1 in results assert popular_show2 in results def test_get_popular_shows_all_added(tv_service, mock_torrent_service): mock_metadata_provider = MagicMock() popular_show1 = MetaDataProviderSearchResult( external_id=123, name="Popular Show 1", year=2022, overview="Overview1", metadata_provider="tmdb", added=False, poster_path=None, ) mock_metadata_provider.search_show.return_value = [popular_show1] mock_metadata_provider.name = "tmdb" tv_service.check_if_show_exists = MagicMock(return_value=True) results = tv_service.get_popular_shows(metadata_provider=mock_metadata_provider) assert results == [] def test_get_popular_shows_empty_from_provider(tv_service, mock_torrent_service): mock_metadata_provider = MagicMock() mock_metadata_provider.search_show.return_value = [] tv_service.check_if_show_exists = MagicMock() results = tv_service.get_popular_shows(metadata_provider=mock_metadata_provider) assert results == []