Files
led-controller/tests/test_sequence_step_beats.py
Jimmy b87382d2be feat(espnow): broadcast delivery with group-filtered routing
Send presets and select on broadcast with groups; unicast only for
per-device settings. V1 select as [preset_id, step?]. Sequence steps
use beat counts; manual presets get select each beat, auto only on
step change. Bridge downlink router, Pi envelope delivery, and tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 01:44:28 +12:00

52 lines
1.5 KiB
Python

"""Sequence step ``beats`` hold (e.g. 12 beats on preset 42, then 4 on preset 5)."""
import asyncio
import os
import sys
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SRC_PATH = os.path.join(PROJECT_ROOT, "src")
if SRC_PATH not in sys.path:
sys.path.insert(0, SRC_PATH)
from util import sequence_playback as sp # noqa: E402
def test_step_holds_beats_before_lane_send(monkeypatch):
sent = []
async def fake_send_lane(i, st, ctx):
sent.append((int(st.get("stepIdx", 0)), int(st.get("beatCount", 0))))
monkeypatch.setattr(sp, "_send_lane", fake_send_lane)
async def noop_stop(**_kwargs):
with sp._beat_run_lock:
sp._beat_run = None
monkeypatch.setattr(sp, "stop_playback", noop_stop)
ctx = {
"num_lanes": 1,
"loop": False,
"lanes": [[{"preset_id": "42", "beats": 12}, {"preset_id": "5", "beats": 4}]],
"lane_states": [{"stepIdx": 0, "beatCount": 0, "done": False}],
"sequence_loop_beat": 0,
}
with sp._beat_run_lock:
sp._beat_run = ctx
async def run():
for _ in range(11):
await sp.process_active_beat_advance()
await sp.process_active_beat_advance()
for _ in range(3):
await sp.process_active_beat_advance()
await sp.process_active_beat_advance()
asyncio.run(run())
assert sent == [(1, 0)]
assert ctx["lane_states"][0]["done"] is True
with sp._beat_run_lock:
sp._beat_run = None