mirror of
https://github.com/Quad4-Software/MeshChatX.git
synced 2026-08-18 09:49:09 -04:00
121 lines
4.8 KiB
JavaScript
121 lines
4.8 KiB
JavaScript
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import NotificationSoundUtils from "../../meshchatx/src/frontend/js/NotificationSoundUtils";
|
|
|
|
describe("NotificationSoundUtils", () => {
|
|
let audioInstances;
|
|
let originalAudio;
|
|
|
|
beforeEach(() => {
|
|
audioInstances = [];
|
|
originalAudio = globalThis.Audio;
|
|
globalThis.Audio = vi.fn(function (src) {
|
|
const player = {
|
|
src,
|
|
loop: false,
|
|
volume: 1,
|
|
currentTime: 0,
|
|
onended: null,
|
|
play: vi.fn().mockResolvedValue(undefined),
|
|
pause: vi.fn(),
|
|
};
|
|
audioInstances.push(player);
|
|
return player;
|
|
});
|
|
globalThis.window = globalThis.window || {};
|
|
globalThis.window.api = {
|
|
get: vi.fn(),
|
|
};
|
|
NotificationSoundUtils.stop();
|
|
NotificationSoundUtils.autoplayBlocked = false;
|
|
});
|
|
|
|
afterEach(() => {
|
|
globalThis.Audio = originalAudio;
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("shouldPlay returns false when disabled", () => {
|
|
expect(NotificationSoundUtils.shouldPlay({ notification_sound_enabled: false })).toBe(false);
|
|
expect(NotificationSoundUtils.shouldPlay({ notification_sound_enabled: true })).toBe(true);
|
|
expect(NotificationSoundUtils.shouldPlay(null)).toBe(false);
|
|
});
|
|
|
|
it("play skips when disabled", async () => {
|
|
const result = await NotificationSoundUtils.play({ notification_sound_enabled: false });
|
|
expect(result).toBe(false);
|
|
expect(globalThis.window.api.get).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("play skips when status has no sound", async () => {
|
|
globalThis.window.api.get.mockResolvedValue({
|
|
data: { enabled: true, has_sound: false, id: null },
|
|
});
|
|
const result = await NotificationSoundUtils.play({ notification_sound_enabled: true });
|
|
expect(result).toBe(false);
|
|
expect(globalThis.Audio).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("play creates audio when configured", async () => {
|
|
globalThis.window.api.get.mockResolvedValue({
|
|
data: { enabled: true, has_sound: true, id: 7, volume: 0.5 },
|
|
});
|
|
const result = await NotificationSoundUtils.play({ notification_sound_enabled: true });
|
|
expect(result).toBe(true);
|
|
expect(globalThis.window.api.get).toHaveBeenCalledWith("/api/v1/notification-sounds/status");
|
|
expect(globalThis.Audio).toHaveBeenCalledWith("/api/v1/notification-sounds/7/audio");
|
|
expect(audioInstances[0].volume).toBe(0.5);
|
|
expect(audioInstances[0].loop).toBe(false);
|
|
expect(audioInstances[0].play).toHaveBeenCalled();
|
|
});
|
|
|
|
it("play sets autoplayBlocked on NotAllowedError", async () => {
|
|
globalThis.window.api.get.mockResolvedValue({
|
|
data: { enabled: true, has_sound: true, id: 2, volume: 1 },
|
|
});
|
|
globalThis.Audio = vi.fn(function () {
|
|
const player = {
|
|
loop: false,
|
|
volume: 1,
|
|
onended: null,
|
|
play: vi.fn().mockRejectedValue(Object.assign(new Error("blocked"), { name: "NotAllowedError" })),
|
|
pause: vi.fn(),
|
|
currentTime: 0,
|
|
};
|
|
audioInstances.push(player);
|
|
return player;
|
|
});
|
|
|
|
const result = await NotificationSoundUtils.play({ notification_sound_enabled: true });
|
|
expect(result).toBe(false);
|
|
expect(NotificationSoundUtils.autoplayBlocked).toBe(true);
|
|
});
|
|
|
|
it("play returns false while autoplayBlocked", async () => {
|
|
NotificationSoundUtils.autoplayBlocked = true;
|
|
const result = await NotificationSoundUtils.play({ notification_sound_enabled: true });
|
|
expect(result).toBe(false);
|
|
expect(globalThis.window.api.get).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("unlockAutoplay clears blocked flag", () => {
|
|
NotificationSoundUtils.autoplayBlocked = true;
|
|
NotificationSoundUtils.unlockAutoplay();
|
|
expect(NotificationSoundUtils.autoplayBlocked).toBe(false);
|
|
});
|
|
|
|
it("stop pauses active player", async () => {
|
|
globalThis.window.api.get.mockResolvedValue({
|
|
data: { enabled: true, has_sound: true, id: 1, volume: 1 },
|
|
});
|
|
await NotificationSoundUtils.play({ notification_sound_enabled: true });
|
|
NotificationSoundUtils.stop();
|
|
expect(audioInstances[0].pause).toHaveBeenCalled();
|
|
});
|
|
|
|
it("preview plays selected sound", async () => {
|
|
const result = await NotificationSoundUtils.preview(9, 80);
|
|
expect(result).toBe(true);
|
|
expect(globalThis.Audio).toHaveBeenCalledWith("/api/v1/notification-sounds/9/audio");
|
|
expect(audioInstances[0].volume).toBeCloseTo(0.8);
|
|
});
|
|
});
|