fix(tests): re-green the JS suite — 18 stale source-shape tests + 1 real seek-reason violation (#740)

main's JS suite has been red since the recent v3-library and player
refactors landed. 17 of 18 failures were test harnesses/regexes that
went stale behind real, intentional code changes; one was a genuine
contract violation in the code.

Code fix:
- session-resume seek passed 'resume' as its _audioSeek reason; the
  documented contract (enforced by song_seek.test.js) requires
  multi-word kebab-case. Renamed to 'session-resume' — no consumer
  string-matches specific reasons, so this is rename-safe.

Test updates (each pins the CURRENT contract):
- highway_colors_facade: inject HWC_PRESETS + applyHighwayStringPreset
  (new preset feature); lock presets/applyPreset into the surface test
- loop_api: stub _updateEditRegionBtn (new edit-region UI hook)
- song_close: sandbox gets window.feedBack.playQueue; assert a real
  close abandons the queue (the new queue-aware behavior)
- v3_keep_practicing: the shelf moved from client-side /api/stats/recent
  dedupe+gating to the server-side practice-suggestions recommender —
  tests now pin that (fetch, arrangement-aware card click, Promise.all)
- v3_songs_tuning: card row variable renamed song → shown (grouped cards)
- live_guitar_tone_source: accept literal ’ where ’ drifted in copy
- legacy_shim_hits: normalize CRLF before fixed-width region() slicing
  (Windows-only failure; char windows shrank by one char per line)

Suite: 987/987 locally (Windows), previously 968/987 (and 18 red on CI).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
OmikronApex
2026-07-03 14:35:07 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent b6442dda75
commit d2b2a7e9f7
8 changed files with 40 additions and 18 deletions
+11 -9
View File
@@ -31,21 +31,23 @@ test('the home is the unfiltered grid front door, local provider only', () => {
);
});
test('the shelf is recently-played, not-yet-mastered songs (per-song, deduped)', () => {
assert.match(src, /\/api\/stats\/recent\?limit=/);
// Mastery is gated on the per-SONG best (state.accuracy, what the badge
// shows), not the per-arrangement recents row, and each filename appears
// once — so no green-badged "keep practicing" card and no duplicates.
test('the shelf is the server-side practice-suggestions recommender', () => {
// The old client-side pipeline (fetch /api/stats/recent, dedupe by
// filename, gate on state.accuracy) moved server-side: the growth-edge
// recommender gates (not-mastered) + aggregates per song and picks the
// arrangement closest to mastery. The client renders its rows as-is.
assert.match(src, /\/api\/library\/practice-suggestions\?limit=/);
// A shelf card click opens the row's recommended arrangement, not the
// song's default.
assert.match(
src,
/const\s+best\s*=\s*acc\[r\.filename\][\s\S]*?best\s*>=\s*MASTERY_ACCURACY/,
'the shelf must gate on the per-song best (state.accuracy) at MASTERY_ACCURACY',
/data-arr="[\s\S]*?getAttribute\('data-arr'\)[\s\S]*?playSong\(enc\(fn\), arr === '' \? undefined : Number\(arr\)\)/,
'shelf cards must pass the recommended arrangement to playSong',
);
assert.match(src, /seen\.has\(r\.filename\)/, 'the shelf must dedupe recents by filename');
});
test('the meter + shelf fetch together and a stale render is discarded', () => {
assert.match(src, /Promise\.all\(\[[\s\S]*?library\/stats[\s\S]*?stats\/recent/,
assert.match(src, /Promise\.all\(\[[\s\S]*?library\/stats[\s\S]*?practice-suggestions/,
'the two reads must be issued together (Promise.all), not sequentially');
assert.match(src, /_homeToken[\s\S]*?_homeToken !== myToken/,
'a stale render must be superseded by a newer one via a token');