Files
advanced-camera-card/tests/card-controller/call/tones/chime.test.ts
T

92 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// @vitest-environment jsdom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { ChimeTone } from '../../../../src/card-controller/call/tones/chime';
import { useAudioMocks } from './test-utils';
const audio = useAudioMocks();
// Each strike emits a 3-layer bell stack in the order: sparkle (one octave
// above the fundamental), fundamental, hum (one octave below). The frequencies
// here are the per-layer values derived from each strike's fundamental.
describe('ChimeTone', () => {
it('should play DING (Eb5) then DOOOOONG (B4) 0.5s later', () => {
new ChimeTone(0).start();
// 2 strikes × 3 layers = 6 oscillators.
expect(audio.oscillators).toHaveLength(6);
// DING -- Eb5 (622.25Hz) at t=0.
expect(audio.oscillators[0].frequency.value).toBe(622.25 * 2);
expect(audio.oscillators[1].frequency.value).toBe(622.25);
expect(audio.oscillators[2].frequency.value).toBe(622.25 / 2);
expect(audio.oscillators[0].start).toHaveBeenCalledWith(0);
expect(audio.oscillators[1].start).toHaveBeenCalledWith(0);
expect(audio.oscillators[2].start).toHaveBeenCalledWith(0);
// DOOOOONG -- B4 (493.88Hz) at t=0.5.
expect(audio.oscillators[3].frequency.value).toBe(493.88 * 2);
expect(audio.oscillators[4].frequency.value).toBe(493.88);
expect(audio.oscillators[5].frequency.value).toBe(493.88 / 2);
expect(audio.oscillators[3].start).toHaveBeenCalledWith(0.5);
expect(audio.oscillators[4].start).toHaveBeenCalledWith(0.5);
expect(audio.oscillators[5].start).toHaveBeenCalledWith(0.5);
});
it('should give DING a brighter, shorter bell envelope', () => {
new ChimeTone(0).start();
// Sparkle / fundamental / hum peaks for DING.
expect(audio.gainParams[0].linearRampToValueAtTime).toHaveBeenCalledWith(0.1, 0.005);
expect(audio.gainParams[1].linearRampToValueAtTime).toHaveBeenCalledWith(
0.22,
0.005,
);
expect(audio.gainParams[2].linearRampToValueAtTime).toHaveBeenCalledWith(
0.08,
0.005,
);
// Decay constants (sparkle fades fastest, hum lingers).
expect(audio.gainParams[0].setTargetAtTime).toHaveBeenCalledWith(0, 0.005, 0.3);
expect(audio.gainParams[1].setTargetAtTime).toHaveBeenCalledWith(0, 0.005, 0.8);
expect(audio.gainParams[2].setTargetAtTime).toHaveBeenCalledWith(0, 0.005, 1.2);
});
it('should give DOOOOONG a fuller, longer bell envelope', () => {
new ChimeTone(0).start();
expect(audio.gainParams[3].linearRampToValueAtTime).toHaveBeenCalledWith(
0.11,
0.505,
);
expect(audio.gainParams[4].linearRampToValueAtTime).toHaveBeenCalledWith(
0.28,
0.505,
);
expect(audio.gainParams[5].linearRampToValueAtTime).toHaveBeenCalledWith(0.1, 0.505);
expect(audio.gainParams[3].setTargetAtTime).toHaveBeenCalledWith(0, 0.505, 0.5);
expect(audio.gainParams[4].setTargetAtTime).toHaveBeenCalledWith(0, 0.505, 1.3);
expect(audio.gainParams[5].setTargetAtTime).toHaveBeenCalledWith(0, 0.505, 1.8);
});
describe('with fake timers', () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
it('should schedule the next iteration 5 seconds after a strike pair', () => {
new ChimeTone(0).start();
expect(audio.oscillators).toHaveLength(6);
vi.advanceTimersByTime(5_000);
// A second iteration ran, producing another 6 oscillators.
expect(audio.oscillators).toHaveLength(12);
});
});
});