mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-21 12:21:49 +00:00
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>
77 lines
3.6 KiB
JavaScript
77 lines
3.6 KiB
JavaScript
// Pins the practice-aware library home in static/v3/songs.js:
|
|
// - a "Repertoire" progress meter (mastered / total library songs), and
|
|
// - a "Keep practicing" shelf (recently played, not yet mastered).
|
|
// Both reuse existing data (/api/stats/best already in state.accuracy, and
|
|
// /api/stats/recent) and are shown only on the unfiltered grid front door.
|
|
//
|
|
// Source-level only — same strategy as tests/js/v3_az_rail.test.js.
|
|
|
|
const { test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const SONGS_JS = path.join(__dirname, '..', '..', 'static', 'v3', 'songs.js');
|
|
const src = fs.readFileSync(SONGS_JS, 'utf8');
|
|
|
|
test('repertoire uses the same mastery threshold as the green accuracy badge', () => {
|
|
assert.match(src, /const\s+MASTERY_ACCURACY\s*=\s*0\.9/);
|
|
assert.match(
|
|
src,
|
|
/function\s+_repertoireCounts[\s\S]*?v\s*>=\s*MASTERY_ACCURACY\s*\)\s*mastered\+\+;\s*else\s+learning\+\+/,
|
|
'repertoire counts must bucket scored songs into mastered/learning at MASTERY_ACCURACY',
|
|
);
|
|
});
|
|
|
|
test('the home is the unfiltered grid front door, local provider only', () => {
|
|
assert.match(
|
|
src,
|
|
/function\s+libHomeVisible[\s\S]*?state\.view === 'grid'[\s\S]*?state\.provider === 'local'[\s\S]*?!state\.selectMode[\s\S]*?!state\.q[\s\S]*?activeFilterCount\(\)\s*===\s*0/,
|
|
'libHomeVisible must require grid view, the local provider, no select mode, no search, no active filters',
|
|
);
|
|
});
|
|
|
|
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,
|
|
/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',
|
|
);
|
|
});
|
|
|
|
test('the meter + shelf fetch together and a stale render is discarded', () => {
|
|
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');
|
|
});
|
|
|
|
test('the repertoire denominator is the unfiltered library total', () => {
|
|
assert.match(src, /\/api\/library\/stats\?provider='/);
|
|
assert.match(src, /total_songs\s*\?\?\s*stats\.total/);
|
|
assert.match(src, /Math\.round\(\(mastered\s*\/\s*total\)\s*\*\s*100\)/);
|
|
});
|
|
|
|
test('the home + #v3-lib-home host are wired into render and reload', () => {
|
|
assert.match(src, /id="v3-lib-home"/, 'render() must include the #v3-lib-home host');
|
|
assert.match(src, /function reload\s*\([\s\S]*?updateLibraryHome\(\)/,
|
|
'reload() must refresh/toggle the home');
|
|
assert.match(src, /function applyScoreRefresh[\s\S]*?renderLibraryHome\(\)/,
|
|
'a new score must refresh the meter + shelf');
|
|
});
|
|
|
|
test('shelf cards play the song on click', () => {
|
|
assert.match(
|
|
src,
|
|
/querySelectorAll\('\.v3-kp-card'\)[\s\S]*?window\.playSong\(enc\(fn\)/,
|
|
'a shelf card click must call window.playSong with the recents filename',
|
|
);
|
|
});
|