Files
clawdbot/src/commands/configure.wizard.test.ts
2026-01-16 03:30:56 +00:00

138 lines
3.7 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
const mocks = vi.hoisted(() => ({
clackIntro: vi.fn(),
clackOutro: vi.fn(),
clackSelect: vi.fn(),
clackText: vi.fn(),
clackConfirm: vi.fn(),
readConfigFileSnapshot: vi.fn(),
writeConfigFile: vi.fn(),
resolveGatewayPort: vi.fn(),
ensureControlUiAssetsBuilt: vi.fn(),
createClackPrompter: vi.fn(),
note: vi.fn(),
printWizardHeader: vi.fn(),
probeGatewayReachable: vi.fn(),
waitForGatewayReachable: vi.fn(),
resolveControlUiLinks: vi.fn(),
summarizeExistingConfig: vi.fn(),
}));
vi.mock("@clack/prompts", () => ({
intro: mocks.clackIntro,
outro: mocks.clackOutro,
select: mocks.clackSelect,
text: mocks.clackText,
confirm: mocks.clackConfirm,
}));
vi.mock("../config/config.js", () => ({
CONFIG_PATH_CLAWDBOT: "~/.clawdbot/clawdbot.json",
readConfigFileSnapshot: mocks.readConfigFileSnapshot,
writeConfigFile: mocks.writeConfigFile,
resolveGatewayPort: mocks.resolveGatewayPort,
}));
vi.mock("../infra/control-ui-assets.js", () => ({
ensureControlUiAssetsBuilt: mocks.ensureControlUiAssetsBuilt,
}));
vi.mock("../wizard/clack-prompter.js", () => ({
createClackPrompter: mocks.createClackPrompter,
}));
vi.mock("../terminal/note.js", () => ({
note: mocks.note,
}));
vi.mock("./onboard-helpers.js", () => ({
DEFAULT_WORKSPACE: "~/.clawdbot/workspace",
applyWizardMetadata: (cfg: ClawdbotConfig) => cfg,
ensureWorkspaceAndSessions: vi.fn(),
guardCancel: <T>(value: T) => value,
printWizardHeader: mocks.printWizardHeader,
probeGatewayReachable: mocks.probeGatewayReachable,
resolveControlUiLinks: mocks.resolveControlUiLinks,
summarizeExistingConfig: mocks.summarizeExistingConfig,
waitForGatewayReachable: mocks.waitForGatewayReachable,
}));
vi.mock("./health.js", () => ({
healthCommand: vi.fn(),
}));
vi.mock("./health-format.js", () => ({
formatHealthCheckFailure: vi.fn(),
}));
vi.mock("./configure.gateway.js", () => ({
promptGatewayConfig: vi.fn(),
}));
vi.mock("./configure.gateway-auth.js", () => ({
promptAuthConfig: vi.fn(),
}));
vi.mock("./configure.channels.js", () => ({
removeChannelConfigWizard: vi.fn(),
}));
vi.mock("./configure.daemon.js", () => ({
maybeInstallDaemon: vi.fn(),
}));
vi.mock("./onboard-remote.js", () => ({
promptRemoteGatewayConfig: vi.fn(),
}));
vi.mock("./onboard-skills.js", () => ({
setupSkills: vi.fn(),
}));
vi.mock("./onboard-channels.js", () => ({
setupChannels: vi.fn(),
}));
import { runConfigureWizard } from "./configure.wizard.js";
describe("runConfigureWizard", () => {
it("persists gateway.mode=local when only the run mode is selected", async () => {
mocks.readConfigFileSnapshot.mockResolvedValue({
exists: false,
valid: true,
config: {},
issues: [],
});
mocks.resolveGatewayPort.mockReturnValue(18789);
mocks.probeGatewayReachable.mockResolvedValue({ ok: false });
mocks.resolveControlUiLinks.mockReturnValue({ wsUrl: "ws://127.0.0.1:18789" });
mocks.summarizeExistingConfig.mockReturnValue("");
mocks.createClackPrompter.mockReturnValue({});
const selectQueue = ["local", "__continue"];
mocks.clackSelect.mockImplementation(async () => selectQueue.shift());
mocks.clackIntro.mockResolvedValue(undefined);
mocks.clackOutro.mockResolvedValue(undefined);
mocks.clackText.mockResolvedValue("");
mocks.clackConfirm.mockResolvedValue(false);
await runConfigureWizard(
{ command: "configure" },
{
log: vi.fn(),
error: vi.fn(),
exit: vi.fn(),
},
);
expect(mocks.writeConfigFile).toHaveBeenCalledWith(
expect.objectContaining({
gateway: expect.objectContaining({ mode: "local" }),
}),
);
});
});