const { describe, it } = require('node:test') const assert = require('node:assert/strict') const { esc, sanitize, formatBytes, formatTime, groupWavs, cleanName } = require('./util.js') describe('esc', () => { it('escapes HTML entities', () => { assert.strictEqual(esc(''), '<script>alert("xss")</script>') }) it('handles ampersands', () => { assert.strictEqual(esc('a & b'), 'a & b') }) it('handles single quotes', () => { assert.strictEqual(esc("it's"), 'it's') }) it('returns empty string for falsy input', () => { assert.strictEqual(esc(''), '') assert.strictEqual(esc(null), '') assert.strictEqual(esc(undefined), '') }) it('passes through safe strings', () => { assert.strictEqual(esc('Hello World'), 'Hello World') }) }) describe('sanitize', () => { it('replaces special characters with underscores', () => { assert.strictEqual(sanitize('hello world!'), 'hello_world_') }) it('preserves alphanumeric and dashes', () => { assert.strictEqual(sanitize('test-123_abc'), 'test-123_abc') }) it('sanitizes dots and slashes', () => { assert.strictEqual(sanitize('path/to/file.name'), 'path_to_file_name') }) }) describe('formatBytes', () => { it('formats zero', () => { assert.strictEqual(formatBytes(0), '0 B') }) it('formats bytes', () => { assert.strictEqual(formatBytes(500), '500 B') }) it('formats KB', () => { assert.strictEqual(formatBytes(1024), '1 KB') }) it('formats MB', () => { assert.strictEqual(formatBytes(1048576), '1 MB') }) it('formats GB', () => { assert.strictEqual(formatBytes(1073741824), '1 GB') }) it('formats fractional', () => { assert.strictEqual(formatBytes(1536), '1.5 KB') }) }) describe('formatTime', () => { it('formats zero', () => { assert.strictEqual(formatTime(0), '0:00') }) it('formats seconds', () => { assert.strictEqual(formatTime(5), '0:05') }) it('formats minutes and seconds', () => { assert.strictEqual(formatTime(65), '1:05') }) it('formats double-digit seconds', () => { assert.strictEqual(formatTime(75), '1:15') }) 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') }) })