Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline (Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/* packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
101 lines
2.5 KiB
TypeScript
101 lines
2.5 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { type OoSoundCue, ooSound } from "./oo-sound";
|
|
import { readOoSoundEnabled, writeOoSoundEnabled } from "./oo-sound-pref";
|
|
|
|
describe("oo-sound-pref", () => {
|
|
const storage = new Map<string, string>();
|
|
|
|
beforeEach(() => {
|
|
storage.clear();
|
|
const localStorage = {
|
|
getItem: (key: string) => storage.get(key) ?? null,
|
|
setItem: (key: string, value: string) => {
|
|
storage.set(key, value);
|
|
},
|
|
removeItem: (key: string) => {
|
|
storage.delete(key);
|
|
},
|
|
};
|
|
vi.stubGlobal("localStorage", localStorage);
|
|
vi.stubGlobal("window", { localStorage });
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it("defaults sound to enabled", () => {
|
|
expect(readOoSoundEnabled()).toBe(true);
|
|
});
|
|
|
|
it("persists disabled preference", () => {
|
|
writeOoSoundEnabled(false);
|
|
expect(readOoSoundEnabled()).toBe(false);
|
|
writeOoSoundEnabled(true);
|
|
expect(readOoSoundEnabled()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("ooSound", () => {
|
|
class FakeContext {
|
|
state: AudioContextState = "running";
|
|
currentTime = 0;
|
|
destination = {};
|
|
createGain() {
|
|
return {
|
|
gain: { value: 0, setValueAtTime: vi.fn(), exponentialRampToValueAtTime: vi.fn() },
|
|
connect: vi.fn(),
|
|
};
|
|
}
|
|
createOscillator() {
|
|
return {
|
|
type: "sine",
|
|
frequency: { setValueAtTime: vi.fn() },
|
|
connect: vi.fn(),
|
|
start: vi.fn(),
|
|
stop: vi.fn(),
|
|
};
|
|
}
|
|
resume = vi.fn(async () => undefined);
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.stubGlobal("AudioContext", FakeContext);
|
|
vi.stubGlobal("window", {
|
|
matchMedia: () => ({
|
|
matches: false,
|
|
addEventListener: vi.fn(),
|
|
removeEventListener: vi.fn(),
|
|
}),
|
|
});
|
|
vi.stubGlobal("document", { visibilityState: "visible" });
|
|
writeOoSoundEnabled(true);
|
|
ooSound.setEnabled(true);
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it("plays procedural cues when enabled", () => {
|
|
const cues: OoSoundCue[] = [
|
|
"work-complete",
|
|
"listening-start",
|
|
"listening-stop",
|
|
"speaking-start",
|
|
"speaking-done",
|
|
"attention",
|
|
"message-sent",
|
|
"handoff",
|
|
];
|
|
for (const cue of cues) {
|
|
expect(() => ooSound.play(cue)).not.toThrow();
|
|
}
|
|
});
|
|
|
|
it("skips playback when disabled", () => {
|
|
ooSound.setEnabled(false);
|
|
expect(() => ooSound.play("work-complete")).not.toThrow();
|
|
});
|
|
});
|