Files
2026-08-28 01:01:12 +02:00

76 lines
2.4 KiB
Python

import json
import pytest
from h3_guidemaster.core.state import default_timeline_state, parse_timeline_state
def test_default_state_is_current_h3_24fps_and_empty():
state = default_timeline_state()
assert state.version == 2
assert state.fps == 24
assert state.guides == ()
assert not hasattr(state, "mask")
def test_parse_v2_timeline_normalizes_guides():
raw = json.dumps({
"version": 2,
"fps": 24,
"timeline": {"frame_count": 124, "selected_frame": 17},
"guides": [
{"id": "g1", "enabled": True, "frame": -1, "image_slot": 2, "audio_slot": None}
],
})
state = parse_timeline_state(raw)
assert state.version == 2
assert state.guides[0].frame == -1
assert state.guides[0].image_slot == 2
assert not hasattr(state.guides[0], "intent")
def test_parse_v1_migrates_and_drops_legacy_guide_intent():
state = parse_timeline_state(json.dumps({
"version": 1,
"fps": 24,
"reference": {"selected_frame": 88},
"guides": [{"id": "old", "frame": 24, "image_slot": 0, "intent": "legacy beat"}],
}))
assert state.version == 2
assert state.guides[0].id == "old"
assert state.guides[0].frame == 24
assert not hasattr(state.guides[0], "intent")
def test_parse_timeline_accepts_zero_based_autogrow_slots():
state = parse_timeline_state(json.dumps({
"version": 2,
"fps": 24,
"guides": [{"frame": 0, "image_slot": 0, "audio_slot": None}],
}))
assert state.guides[0].image_slot == 0
def test_rejects_unknown_state_version():
with pytest.raises(ValueError, match="timeline version"):
parse_timeline_state('{"version": 99, "fps": 24}')
def test_rejects_non_h3_fps():
with pytest.raises(ValueError, match="24 fps"):
parse_timeline_state('{"version": 2, "fps": 30}')
@pytest.mark.parametrize("payload", [
'{"version": 2.5, "fps": 24}',
'{"version": 2, "fps": 24, "guides": [{"frame": 1.5}]}',
'{"version": 2, "fps": 24, "guides": [{"frame": 1, "image_slot": 0.5}]}',
])
def test_rejects_non_integer_timeline_values(payload):
with pytest.raises(ValueError, match="integer"):
parse_timeline_state(payload)
def test_rejects_string_boolean_values():
with pytest.raises(ValueError, match="enabled"):
parse_timeline_state('{"version": 2, "fps": 24, "guides": [{"enabled": "false"}]}')