test: inject setup command side effects

This commit is contained in:
Peter Steinberger
2026-04-10 17:56:56 +01:00
parent fe0f686c92
commit b9981c8ee8
2 changed files with 42 additions and 8 deletions

View File

@@ -4,6 +4,21 @@ import { describe, expect, it, vi } from "vitest";
import { withTempHome } from "../../test/helpers/temp-home.js";
import { setupCommand } from "./setup.js";
function createSetupDeps(home: string) {
const configPath = path.join(home, ".openclaw", "openclaw.json");
return {
ensureAgentWorkspace: vi.fn(async (params?: { dir?: string }) => ({
dir: params?.dir ?? path.join(home, ".openclaw", "workspace"),
})),
mkdir: vi.fn(async () => {}),
resolveSessionTranscriptsDir: vi.fn(() => path.join(home, ".openclaw", "sessions")),
writeConfigFile: vi.fn(async (config: unknown) => {
await fs.mkdir(path.dirname(configPath), { recursive: true });
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
}),
};
}
describe("setupCommand", () => {
it("writes gateway.mode=local on first run", async () => {
await withTempHome(async (home) => {
@@ -12,8 +27,10 @@ describe("setupCommand", () => {
error: vi.fn(),
exit: vi.fn(),
};
const deps = createSetupDeps(home);
const workspace = path.join(home, ".openclaw", "workspace");
await setupCommand(undefined, runtime);
await setupCommand({ workspace }, runtime, deps);
const configPath = path.join(home, ".openclaw", "openclaw.json");
const raw = await fs.readFile(configPath, "utf-8");
@@ -33,6 +50,7 @@ describe("setupCommand", () => {
const configDir = path.join(home, ".openclaw");
const configPath = path.join(configDir, "openclaw.json");
const workspace = path.join(home, "custom-workspace");
const deps = createSetupDeps(home);
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(
@@ -46,7 +64,7 @@ describe("setupCommand", () => {
}),
);
await setupCommand(undefined, runtime);
await setupCommand(undefined, runtime, deps);
const raw = JSON.parse(await fs.readFile(configPath, "utf-8")) as {
agents?: { defaults?: { workspace?: string } };
@@ -67,11 +85,13 @@ describe("setupCommand", () => {
};
const configDir = path.join(home, ".openclaw");
const configPath = path.join(configDir, "openclaw.json");
const deps = createSetupDeps(home);
const workspace = path.join(home, ".openclaw", "workspace");
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(configPath, '"not-an-object"', "utf-8");
await setupCommand(undefined, runtime);
await setupCommand({ workspace }, runtime, deps);
const raw = JSON.parse(await fs.readFile(configPath, "utf-8")) as {
agents?: { defaults?: { workspace?: string } };

View File

@@ -4,7 +4,6 @@ import { z } from "zod";
import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js";
import { type OpenClawConfig, createConfigIO, writeConfigFile } from "../config/config.js";
import { formatConfigPath, logConfigUpdated } from "../config/logging.js";
import { resolveSessionTranscriptsDir } from "../config/sessions.js";
import type { RuntimeEnv } from "../runtime.js";
import { defaultRuntime } from "../runtime.js";
import { shortenHomePath } from "../utils.js";
@@ -12,6 +11,18 @@ import { safeParseWithSchema } from "../utils/zod-parse.js";
const JsonRecordSchema = z.record(z.string(), z.unknown());
type SetupCommandDeps = {
ensureAgentWorkspace?: typeof ensureAgentWorkspace;
mkdir?: (dir: string, options: { recursive: true }) => Promise<unknown>;
resolveSessionTranscriptsDir?: () => string | Promise<string>;
writeConfigFile?: typeof writeConfigFile;
};
async function resolveDefaultSessionTranscriptsDir(): Promise<string> {
const { resolveSessionTranscriptsDir } = await import("../config/sessions.js");
return resolveSessionTranscriptsDir();
}
async function readConfigFileRaw(configPath: string): Promise<{
exists: boolean;
parsed: OpenClawConfig;
@@ -28,6 +39,7 @@ async function readConfigFileRaw(configPath: string): Promise<{
export async function setupCommand(
opts?: { workspace?: string },
runtime: RuntimeEnv = defaultRuntime,
deps: SetupCommandDeps = {},
) {
const desiredWorkspace =
typeof opts?.workspace === "string" && opts.workspace.trim()
@@ -62,7 +74,7 @@ export async function setupCommand(
defaults.workspace !== workspace ||
cfg.gateway?.mode !== next.gateway?.mode
) {
await writeConfigFile(next);
await (deps.writeConfigFile ?? writeConfigFile)(next);
if (!existingRaw.exists) {
runtime.log(`Wrote ${formatConfigPath(configPath)}`);
} else {
@@ -80,13 +92,15 @@ export async function setupCommand(
runtime.log(`Config OK: ${formatConfigPath(configPath)}`);
}
const ws = await ensureAgentWorkspace({
const ws = await (deps.ensureAgentWorkspace ?? ensureAgentWorkspace)({
dir: workspace,
ensureBootstrapFiles: !next.agents?.defaults?.skipBootstrap,
});
runtime.log(`Workspace OK: ${shortenHomePath(ws.dir)}`);
const sessionsDir = resolveSessionTranscriptsDir();
await fs.mkdir(sessionsDir, { recursive: true });
const sessionsDir = await (
deps.resolveSessionTranscriptsDir ?? resolveDefaultSessionTranscriptsDir
)();
await (deps.mkdir ?? fs.mkdir)(sessionsDir, { recursive: true });
runtime.log(`Sessions OK: ${shortenHomePath(sessionsDir)}`);
}