fix(audio): client soundtrack fallback when /api/ring lacks audio (stale server)

Root cause of 'no sound', found via the live readout: the operator's /api/ring
returned the ring WITHOUT the per-scale audio field (a server process predating the
audio code) → soundtrackUrl() was null → the element never got a src (readyState 0,
no error). The native test player proved the file itself plays. Fix: client falls
back to a scale-id→soundtrack map (mirrors build_pool_manifest.SCALE_AUDIO) so audio
works without a server restart. Verified: stale-ring sim now plays; audio-first-then-
video leaves both on. +2 E2E regression tests (7 total). Chromium + WebKit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BenStullsBets
2026-06-26 13:42:12 -07:00
parent 56e352fe65
commit 97d2ddd573
2 changed files with 37 additions and 2 deletions
+20
View File
@@ -101,6 +101,26 @@ def test_audio_before_video_stays_audio_only(page):
page.wait_for_selector("#black:not(.hidden)") # still blanked
def test_audio_then_video_leaves_both_on(page):
_toggle(page, "audio") # audio first
page.wait_for_function("!document.getElementById('aud').paused")
_toggle(page, "visual") # then video
page.wait_for_selector("#black.hidden", state="attached") # video showing
assert page.is_checked("#audio") is True
assert page.evaluate("!document.getElementById('aud').paused") is True # audio still plays
def test_soundtrack_fallback_when_ring_lacks_audio(page):
# simulate a stale server whose /api/ring omits the per-scale `audio` field;
# the client falls back to the scale-id soundtrack map so audio still plays
page.evaluate("ring.scales.forEach(s => { delete s.audio; })")
_toggle(page, "audio")
page.wait_for_function(
"(() => { const a = document.getElementById('aud');"
" return a.src.includes('/media/audio/cosmos/') && !a.paused; })()"
)
def test_video_off_blanks_after_being_on(page):
_toggle(page, "visual") # on
page.wait_for_selector("#black.hidden", state="attached")