test: add real-world release fixtures (EASY bucket)
Captures 5 canonical releases from /mnt/testipool/downloads as parametrized fixtures under tests/fixtures/releases/easy/. Each fixture declares the release name, expected ParsedRelease fields, original tree, and the future routing (library / torrents / seed_hardlinks) for the upcoming organize_media refactor. Today only the 'parsed' section is asserted; tree is materialized into a tmp_path to catch typos. Routing is captured ahead of the planner work — it becomes verifiable once organize_media lands. Cases: back_in_action (movie), slow_horses_single_ep (TV single), foundation_season_pack (S02 + .nfo noise), long_walk_with_noise (movie + KONTRAST.TOP.txt), sinners_yts (YTS bracket-heavy + Subs/ dir). Also tracks CHANGELOG.md under [Unreleased] / Added.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
"""Real-world release fixtures — anti-regression baseline for parse_release.
|
||||
|
||||
Each fixture under ``tests/fixtures/releases/<bucket>/<case>/expected.yaml``
|
||||
declares a release name and the ``ParsedRelease`` fields it should produce.
|
||||
Fields absent from the fixture's ``parsed`` block are not checked, so adding
|
||||
new attributes to ``ParsedRelease`` never breaks existing fixtures.
|
||||
|
||||
The fixture's ``tree`` is materialized into a temp dir to prove the layout is
|
||||
self-consistent, even though no filesystem assertions are made yet. The
|
||||
``routing`` block (library / torrents / seed_hardlinks) is captured ahead of
|
||||
the ``organize_media`` refactor — it will become verifiable once the planner
|
||||
exists.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict
|
||||
|
||||
import pytest
|
||||
|
||||
from alfred.domain.release.services import parse_release
|
||||
from tests.fixtures.releases.conftest import ReleaseFixture, discover_fixtures
|
||||
|
||||
FIXTURES = discover_fixtures()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fixture",
|
||||
FIXTURES,
|
||||
ids=[f.name for f in FIXTURES],
|
||||
)
|
||||
def test_parse_matches_fixture(fixture: ReleaseFixture, tmp_path) -> None:
|
||||
# Materialize the tree to assert it is at least well-formed YAML +
|
||||
# plausible filesystem paths. Catches typos / missing leading dirs early.
|
||||
fixture.materialize(tmp_path)
|
||||
|
||||
result = asdict(parse_release(fixture.release_name))
|
||||
# ``is_season_pack`` is a @property — asdict() does not include it.
|
||||
result["is_season_pack"] = parse_release(fixture.release_name).is_season_pack
|
||||
|
||||
for field, expected in fixture.expected_parsed.items():
|
||||
assert field in result, (
|
||||
f"{fixture.name}: unknown field '{field}' in expected.parsed"
|
||||
)
|
||||
assert result[field] == expected, (
|
||||
f"{fixture.name}: parsed.{field} — "
|
||||
f"expected {expected!r}, got {result[field]!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_at_least_one_fixture_per_bucket() -> None:
|
||||
"""Each bucket should hold at least one case once populated."""
|
||||
buckets = {f.name.split("/")[0] for f in FIXTURES}
|
||||
assert "easy" in buckets, "EASY bucket must have at least one fixture"
|
||||
Reference in New Issue
Block a user