Files
unshackle/tests/core/test_latest_episodes.py
T
imSp4rky 37e2b59bce feat(dl): add --latest-episodes N to download the N newest episodes
Split episodes count once. Exposed as latest_episodes on the REST API. Closes #159.
2026-09-28 09:01:40 -06:00

62 lines
2.1 KiB
Python

"""Selection for --latest-episode / --latest-episodes and its REST API validation."""
from __future__ import annotations
from typing import Optional
import pytest
from unshackle.commands.dl import latest_episode_keys
from unshackle.core.api.handlers import validate_download_parameters
from unshackle.core.titles import Movie, Movies, Series
from unshackle.core.titles.episode import Episode
class Svc:
pass
def episode(season: int, number: int, part: Optional[int] = None) -> Episode:
return Episode(id_=f"ep-{season}x{number}.{part}", service=Svc, title="T", season=season, number=number, part=part)
def series() -> Series:
# out of order on purpose: the Series sorts itself
return Series(episode(s, n) for s, n in [(2, 1), (1, 1), (2, 3), (1, 2), (2, 2)])
@pytest.mark.parametrize(
("latest_episode", "latest_episodes", "expected"),
[
(False, None, []),
(True, None, [(2, 3)]),
(False, 3, [(2, 1), (2, 2), (2, 3)]),
(True, 2, [(2, 2), (2, 3)]),
(False, 99, [(1, 1), (1, 2), (2, 1), (2, 2), (2, 3)]),
],
)
def test_the_newest_episodes_are_picked_across_seasons(
latest_episode: bool, latest_episodes: Optional[int], expected: list[tuple[int, int]]
) -> None:
assert latest_episode_keys(series(), latest_episode, latest_episodes) == expected
def test_a_split_episode_takes_one_slot() -> None:
titles = Series([episode(1, 4), episode(1, 5, part=1), episode(1, 5, part=2)])
assert latest_episode_keys(titles, False, 2) == [(1, 4), (1, 5)]
assert latest_episode_keys(titles, True, None) == [(1, 5)]
def test_titles_that_are_not_a_series_are_left_alone() -> None:
movies = Movies([Movie(id_="movie-1", service=Svc, name="M")])
assert latest_episode_keys(movies, True, 3) == []
@pytest.mark.parametrize("value", [0, -1, True, "3", 1.5])
def test_a_non_positive_or_non_integer_count_is_refused(value: object) -> None:
assert validate_download_parameters({"latest_episodes": value}) == "latest_episodes must be a positive integer"
def test_a_positive_count_is_accepted() -> None:
assert validate_download_parameters({"latest_episodes": 3}) is None