"""Tests for TV Show domain — entities and value objects.""" import pytest from alfred.domain.shared.exceptions import ValidationError from alfred.domain.tv_shows.entities import Episode, Season, TVShow from alfred.domain.tv_shows.value_objects import EpisodeNumber, SeasonNumber, ShowStatus # --------------------------------------------------------------------------- # ShowStatus # --------------------------------------------------------------------------- class TestShowStatus: def test_from_string_ongoing(self): assert ShowStatus.from_string("ongoing") == ShowStatus.ONGOING def test_from_string_ended(self): assert ShowStatus.from_string("ended") == ShowStatus.ENDED def test_from_string_case_insensitive(self): assert ShowStatus.from_string("ONGOING") == ShowStatus.ONGOING assert ShowStatus.from_string("Ended") == ShowStatus.ENDED def test_from_string_unknown(self): assert ShowStatus.from_string("cancelled") == ShowStatus.UNKNOWN assert ShowStatus.from_string("") == ShowStatus.UNKNOWN # --------------------------------------------------------------------------- # SeasonNumber # --------------------------------------------------------------------------- class TestSeasonNumber: def test_valid_season(self): s = SeasonNumber(1) assert s.value == 1 def test_season_zero_is_specials(self): s = SeasonNumber(0) assert s.is_special() def test_normal_season_not_special(self): assert not SeasonNumber(3).is_special() def test_negative_raises(self): with pytest.raises(ValidationError): SeasonNumber(-1) def test_too_high_raises(self): with pytest.raises(ValidationError): SeasonNumber(101) def test_non_integer_raises(self): with pytest.raises((ValidationError, TypeError)): SeasonNumber("1") # type: ignore def test_str_and_int(self): s = SeasonNumber(5) assert str(s) == "5" assert int(s) == 5 # --------------------------------------------------------------------------- # EpisodeNumber # --------------------------------------------------------------------------- class TestEpisodeNumber: def test_valid_episode(self): e = EpisodeNumber(1) assert e.value == 1 def test_zero_raises(self): with pytest.raises(ValidationError): EpisodeNumber(0) def test_negative_raises(self): with pytest.raises(ValidationError): EpisodeNumber(-5) def test_too_high_raises(self): with pytest.raises(ValidationError): EpisodeNumber(1001) def test_str_and_int(self): e = EpisodeNumber(12) assert str(e) == "12" assert int(e) == 12 # --------------------------------------------------------------------------- # TVShow entity # --------------------------------------------------------------------------- class TestTVShow: def _make(self, imdb_id="tt0903747", title="Breaking Bad", seasons=5, status="ended"): return TVShow(imdb_id=imdb_id, title=title, seasons_count=seasons, status=status) def test_basic_creation(self): show = self._make() assert show.title == "Breaking Bad" assert show.seasons_count == 5 def test_coerces_string_imdb_id(self): show = self._make() from alfred.domain.shared.value_objects import ImdbId assert isinstance(show.imdb_id, ImdbId) def test_coerces_string_status(self): show = self._make(status="ongoing") assert show.status == ShowStatus.ONGOING def test_is_ongoing(self): show = self._make(status="ongoing") assert show.is_ongoing() assert not show.is_ended() def test_is_ended(self): show = self._make(status="ended") assert show.is_ended() assert not show.is_ongoing() def test_negative_seasons_raises(self): with pytest.raises(ValueError): TVShow(imdb_id="tt0903747", title="X", seasons_count=-1, status="ended") def test_invalid_imdb_id_type_raises(self): with pytest.raises(ValueError): TVShow(imdb_id=12345, title="X", seasons_count=1, status="ended") # type: ignore def test_get_folder_name_replaces_spaces(self): show = self._make(title="Breaking Bad") assert show.get_folder_name() == "Breaking.Bad" def test_get_folder_name_strips_special_chars(self): show = self._make(title="It's Always Sunny") name = show.get_folder_name() assert "'" not in name def test_str_repr(self): show = self._make() assert "Breaking Bad" in str(show) assert "tt0903747" in repr(show) # --------------------------------------------------------------------------- # Season entity # --------------------------------------------------------------------------- class TestSeason: def test_basic_creation(self): s = Season(show_imdb_id="tt0903747", season_number=1, episode_count=7) assert s.episode_count == 7 def test_get_folder_name_normal(self): s = Season(show_imdb_id="tt0903747", season_number=2, episode_count=13) assert s.get_folder_name() == "Season 02" def test_get_folder_name_specials(self): s = Season(show_imdb_id="tt0903747", season_number=0, episode_count=3) assert s.get_folder_name() == "Specials" assert s.is_special() def test_negative_episode_count_raises(self): with pytest.raises(ValueError): Season(show_imdb_id="tt0903747", season_number=1, episode_count=-1) def test_str(self): s = Season(show_imdb_id="tt0903747", season_number=1, episode_count=7, name="Pilot Season") assert "Pilot Season" in str(s) # --------------------------------------------------------------------------- # Episode entity # --------------------------------------------------------------------------- class TestEpisode: def test_basic_creation(self): e = Episode( show_imdb_id="tt0903747", season_number=1, episode_number=1, title="Pilot", ) assert e.title == "Pilot" def test_get_filename_format(self): e = Episode( show_imdb_id="tt0903747", season_number=1, episode_number=5, title="Gray Matter", ) filename = e.get_filename() assert filename.startswith("S01E05") assert "Gray.Matter" in filename def test_has_file_false_when_no_path(self): e = Episode( show_imdb_id="tt0903747", season_number=1, episode_number=1, title="Pilot", ) assert not e.has_file() assert not e.is_downloaded() def test_str_format(self): e = Episode( show_imdb_id="tt0903747", season_number=2, episode_number=3, title="Bit by a Dead Bee", ) s = str(e) assert "S02E03" in s assert "Bit by a Dead Bee" in s