import { afterEach, describe, expect, it, vi } from "vitest"; const combatMedia = vi.hoisted(() => ({ ready: false })); vi.mock("./combatMediaPack", async (importOriginal) => ({ ...(await importOriginal()), combatMediaPackReady: () => combatMedia.ready, })); import { DEFAULT_COMBAT_PRESENTATION_SETTINGS, type CombatPresentationEvent, } from "./combatPresentation"; import { combatAudioOutputEnabled, authenticCombatAudioEnabled, combatMediaPreloadEnabled, configureCombatAudio, masterAudioOutputEnabled, playCombatAudio, playMasterAudioCue, } from "./combatAudio"; const fixtureEvent: CombatPresentationEvent = { id: 1, sessionId: 1, occurredAt: 1, phase: "impact", actorGroup: "player", sourceActorId: "player", targetActorId: "enemy", abilityId: "fixture", name: "Fixture", source: "fallback", school: "holy", delivery: "projectile", origin: [0, 0, 0], targetPosition: [1, 0, 0], }; afterEach(() => { combatMedia.ready = false; vi.unstubAllGlobals(); }); describe("combat audio output policy", () => { it("does not create or fetch audio while the master volume is disabled", async () => { const AudioContextConstructor = vi.fn(); const fetch = vi.fn(); vi.stubGlobal("window", { AudioContext: AudioContextConstructor }); vi.stubGlobal("fetch", fetch); configureCombatAudio(DEFAULT_COMBAT_PRESENTATION_SETTINGS, 0); playCombatAudio(fixtureEvent); await expect(playMasterAudioCue("/fixture.wav")).resolves.toBeNull(); expect(AudioContextConstructor).not.toHaveBeenCalled(); expect(fetch).not.toHaveBeenCalled(); }); it("allows explicitly enabled positive-volume output", () => { expect(masterAudioOutputEnabled(0)).toBe(false); expect(masterAudioOutputEnabled(0.6)).toBe(true); expect(combatAudioOutputEnabled(DEFAULT_COMBAT_PRESENTATION_SETTINGS, 0)).toBe(false); expect(combatAudioOutputEnabled(DEFAULT_COMBAT_PRESENTATION_SETTINGS, 0.6)).toBe(true); expect(authenticCombatAudioEnabled(DEFAULT_COMBAT_PRESENTATION_SETTINGS)).toBe(false); combatMedia.ready = true; expect(authenticCombatAudioEnabled({ ...DEFAULT_COMBAT_PRESENTATION_SETTINGS, originalMediaEnabled: true, })).toBe(true); expect(combatMediaPreloadEnabled(DEFAULT_COMBAT_PRESENTATION_SETTINGS, 0.6)).toBe(false); expect(combatMediaPreloadEnabled({ ...DEFAULT_COMBAT_PRESENTATION_SETTINGS, originalMediaEnabled: true, }, 0.6)).toBe(true); }); it("does not fetch packaged sound effects before the player downloads them", async () => { const AudioContextConstructor = vi.fn(); const fetch = vi.fn(); vi.stubGlobal("window", { AudioContext: AudioContextConstructor }); vi.stubGlobal("fetch", fetch); configureCombatAudio(DEFAULT_COMBAT_PRESENTATION_SETTINGS, 0.6); await expect(playMasterAudioCue("/assets/game/combat-effects/audio/fixture.wav")).resolves.toBeNull(); expect(AudioContextConstructor).not.toHaveBeenCalled(); expect(fetch).not.toHaveBeenCalled(); }); it("does not initialize audio for a zero-volume actor group", () => { const AudioContextConstructor = vi.fn(); vi.stubGlobal("window", { AudioContext: AudioContextConstructor }); configureCombatAudio({ ...DEFAULT_COMBAT_PRESENTATION_SETTINGS, audioVolume: { ...DEFAULT_COMBAT_PRESENTATION_SETTINGS.audioVolume, player: 0, }, }, 0.6); playCombatAudio(fixtureEvent); expect(AudioContextConstructor).not.toHaveBeenCalled(); }); });