"""Unit-Tests Medienbibliothek (PLAN.md §13.2, §13.3).""" from __future__ import annotations from pathlib import Path import pytest from hms_media import ImportStatus, MediaLibrary @pytest.fixture() def media_root(tmp_path: Path) -> Path: root = tmp_path / "media" (root / "clips").mkdir(parents=True) (root / "clips" / "intro.mp4").write_bytes(b"video-bytes-1" * 20) (root / "clips" / "loop.mp4").write_bytes(b"video-bytes-2" * 20) return root def test_import_creates_asset_with_hash(media_root: Path) -> None: lib = MediaLibrary(media_root) outcome = lib.import_file(media_root / "clips" / "intro.mp4") assert outcome.status is ImportStatus.IMPORTED assert outcome.asset is not None assert outcome.asset.content_hash # §13.2: Hash vorhanden assert outcome.asset.rel_path == "clips/intro.mp4" assert len(lib) == 1 def test_duplicate_content_detected(media_root: Path) -> None: """Gleicher Inhalt unter anderem Namen = Duplikat (§13.3).""" lib = MediaLibrary(media_root) first = lib.import_file(media_root / "clips" / "intro.mp4") copy = media_root / "clips" / "kopie.mp4" copy.write_bytes((media_root / "clips" / "intro.mp4").read_bytes()) outcome = lib.import_file(copy) assert outcome.status is ImportStatus.DUPLICATE assert outcome.duplicate_of == first.asset.id # verweist auf das Original assert len(lib) == 1 # kein zweiter Eintrag def test_import_missing_file_reports_cleanly(media_root: Path) -> None: lib = MediaLibrary(media_root) outcome = lib.import_file(media_root / "clips" / "fehlt.mp4") assert outcome.status is ImportStatus.MISSING_FILE assert outcome.asset is None def test_bank_slots_are_explicit_metadata(media_root: Path) -> None: """Bank/Index als Show-Metadaten, unabhängig vom Dateinamen (§13.2).""" lib = MediaLibrary(media_root) asset = lib.import_file(media_root / "clips" / "intro.mp4").asset lib.register_bank_slot(asset.id, bank=1, index=5) found = lib.asset_at(bank=1, index=5) assert found is not None and found.id == asset.id assert lib.asset_at(bank=1, index=6) is None with pytest.raises(KeyError): lib.register_bank_slot("unbekannt", 1, 1) def test_missing_detection_and_relink(media_root: Path) -> None: """Fehlende Dateien werden markiert; Relink bindet neu (§13.3).""" lib = MediaLibrary(media_root) asset = lib.import_file(media_root / "clips" / "loop.mp4").asset (media_root / "clips" / "loop.mp4").unlink() # Datei verschwindet assert lib.mark_missing() == [asset.id] assert asset.id in lib.missing_asset_ids # Relink auf eine neue Datei mit gleichem Namen (media_root / "clips" / "loop.mp4").write_bytes(b"neuer-inhalt") updated = lib.relink(asset.id, media_root / "clips" / "loop.mp4") assert updated.content_hash != asset.content_hash # neuer Inhalt → neuer Hash assert asset.id not in lib.missing_asset_ids def test_relink_rejects_missing_target(media_root: Path) -> None: lib = MediaLibrary(media_root) asset = lib.import_file(media_root / "clips" / "loop.mp4").asset with pytest.raises(FileNotFoundError): lib.relink(asset.id, media_root / "nirgendwo.mp4") def test_library_all_and_get(media_root: Path) -> None: lib = MediaLibrary(media_root) a = lib.import_file(media_root / "clips" / "intro.mp4").asset b = lib.import_file(media_root / "clips" / "loop.mp4").asset assert {x.id for x in lib.all()} == {a.id, b.id} assert lib.get(a.id).rel_path == "clips/intro.mp4" assert lib.get("gibts-nicht") is None