Files

26 lines
1.5 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { createSound } from '../src/client/sound.js';
test('audio starts only after unlock, deduplicates events, stops on mute and persists preference', async () => {
let created = 0, started = 0, stopped = 0;
const values = new Map<string, string>();
const param = () => ({ value: 0, setValueAtTime() {}, exponentialRampToValueAtTime() {}, linearRampToValueAtTime() {} });
const node = () => ({ connect() {}, disconnect() {}, gain: param(), frequency: param(), pan: param(),
start() { started++; }, stop() { stopped++; }, onended: null });
const context = { state: 'suspended', currentTime: 0, sampleRate: 44100, destination: {},
async resume() { this.state = 'running'; }, createGain: node, createOscillator: node,
createStereoPanner: node, createDynamicsCompressor: node,
};
const sound = createSound({ context: () => { created++; return context as unknown as AudioContext; },
storage: { getItem: key => values.get(key) ?? null, setItem: (key, value) => { values.set(key, value); } } });
sound.play('click'); assert.equal(created, 0);
await sound.unlock(); assert.equal(created, 1);
sound.play('click', 'one'); const count = started;
sound.play('click', 'one'); assert.equal(started, count);
sound.play('click', 'two'); assert.ok(started > count);
sound.setMuted(true); assert.ok(stopped > 0);
const mutedCount = started; sound.play('click'); assert.equal(started, mutedCount);
assert.ok([...values.values()].includes('true'));
});