scenario("the API calls our webhook and we drive the call", async () => {
const mock = new MockServer();
mock.respond("POST", "/voice", (req) => {
const event = JSON.parse(req.body || "{}").event;
return event === "incoming_call"
? jsonResponse({
actions: [
{ type: "answer" },
{ type: "play", url: "https://example.com/greeting.wav" },
],
})
: jsonResponse({ actions: [{ type: "hangup" }] });
});
mock.respond(regex("/calls/.*/status"), () => textResponse("ok"));
await http("PUT", `${env("API_URL")}/config?webhook=${mock.url}/voice`);
const caller = new Agent("A", {
username: env("A_USER"),
domain: env("SIP_DOMAIN"),
password: env("A_PASS"),
});
caller.register();
await until(() => expect(caller.registered).toBeTruthy(), "10s");
caller.dial(env("API_NUMBER"));
await until(() => expect(mock.requestCount("/voice")).toBe(1), "10s");
const last = mock.lastRequest("/voice");
expect(last).toBeDefined();
expect(JSON.parse(last?.body || "{}").event).toBe("incoming_call");
expect(last?.headers["content-type"]).toContain("application/json");
caller.hangup();
await until(() => expect(caller.state).toBe(State.Idle), "10s");
});