openclaw/src/commands/up.test.ts

77 lines
2.2 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import type { CliDeps } from "../cli/deps.js";
import type { RuntimeEnv } from "../runtime.js";
import { upCommand } from "./up.js";
const runtime: RuntimeEnv = {
log: vi.fn(),
error: vi.fn(),
exit: vi.fn(() => {
throw new Error("exit");
}),
};
const makeDeps = (): CliDeps => ({
ensurePortAvailable: vi.fn().mockResolvedValue(undefined),
readEnv: vi.fn().mockReturnValue({
whatsappFrom: "whatsapp:+1555",
whatsappSenderSid: "WW",
}),
ensureBinary: vi.fn().mockResolvedValue(undefined),
ensureFunnel: vi.fn().mockResolvedValue(undefined),
getTailnetHostname: vi.fn().mockResolvedValue("tailnet-host"),
startWebhook: vi.fn().mockResolvedValue({ server: true }),
createClient: vi.fn().mockReturnValue({ client: true }),
findWhatsappSenderSid: vi.fn().mockResolvedValue("SID123"),
updateWebhook: vi.fn().mockResolvedValue(undefined),
});
describe("upCommand", () => {
it("throws on invalid port", async () => {
await expect(() =>
upCommand({ port: "0", path: "/cb" }, makeDeps(), runtime),
).rejects.toThrow("Port must be between 1 and 65535");
});
it("performs dry run and returns mock data", async () => {
runtime.log.mockClear();
const result = await upCommand(
{ port: "42873", path: "/cb", dryRun: true },
makeDeps(),
runtime,
);
expect(runtime.log).toHaveBeenCalledWith(
"[dry-run] would enable funnel on port 42873",
);
expect(result?.publicUrl).toBe("https://dry-run/cb");
expect(result?.senderSid).toBeUndefined();
});
it("enables funnel, starts webhook, and updates Twilio", async () => {
const deps = makeDeps();
const res = await upCommand(
{ port: "42873", path: "/hook", verbose: true },
deps,
runtime,
);
expect(deps.ensureBinary).toHaveBeenCalledWith(
"tailscale",
undefined,
runtime,
);
expect(deps.ensureFunnel).toHaveBeenCalled();
expect(deps.startWebhook).toHaveBeenCalled();
expect(deps.updateWebhook).toHaveBeenCalledWith(
expect.anything(),
"SID123",
"https://tailnet-host/hook",
"POST",
runtime,
);
expect(res?.publicUrl).toBe("https://tailnet-host/hook");
// waiter is returned to keep the process alive in real use.
expect(typeof res?.waiter).toBe("function");
});
});