Skip to content
Merged
109 changes: 109 additions & 0 deletions __tests__/vapi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,115 @@ describe("Vapi local audio level observer", () => {
});
});

describe("Vapi clientSideNoiseCancellationEnabled", () => {
const webCall = {
id: "call_test",
webCallUrl: "https://example.daily.co/test",
};
const noiseCancellation = {
audio: { processor: { type: "noise-cancellation" } },
};

afterEach(() => {
mockDailyCall = null;
});

function startCall(vapi: Vapi, options?: { clientSideNoiseCancellationEnabled?: boolean }) {
return vapi.start(
"dummy_assistant_id",
undefined,
undefined,
undefined,
undefined,
options
);
}

it("turns noise cancellation on by default", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");

await startCall(vapi);

expect(mockDailyCall.updateInputSettings).toHaveBeenCalledWith(
noiseCancellation
);
});

it("skips noise cancellation when start() is told not to", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");
vapi.on("local-volume-level", () => {});

const call = await startCall(vapi, { clientSideNoiseCancellationEnabled: false });
await flushRejections();

expect(call).not.toBeNull();
expect(mockDailyCall.updateInputSettings).not.toHaveBeenCalled();
// Nothing swaps the track, so the observer starts without waiting.
expect(mockDailyCall.startLocalAudioLevelObserver).toHaveBeenCalledWith(100);
});

it("reports no audio processing stage when start() skips it", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");
const stages: string[] = [];
vapi.on("call-start-progress", (event) => {
stages.push(event.stage);
});

await startCall(vapi, { clientSideNoiseCancellationEnabled: false });

expect(stages).not.toContain("audio-processing-setup");
});

it("keeps the value from start() on reconnect()", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");
await startCall(vapi, { clientSideNoiseCancellationEnabled: false });
await vapi.stop();

mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
await vapi.reconnect(webCall);

expect(mockDailyCall.updateInputSettings).not.toHaveBeenCalled();
});

it("lets reconnect() override the value from start()", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");
await startCall(vapi, { clientSideNoiseCancellationEnabled: false });
await vapi.stop();

mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
await vapi.reconnect(webCall, { clientSideNoiseCancellationEnabled: true });

expect(mockDailyCall.updateInputSettings).toHaveBeenCalledWith(
noiseCancellation
);
});

it("turns noise cancellation on for reconnect() without a prior start()", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");

await vapi.reconnect(webCall);

expect(mockDailyCall.updateInputSettings).toHaveBeenCalledWith(
noiseCancellation
);
});

it("skips noise cancellation when reconnect() is told not to", async () => {
mockDailyCall = createMockDailyCall(jest.fn().mockResolvedValue(undefined));
const vapi = new Vapi("dummy_token");

await vapi.reconnect(webCall, { clientSideNoiseCancellationEnabled: false });

expect(mockDailyCall.updateInputSettings).not.toHaveBeenCalled();
});
});

// The SDK never starts a recording itself: a token (or Vapi's servers) does,
// and a missing token or a failed server-side start becomes recording-error.
describe("Vapi video recording start", () => {
Expand Down
Loading
Loading