Files

221 lines
5.8 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import {
handleNotificationEvent,
playNotification,
shouldPlayNotification,
} from "../src/audio";
describe("shouldPlayNotification", () => {
it("returns false when the selected sound is unavailable", () => {
expect(
shouldPlayNotification({
selectedSound: "missing.wav",
soundExists: false,
})
).toBe(false);
});
it("returns true when a selected sound exists", () => {
expect(
shouldPlayNotification({
selectedSound: "ping-success.wav",
soundExists: true,
})
).toBe(true);
});
});
describe("playNotification", () => {
it("warns and plays nothing for an invalid selected sound", async () => {
const warn = vi.fn();
const createAudio = vi.fn();
const result = await playNotification({
audioUrl: "unused",
createAudio,
logger: { warn },
selectedSound: "missing.wav",
soundExists: false,
volume: 0.7,
});
expect(result.played).toBe(false);
expect(createAudio).not.toHaveBeenCalled();
expect(warn).toHaveBeenCalledWith(expect.stringContaining("Selected sound"));
});
it("clears stale current audio for an invalid selected sound", async () => {
const pause = vi.fn();
const warn = vi.fn();
const currentAudio = {
currentTime: 9,
pause,
play: vi.fn(),
volume: 0.2,
};
const result = await playNotification({
audioUrl: "unused",
createAudio: vi.fn(),
currentAudio,
logger: { warn },
selectedSound: "missing.wav",
soundExists: false,
volume: 0.7,
});
expect(pause).toHaveBeenCalledTimes(1);
expect(currentAudio.currentTime).toBe(0);
expect(result.played).toBe(false);
expect(result.audio).toBeNull();
expect(warn).toHaveBeenCalledWith(expect.stringContaining("Selected sound"));
});
it("stops the previous audio before playing a new sound", async () => {
const pause = vi.fn();
const play = vi.fn().mockResolvedValue(undefined);
const currentAudio = {
currentTime: 12,
pause,
play: vi.fn(),
volume: 0,
};
const nextAudio = {
currentTime: 0,
pause: vi.fn(),
play,
volume: 0,
};
const createAudio = vi.fn(() => nextAudio);
const result = await playNotification({
audioUrl: "memory://ping-success",
createAudio,
currentAudio,
selectedSound: "ping-success.wav",
soundExists: true,
stopPrevious: true,
volume: 0.4,
});
expect(pause).toHaveBeenCalledTimes(1);
expect(currentAudio.currentTime).toBe(0);
expect(nextAudio.volume).toBe(0.4);
expect(play).toHaveBeenCalledTimes(1);
expect(result.played).toBe(true);
expect(result.audio).toBe(nextAudio);
});
it("warns and returns a non-playing result when audio playback rejects", async () => {
const warn = vi.fn();
const pause = vi.fn();
const play = vi.fn().mockRejectedValue(new Error("autoplay blocked"));
const currentAudio = {
currentTime: 4,
pause,
play: vi.fn(),
volume: 0.3,
};
const nextAudio = {
currentTime: 0,
pause: vi.fn(),
play,
volume: 0,
};
const result = await playNotification({
audioUrl: "memory://ping-failure",
createAudio: vi.fn(() => nextAudio),
currentAudio,
logger: { warn },
selectedSound: "ping-failure.wav",
soundExists: true,
volume: 0.5,
});
expect(warn).toHaveBeenCalledWith(
expect.stringContaining("Unable to play notification audio")
);
expect(result.played).toBe(false);
expect(result.audio).toBeNull();
});
});
describe("handleNotificationEvent", () => {
it("plays flat sound ids through the real backend sound route", async () => {
const play = vi.fn().mockResolvedValue(undefined);
const audio = {
currentTime: 0,
pause: vi.fn(),
play,
volume: 0,
};
const createAudio = vi.fn(() => audio);
const result = await handleNotificationEvent({
catalog: [{ name: "uploaded.wav" }],
createAudio,
detail: {
event_kind: "global",
sound_id: "uploaded.wav",
source: "queue_drained",
status: "success",
volume: 0.8,
},
});
expect(createAudio).toHaveBeenCalledWith("/comfyui-ping/sounds/uploaded.wav");
expect(play).toHaveBeenCalledTimes(1);
expect(result.played).toBe(true);
});
it("normalizes legacy prefixed sound ids before playback", async () => {
const play = vi.fn().mockResolvedValue(undefined);
const audio = {
currentTime: 0,
pause: vi.fn(),
play,
volume: 0,
};
const createAudio = vi.fn(() => audio);
const result = await handleNotificationEvent({
catalog: [{ name: "uploaded.wav" }],
createAudio,
detail: {
event_kind: "global",
sound_id: "custom:uploaded.wav",
source: "queue_drained",
status: "success",
volume: 0.8,
},
});
expect(createAudio).toHaveBeenCalledWith("/comfyui-ping/sounds/uploaded.wav");
expect(play).toHaveBeenCalledTimes(1);
expect(result.played).toBe(true);
});
it("warns and stays silent when the selected sound is not in the catalog", async () => {
const warn = vi.fn();
const createAudio = vi.fn();
const result = await handleNotificationEvent({
catalog: [{ name: "ping-success.wav" }],
createAudio,
detail: {
event_kind: "global",
sound_id: "uploaded.wav",
source: "queue_drained",
status: "success",
volume: 0.8,
},
logger: { warn },
});
expect(createAudio).not.toHaveBeenCalled();
expect(warn).toHaveBeenCalledWith(expect.stringContaining("Selected sound"));
expect(result.played).toBe(false);
});
});