Files
alfred/tests/infrastructure/persistence/dot_alfred/v2/conftest.py
T
2026-05-26 21:45:11 +02:00

202 lines
6.6 KiB
Python

"""Shared fixtures for v2 ``.alfred`` integration tests.
The fixtures here build realistic ``SeriesRelease`` / ``MovieRelease``
aggregates — populated tracks, multi-episode files, both PACK and
EPISODIC modes — so every test starts from a known-rich state.
The point is to make round-trip tests genuinely lossless-checking
(if a field is unused in the fixture, the round-trip can't prove
much about it).
"""
from __future__ import annotations
from datetime import UTC, datetime
import pytest
from alfred.domain.releases_TO_CHECK.entities import (
EpisodeRelease,
MovieRelease,
SeasonRelease,
SeriesRelease,
TrackProfile,
)
from alfred.domain.releases_TO_CHECK.value_objects import EpisodeRange, ReleaseMode
from alfred.domain.shared_TO_CHECK.media import AudioTrack, SubtitleTrack
from alfred.domain.shared_TO_CHECK.value_objects import FilePath, ImdbId, TmdbId
from alfred.domain.tv_shows.value_objects import EpisodeNumber, SeasonNumber, ShowStatus
from alfred.infrastructure.api_TO_CHECK.tmdb.dto import TmdbSeasonInfo, TmdbShowInfo
def _audio(lang: str = "eng", *, index: int = 0) -> AudioTrack:
# ``index`` defaults to 0 to match what the bridge reconstructs on
# read (sidecars don't persist ffprobe stream indices — see the
# bridge module's track-conversion notes). Pass explicit indices
# only when a fixture has multiple tracks of the same kind.
return AudioTrack(
index=index,
codec="eac3",
channels=6,
channel_layout="5.1",
language=lang,
)
def _sub(
lang: str = "eng",
*,
index: int = 0,
forced: bool = False,
sdh: bool = False,
) -> SubtitleTrack:
return SubtitleTrack(
index=index,
codec="subrip",
language=lang,
is_default=False,
is_forced=forced,
is_sdh=sdh,
)
@pytest.fixture
def foundation_release() -> SeriesRelease:
"""Foundation S01 (PACK, 3 files) + S02 (EPISODIC, one multi-episode file)."""
s01 = SeasonRelease(
season_number=SeasonNumber(1),
folder="Foundation.S01.1080p.WEBRip.x265-RARBG",
mode=ReleaseMode.PACK,
episodes=(
EpisodeRelease(
episodes=EpisodeRange(EpisodeNumber(1), EpisodeNumber(1)),
file_path=FilePath(
"Foundation.S01.1080p.WEBRip.x265-RARBG/"
"Foundation.S01E01.1080p.WEBRip.x265-RARBG.mkv"
),
tracks=TrackProfile(
audio_tracks=(_audio("eng"),),
subtitle_tracks=(
_sub("eng", index=0),
_sub("eng", index=1, sdh=True),
),
),
),
EpisodeRelease(
episodes=EpisodeRange(EpisodeNumber(2), EpisodeNumber(2)),
file_path=FilePath(
"Foundation.S01.1080p.WEBRip.x265-RARBG/"
"Foundation.S01E02.1080p.WEBRip.x265-RARBG.mkv"
),
tracks=TrackProfile(audio_tracks=(_audio("eng"),)),
),
EpisodeRelease(
episodes=EpisodeRange(EpisodeNumber(3), EpisodeNumber(3)),
file_path=FilePath(
"Foundation.S01.1080p.WEBRip.x265-RARBG/"
"Foundation.S01E03.1080p.WEBRip.x265-RARBG.mkv"
),
tracks=TrackProfile(audio_tracks=(_audio("eng"),)),
),
),
)
s02 = SeasonRelease(
season_number=SeasonNumber(2),
folder="Foundation.S02",
mode=ReleaseMode.EPISODIC,
episodes=(
EpisodeRelease(
episodes=EpisodeRange(EpisodeNumber(1), EpisodeNumber(1)),
file_path=FilePath(
"Foundation.S02/Foundation.S02E01.1080p.x265-ELiTE/"
"Foundation.S02E01.1080p.x265-ELiTE.mkv"
),
tracks=TrackProfile(audio_tracks=(_audio("eng"),)),
),
# Multi-episode file (E02 + E03 in one .mkv).
EpisodeRelease(
episodes=EpisodeRange(EpisodeNumber(2), EpisodeNumber(3)),
file_path=FilePath(
"Foundation.S02/Foundation.S02E02-E03.2160p.WEB.x265-CtrlHD/"
"Foundation.S02E02-E03.2160p.WEB.x265-CtrlHD.mkv"
),
tracks=TrackProfile(
audio_tracks=(_audio("eng"),),
subtitle_tracks=(_sub("eng", forced=True),),
),
),
),
)
return SeriesRelease(
tmdb_id=TmdbId(84958),
imdb_id=ImdbId("tt0804484"),
seasons=(s01, s02),
)
@pytest.fixture
def inception_release() -> MovieRelease:
"""Inception (2010) — single-file movie with rich tracks."""
return MovieRelease(
tmdb_id=TmdbId(27205),
imdb_id=ImdbId("tt1375666"),
folder="Inception.2010.1080p.BluRay.x264-GROUP",
file_path=FilePath("Inception.2010.1080p.BluRay.x264-GROUP.mkv"),
added_at=datetime(2026, 5, 25, 8, 30, 0, tzinfo=UTC),
tracks=TrackProfile(
audio_tracks=(
AudioTrack(
index=0,
codec="dts",
channels=8,
channel_layout="7.1",
language="eng",
),
),
subtitle_tracks=(
_sub("eng", index=0),
_sub("fre", index=1, forced=True),
),
),
)
@pytest.fixture
def foundation_tmdb_info() -> TmdbShowInfo:
"""Foundation TMDB cache snapshot — 3 seasons, S03 not yet aired."""
return TmdbShowInfo(
tmdb_id=TmdbId(84958),
imdb_id=ImdbId("tt0804484"),
name="Foundation",
status=ShowStatus.RETURNING_SERIES,
seasons=(
TmdbSeasonInfo(number=1, episode_count=10, aired=True),
TmdbSeasonInfo(number=2, episode_count=10, aired=True),
TmdbSeasonInfo(number=3, episode_count=10, aired=False),
),
)
@pytest.fixture
def now_utc() -> datetime:
"""Stable UTC reference for deterministic fetched_at fields."""
return datetime(2026, 5, 25, 8, 30, 0, tzinfo=UTC)
@pytest.fixture
def tv_library(tmp_path):
"""Empty ``tv_shows/`` directory pre-populated with show folders."""
root = tmp_path / "tv_shows"
root.mkdir()
(root / "Foundation").mkdir()
(root / "Fallout").mkdir()
return root
@pytest.fixture
def movie_library(tmp_path):
"""Empty ``movies/`` directory pre-populated with one movie folder."""
root = tmp_path / "movies"
root.mkdir()
(root / "Inception.2010.1080p.BluRay.x264-GROUP").mkdir()
return root