ci / module boundaries / boundaries (push) Successful in 6s
ci / api / api (push) Successful in 47s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m2s
ci / db / db (push) Successful in 1m4s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m30s
ci / ts / ts (packages + web) (push) Successful in 2m54s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m14s
58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { AudioAnalysis } from './analysis';
|
|
import { AudioEngine } from './engine';
|
|
|
|
afterEach(() => vi.restoreAllMocks());
|
|
|
|
function fixture() {
|
|
const sample = vi.fn((data: Uint8Array) => {
|
|
data.fill(0);
|
|
// 48 kHz / 1024: bins 1..4 cover the bass band.
|
|
data.fill(255, 1, 5);
|
|
});
|
|
const analyser = { context: { sampleRate: 48000 }, fftSize: 1024, getByteFrequencyData: sample } as unknown as AnalyserNode;
|
|
const analysis = new AudioAnalysis(() => analyser);
|
|
return { analysis, sample };
|
|
}
|
|
|
|
describe('audio reactivity', () => {
|
|
it('separates bass from the other frequency bands and shares the frame', () => {
|
|
vi.spyOn(performance, 'now').mockReturnValue(100);
|
|
const { analysis, sample } = fixture();
|
|
expect(analysis.read(true)).toEqual({ bass: 1, mid: 0, treble: 0 });
|
|
analysis.read(true);
|
|
expect(sample).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('returns silence after pausing or muting', () => {
|
|
const clock = vi.spyOn(performance, 'now').mockReturnValue(100);
|
|
const { analysis, sample } = fixture();
|
|
analysis.read(true);
|
|
clock.mockReturnValue(120);
|
|
expect(analysis.read(false)).toEqual({ bass: 0, mid: 0, treble: 0 });
|
|
clock.mockReturnValue(140);
|
|
expect(analysis.read(false)).toEqual({ bass: 0, mid: 0, treble: 0 });
|
|
expect(sample).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('works when Web Audio is unavailable', () => {
|
|
const analysis = new AudioAnalysis(() => null);
|
|
expect(analysis.read(false)).toEqual({ bass: 0, mid: 0, treble: 0 });
|
|
});
|
|
});
|
|
|
|
describe('audio engine lifetime', () => {
|
|
it('removes audio listeners on disposal', () => {
|
|
const audio = document.createElement('audio');
|
|
const engine = new AudioEngine(audio);
|
|
const playing = vi.fn();
|
|
engine.on('playing', playing);
|
|
audio.dispatchEvent(new Event('playing'));
|
|
expect(playing).toHaveBeenCalledTimes(1);
|
|
engine.dispose();
|
|
audio.dispatchEvent(new Event('playing'));
|
|
expect(playing).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|