




























@@ -48,7 +48,7 @@ vi.mock("./twiml.js", () => ({
4848generateNotifyTwiml: generateNotifyTwimlMock,
4949}));
505051-import { endCall, initiateCall, speak } from "./outbound.js";
51+import { endCall, initiateCall, sendDtmf, speak } from "./outbound.js";
52525353function createActiveCallContext(params: { hangupCall?: ReturnType<typeof vi.fn> } = {}) {
5454const call = { callId: "call-1", providerCallId: "provider-1", state: "active" };
@@ -226,6 +226,47 @@ describe("voice-call outbound helpers", () => {
226226expect(transitionStateMock).toHaveBeenLastCalledWith(call, "listening");
227227});
228228229+it("sends DTMF through connected provider calls", async () => {
230+const call = { callId: "call-1", providerCallId: "provider-1", state: "active" };
231+const sendDtmfProvider = vi.fn(async () => {});
232+const ctx = {
233+activeCalls: new Map([["call-1", call]]),
234+providerCallIdMap: new Map(),
235+provider: { name: "twilio", sendDtmf: sendDtmfProvider },
236+config: {},
237+storePath: "/tmp/voice-call.json",
238+};
239+240+await expect(sendDtmf(ctx as never, "call-1", "ww123#")).resolves.toEqual({
241+success: true,
242+});
243+expect(sendDtmfProvider).toHaveBeenCalledWith({
244+callId: "call-1",
245+providerCallId: "provider-1",
246+digits: "ww123#",
247+});
248+});
249+250+it("rejects invalid or unsupported outbound DTMF", async () => {
251+const call = { callId: "call-1", providerCallId: "provider-1", state: "active" };
252+const ctx = {
253+activeCalls: new Map([["call-1", call]]),
254+providerCallIdMap: new Map(),
255+provider: { name: "telnyx" },
256+config: {},
257+storePath: "/tmp/voice-call.json",
258+};
259+260+await expect(sendDtmf(ctx as never, "call-1", "abc")).resolves.toEqual({
261+success: false,
262+error: "digits may only contain digits, *, #, comma, w, p",
263+});
264+await expect(sendDtmf(ctx as never, "call-1", "123#")).resolves.toEqual({
265+success: false,
266+error: "telnyx does not support outbound DTMF",
267+});
268+});
269+229270it("ends connected calls, clears timers, and rejects pending transcripts", async () => {
230271const { call, ctx, hangupCall } = createActiveCallContext();
231272此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。