

























@@ -1,8 +1,20 @@
11import crypto from "node:crypto";
2-import { describe, expect, it } from "vitest";
2+import { afterEach, describe, expect, it, vi } from "vitest";
33import type { WebhookContext } from "../types.js";
44import { TelnyxProvider } from "./telnyx.js";
556+const apiMocks = vi.hoisted(() => ({
7+fetchWithSsrFGuard: vi.fn(),
8+}));
9+10+vi.mock("../../api.js", () => ({
11+fetchWithSsrFGuard: apiMocks.fetchWithSsrFGuard,
12+}));
13+14+afterEach(() => {
15+apiMocks.fetchWithSsrFGuard.mockReset();
16+});
17+618function createCtx(params?: Partial<WebhookContext>): WebhookContext {
719return {
820headers: {},
@@ -256,3 +268,36 @@ describe("TelnyxProvider.parseWebhookEvent", () => {
256268);
257269});
258270});
271+272+describe("TelnyxProvider answer control", () => {
273+it("answers inbound call-control legs with a deterministic command id", async () => {
274+const release = vi.fn(async () => {});
275+apiMocks.fetchWithSsrFGuard.mockResolvedValue({
276+response: new Response(JSON.stringify({ data: {} }), { status: 200 }),
277+ release,
278+});
279+const provider = new TelnyxProvider({
280+apiKey: "KEY123",
281+connectionId: "CONN456",
282+publicKey: undefined,
283+});
284+285+await provider.answerCall({
286+callId: "call-1",
287+providerCallId: "call-control-1",
288+});
289+290+expect(apiMocks.fetchWithSsrFGuard).toHaveBeenCalledWith(
291+expect.objectContaining({
292+url: "https://api.telnyx.com/v2/calls/call-control-1/actions/answer",
293+auditContext: "voice-call.telnyx.api",
294+policy: { allowedHostnames: ["api.telnyx.com"] },
295+init: expect.objectContaining({
296+method: "POST",
297+body: JSON.stringify({ command_id: "openclaw-answer-call-1" }),
298+}),
299+}),
300+);
301+expect(release).toHaveBeenCalledTimes(1);
302+});
303+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。