64 lines
3.7 KiB
JavaScript
64 lines
3.7 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
const { createSoundDirector, COUNTS, CATALOG } = require('../../data/game_sounds.js');
|
|
|
|
function recorder() { const played = []; return { played, playPreset: preset => { played.push(preset); return true; } }; }
|
|
|
|
test('every required event family has its planned minimum of original synthesis presets', () => {
|
|
Object.entries(COUNTS).forEach(([family, count]) => {
|
|
assert.equal(CATALOG[family].length, count);
|
|
assert.equal(new Set(CATALOG[family].map(preset => preset.id)).size, count);
|
|
});
|
|
});
|
|
|
|
test('selection is randomized without immediate repeats and keeps bounded history', () => {
|
|
const output = recorder(); let sample = 0;
|
|
const director = createSoundDirector({ engine: output, random: () => (sample++ % 11) / 11, historyLimit: 3 });
|
|
const selected = [];
|
|
for (let index = 0; index < 30; index += 1) selected.push(director.play('shot').preset.id);
|
|
selected.slice(1).forEach((id, index) => assert.notEqual(id, selected[index]));
|
|
assert.ok(director.getHistory('shot').length <= 3);
|
|
});
|
|
|
|
test('preset parameter ranges remain safe through many randomized selections', () => {
|
|
const output = recorder(); const director = createSoundDirector({ engine: output, random: Math.random });
|
|
for (let index = 0; index < 3000; index += 1) director.play(Object.keys(COUNTS)[index % Object.keys(COUNTS).length]);
|
|
output.played.forEach(preset => {
|
|
assert.ok(preset.frequency >= 100 && preset.frequency <= 1000);
|
|
assert.ok(preset.endFrequency >= 100 && preset.endFrequency <= 1000);
|
|
assert.ok(preset.durationMs >= 100 && preset.durationMs <= 900);
|
|
assert.ok(preset.filterHz >= 900 && preset.filterHz <= 3500);
|
|
assert.ok(Math.abs(preset.pan) <= 0.4 && preset.gain <= 0.75);
|
|
});
|
|
});
|
|
|
|
test('state versions, perspectives, priority, waiting rate limit, and reconnect summaries are safe', () => {
|
|
const output = recorder(); let clock = 0;
|
|
const director = createSoundDirector({ engine: output, random: () => 0, now: () => clock, waitingIntervalMs: 12000 });
|
|
assert.ok(director.getPriority('victory') > director.getPriority('sunk'));
|
|
assert.ok(director.getPriority('sunk') > director.getPriority('hit'));
|
|
assert.ok(director.getPriority('hit') > director.getPriority('miss'));
|
|
assert.equal(director.play('watch-hit', { version: 4 }).preset.family, 'hit');
|
|
assert.equal(director.play('damage', { version: 4 }), false);
|
|
assert.equal(director.play('watch-sunk', { version: 5 }).preset.family, 'sunk');
|
|
assert.equal(director.play('waiting').preset.family, 'waiting');
|
|
assert.equal(director.play('waiting'), false);
|
|
clock = 12001;
|
|
assert.equal(director.play('waiting').preset.family, 'waiting');
|
|
assert.equal(director.play('summary', { version: 6, summary: true }).preset.family, 'victory');
|
|
});
|
|
|
|
test('combos escalate, reduced intensity suppresses extras, and recovery remains calm', () => {
|
|
const output = recorder(); const director = createSoundDirector({ engine: output, random: () => 0.3 });
|
|
assert.equal(director.play('hit', { combo: 2 }).combo, 'combo');
|
|
assert.equal(director.play('hit', { combo: 3 }).combo, 'mega');
|
|
assert.equal(director.play('sunk', { combo: 4 }).combo, 'ultra');
|
|
const count = output.played.length;
|
|
assert.equal(director.play('hit', { combo: 4, reduced: true }).combo, 'ultra');
|
|
assert.equal(output.played.length, count + 1);
|
|
assert.equal(director.play('waiting', { reduced: true }), false);
|
|
const recovery = ['recovery-open', 'recovery-cancel', 'recovery-leave', 'recovery-profile', 'recovery-game'].map(event => director.play(event).preset);
|
|
assert.equal(new Set(recovery.map(preset => preset.id)).size, 5);
|
|
recovery.forEach(preset => assert.ok(preset.family === 'recovery' && preset.gain <= 0.16 && preset.durationMs <= 300));
|
|
});
|