docs: update AGENTS.md and README for new features, add JS tests

Docs:
- AGENTS.md: updated toolchain section with js-lint/js-test tasks,
  expanded web/ui/ directory listing, added event delegation and
  Web Audio API to key patterns, updated testing section
- README: marked issue #9 (Audio Preview Player) as done
- .gitignore: added akai-fetch.test and cover.out

Tests:
- Moved groupWavs and cleanName to util.js (pure functions)
- Added 10 new JS tests: 6 groupWavs, 4 cleanName
- Total JS tests: 29 (up from 19)
This commit is contained in:
2026-06-22 02:46:34 -07:00
parent e0bad5e5ac
commit 7124b16fc1
6 changed files with 118 additions and 33 deletions
+71 -1
View File
@@ -1,6 +1,6 @@
const { describe, it } = require('node:test')
const assert = require('node:assert/strict')
const { esc, sanitize, formatBytes, formatTime } = require('./util.js')
const { esc, sanitize, formatBytes, formatTime, groupWavs, cleanName } = require('./util.js')
describe('esc', () => {
it('escapes HTML entities', () => {
@@ -88,4 +88,74 @@ describe('formatTime', () => {
it('formats large times', () => {
assert.strictEqual(formatTime(3661), '61:01')
})
})
describe('groupWavs', () => {
it('groups by library and program', () => {
const paths = [
'LibA/Prog1/kick.wav',
'LibA/Prog1/snare.wav',
'LibA/Prog2/hat.wav'
]
const result = groupWavs(paths)
assert.strictEqual(Object.keys(result).length, 1)
assert.strictEqual(Object.keys(result.LibA).length, 2)
assert.strictEqual(result.LibA.Prog1.length, 2)
assert.strictEqual(result.LibA.Prog2.length, 1)
})
it('handles multiple libraries', () => {
const paths = [
'LibA/kick.wav',
'LibB/snare.wav'
]
const result = groupWavs(paths)
assert.strictEqual(Object.keys(result).length, 2)
assert.strictEqual(result.LibA.LibA[0].name, 'kick')
assert.strictEqual(result.LibB.LibB[0].name, 'snare')
})
it('strips .wav extension case-insensitively', () => {
const paths = ['Lib/Prog/KICK.WAV']
const result = groupWavs(paths)
assert.strictEqual(result.Lib.Prog[0].name, 'KICK')
})
it('handles deeply nested paths', () => {
const paths = ['A/B/C/D/file.wav']
const result = groupWavs(paths)
assert.strictEqual(result.A.B.length, 1)
assert.strictEqual(result.A.B[0].name, 'file')
assert.strictEqual(result.A.B[0].fullPath, 'A/B/C/D/file.wav')
})
it('handles flat paths with no directory', () => {
const paths = ['sound.wav']
const result = groupWavs(paths)
assert.strictEqual(Object.keys(result).length, 1)
assert.strictEqual(Object.keys(result['']).length, 1)
})
it('returns empty object for empty input', () => {
const result = groupWavs([])
assert.strictEqual(Object.keys(result).length, 0)
})
})
describe('cleanName', () => {
it('replaces underscores with spaces', () => {
assert.strictEqual(cleanName('hello_world'), 'hello world')
})
it('collapses multiple underscores', () => {
assert.strictEqual(cleanName('AMG_-_Black__II'), 'AMG - Black II')
})
it('trims leading/trailing spaces from underscores', () => {
assert.strictEqual(cleanName('_padded_'), 'padded')
})
it('preserves regular text', () => {
assert.strictEqual(cleanName('Kick Drum'), 'Kick Drum')
})
})