"""Real-world release fixtures — anti-regression baseline for parse_release. Each fixture under ``tests/fixtures/releases///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"