"""Unit-Tests Fixture-Generator (PLAN.md §16.3, §16.4).""" from __future__ import annotations import csv from pathlib import Path from fixture_generator import LAYER64, MASTER32, write_csv def test_master32_has_exactly_32_contiguous_channels() -> None: assert len(MASTER32) == 32 assert [row[0] for row in MASTER32] == list(range(1, 33)) def test_layer64_has_exactly_64_contiguous_channels() -> None: assert len(LAYER64) == 64 assert [row[0] for row in LAYER64] == list(range(1, 65)) def test_master32_key_channels_match_plan() -> None: by_channel = {row[0]: row for row in MASTER32} assert "Blackout" in by_channel[3][1] # Kanal 3 Blackout assert "Preset Recall" in by_channel[8][1] # Kanal 8 steigende Flanke assert "Tap Tempo" in by_channel[16][1] # Kanal 16 Tap def test_layer64_key_channels_match_plan() -> None: by_channel = {row[0]: row for row in LAYER64} assert "Layer Enable" in by_channel[1][1] assert "Opacity" in by_channel[2][1] assert "Load/Commit" in by_channel[9][1] assert "Blend Mode" in by_channel[21][1] assert "FX1 Enable" in by_channel[41][1] assert "FX2 Enable" in by_channel[52][1] assert "Retrigger" in by_channel[63][1] def test_layer64_fx_parameter_blocks() -> None: by_channel = {row[0]: row for row in LAYER64} for slot in range(1, 9): assert f"P{slot}" in by_channel[43 + slot][1] assert f"P{slot}" in by_channel[54 + slot][1] def test_eight_layers_fit_exactly_one_universe() -> None: # §16.2: „Acht Layer entsprechen damit exakt einem DMX-Universe“ assert 8 * len(LAYER64) == 512 def test_write_csv_output(tmp_path: Path) -> None: out = tmp_path / "layer64" / "layer64.csv" write_csv(LAYER64, out) with open(out, encoding="utf-8", newline="") as fh: rows = list(csv.reader(fh)) assert rows[0] == ["channel", "parameter", "resolution_behavior"] assert len(rows) == 65 # Header + 64 assert rows[1] == ["1", "Layer Enable", "Schalter"] def test_write_csv_rejects_gaps(tmp_path: Path) -> None: import pytest broken = [(1, "a", "x"), (3, "b", "y")] # Kanal 2 fehlt with pytest.raises(ValueError, match="contiguous"): write_csv(broken, tmp_path / "broken.csv") # ValueError vor dem Schreiben