import { describe, expect, it, vi } from "vitest"; import type { CliDeps } from "../cli/deps.js"; import type { RuntimeEnv } from "../runtime.js"; import { sendCommand } from "./send.js"; const runtime: RuntimeEnv = { log: vi.fn(), error: vi.fn(), exit: vi.fn(() => { throw new Error("exit"); }), }; const baseDeps = { assertProvider: vi.fn(), sendMessageWeb: vi.fn(), resolveTwilioMediaUrl: vi.fn(), sendMessage: vi.fn(), waitForFinalStatus: vi.fn(), } as unknown as CliDeps; describe("sendCommand", () => { it("validates wait and poll", async () => { await expect(() => sendCommand( { to: "+1", message: "hi", wait: "-1", poll: "2", provider: "twilio", }, baseDeps, runtime, ), ).rejects.toThrow("Wait must be >= 0 seconds"); await expect(() => sendCommand( { to: "+1", message: "hi", wait: "0", poll: "0", provider: "twilio", }, baseDeps, runtime, ), ).rejects.toThrow("Poll must be > 0 seconds"); }); it("handles web dry-run and warns on wait", async () => { const deps = { ...baseDeps, sendMessageWeb: vi.fn(), } as CliDeps; await sendCommand( { to: "+1", message: "hi", wait: "5", poll: "2", provider: "web", dryRun: true, media: "pic.jpg", }, deps, runtime, ); expect(deps.sendMessageWeb).not.toHaveBeenCalled(); }); it("sends via web and outputs JSON", async () => { const deps = { ...baseDeps, sendMessageWeb: vi.fn().mockResolvedValue({ messageId: "web1" }), } as CliDeps; await sendCommand( { to: "+1", message: "hi", wait: "1", poll: "2", provider: "web", json: true, }, deps, runtime, ); expect(deps.sendMessageWeb).toHaveBeenCalled(); expect(runtime.log).toHaveBeenCalledWith( expect.stringContaining('"provider": "web"'), ); }); it("supports twilio dry-run", async () => { const deps = { ...baseDeps } as CliDeps; await sendCommand( { to: "+1", message: "hi", wait: "0", poll: "2", provider: "twilio", dryRun: true, }, deps, runtime, ); expect(deps.sendMessage).not.toHaveBeenCalled(); }); it("sends via twilio with media and skips wait when zero", async () => { const deps = { ...baseDeps, resolveTwilioMediaUrl: vi.fn().mockResolvedValue("https://media"), sendMessage: vi.fn().mockResolvedValue({ sid: "SM1", client: {} }), waitForFinalStatus: vi.fn(), } as CliDeps; await sendCommand( { to: "+1", message: "hi", wait: "0", poll: "2", provider: "twilio", media: "pic.jpg", serveMedia: true, json: true, }, deps, runtime, ); expect(deps.resolveTwilioMediaUrl).toHaveBeenCalledWith("pic.jpg", { serveMedia: true, runtime, }); expect(deps.waitForFinalStatus).not.toHaveBeenCalled(); expect(runtime.log).toHaveBeenCalledWith( expect.stringContaining('"provider": "twilio"'), ); }); });