animetix-web / frontend /src /utils /__tests__ /SoundManager.test.ts
MissawB's picture
Upload folder using huggingface_hub (part 5)
c288a20 verified
Raw
History Blame Contribute Delete
2.67 kB
import { describe, it, expect, vi, beforeEach } from 'vitest';
// SoundManager wraps `howler`'s Howl. Mock it so no real audio loads and we can
// assert play() is invoked. `play` resolves to mimic the real (async) call.
const playSpy = vi.fn().mockResolvedValue(undefined);
// `Howl` is invoked with `new`, so the mock must be a real (non-arrow)
// constructable function returning the instance shape we assert on.
const HowlMock = vi.fn(function HowlCtor(this: { play: typeof playSpy }) {
this.play = playSpy;
});
vi.mock('howler', () => ({
Howl: HowlMock,
}));
const importSoundManager = async () => {
vi.resetModules();
const mod = await import('../SoundManager');
return mod.default;
};
describe('SoundManager', () => {
beforeEach(() => {
vi.clearAllMocks();
localStorage.clear();
});
it('constructs one Howl instance per sound type', async () => {
await importSoundManager();
// click, win, loss, unlock, reveal, error
expect(HowlMock).toHaveBeenCalledTimes(6);
});
it('plays the requested sound when not muted', async () => {
const sm = await importSoundManager();
sm.play('click');
expect(playSpy).toHaveBeenCalledTimes(1);
});
it('does not play when muted (persisted in localStorage)', async () => {
localStorage.setItem('sound_muted', 'true');
const sm = await importSoundManager();
sm.play('win');
expect(playSpy).not.toHaveBeenCalled();
});
it('tolerates play() rejections without throwing', async () => {
playSpy.mockRejectedValueOnce(new Error('autoplay blocked'));
const sm = await importSoundManager();
expect(() => sm.play('error')).not.toThrow();
});
it('toggle() flips mute state and persists it', async () => {
const sm = await importSoundManager();
const muted = sm.toggle();
expect(muted).toBe(true);
expect(localStorage.getItem('sound_muted')).toBe('true');
// While muted, play is suppressed.
sm.play('click');
expect(playSpy).not.toHaveBeenCalled();
const unmuted = sm.toggle();
expect(unmuted).toBe(false);
expect(localStorage.getItem('sound_muted')).toBe('false');
sm.play('click');
expect(playSpy).toHaveBeenCalledTimes(1);
});
it('triggers vibration patterns for relevant sound types', async () => {
const vibrate = vi.fn();
vi.stubGlobal('navigator', { vibrate });
const sm = await importSoundManager();
sm.play('win');
expect(vibrate).toHaveBeenCalledWith([100, 30, 100, 30, 200]);
sm.play('error');
expect(vibrate).toHaveBeenCalledWith(200);
sm.play('click');
expect(vibrate).toHaveBeenCalledWith(10);
vi.unstubAllGlobals();
});
});