import fs from "node:fs" ;
import path from "node:path" ;
import { describe, expect, it, vi } from "vitest" ;
import { withTempDir } from "./test-helpers/temp-dir.js" ;
import {
ensureDir,
resolveConfigDir,
resolveHomeDir,
resolveUserPath,
shortenHomeInString,
shortenHomePath,
sleep,
} from "./utils.js" ;
describe("ensureDir" , () => {
it("creates nested directory" , async () => {
await withTempDir({ prefix: "openclaw-test-" }, async (tmp) => {
const target = path.join(tmp, "nested" , "dir" );
await ensureDir(target);
expect(fs.existsSync(target)).toBe(true );
});
});
});
describe("sleep" , () => {
it("resolves after delay using fake timers" , async () => {
vi.useFakeTimers();
const promise = sleep(1000 );
vi.advanceTimersByTime(1000 );
await expect(promise).resolves.toBeUndefined();
vi.useRealTimers();
});
});
describe("resolveConfigDir" , () => {
it("prefers ~/.openclaw when legacy dir is missing" , async () => {
await withTempDir({ prefix: "openclaw-config-dir-" }, async (root) => {
const newDir = path.join(root, ".openclaw" );
await fs.promises.mkdir(newDir, { recursive: true });
const resolved = resolveConfigDir({} as NodeJS.ProcessEnv, () => root);
expect(resolved).toBe(newDir);
});
});
it("expands OPENCLAW_STATE_DIR using the provided env" , () => {
const env = {
HOME: "/tmp/openclaw-home" ,
OPENCLAW_STATE_DIR: "~/state" ,
} as NodeJS.ProcessEnv;
expect(resolveConfigDir(env)).toBe(path.resolve("/tmp/openclaw-home" , "state" ));
});
it("falls back to the config file directory when only OPENCLAW_CONFIG_PATH is set" , () => {
const env = {
HOME: "/tmp/openclaw-home" ,
OPENCLAW_CONFIG_PATH: "~/profiles/dev/openclaw.json" ,
} as NodeJS.ProcessEnv;
expect(resolveConfigDir(env)).toBe(path.resolve("/tmp/openclaw-home" , "profiles" , "dev" ));
});
});
describe("resolveHomeDir" , () => {
it("prefers OPENCLAW_HOME over HOME" , () => {
vi.stubEnv("OPENCLAW_HOME" , "/srv/openclaw-home" );
vi.stubEnv("HOME" , "/home/other" );
expect(resolveHomeDir()).toBe(path.resolve("/srv/openclaw-home" ));
vi.unstubAllEnvs();
});
});
describe("shortenHomePath" , () => {
it("uses $OPENCLAW_HOME prefix when OPENCLAW_HOME is set" , () => {
vi.stubEnv("OPENCLAW_HOME" , "/srv/openclaw-home" );
vi.stubEnv("HOME" , "/home/other" );
expect(shortenHomePath(`${path.resolve("/srv/openclaw-home" )}/.openclaw/openclaw.json`)).toBe(
"$OPENCLAW_HOME/.openclaw/openclaw.json" ,
);
vi.unstubAllEnvs();
});
});
describe("shortenHomeInString" , () => {
it("uses $OPENCLAW_HOME replacement when OPENCLAW_HOME is set" , () => {
vi.stubEnv("OPENCLAW_HOME" , "/srv/openclaw-home" );
vi.stubEnv("HOME" , "/home/other" );
expect(
shortenHomeInString(`config: ${path.resolve("/srv/openclaw-home" )}/.openclaw/openclaw.json`),
).toBe("config: $OPENCLAW_HOME/.openclaw/openclaw.json" );
vi.unstubAllEnvs();
});
});
describe("resolveUserPath" , () => {
it("expands ~ to home dir" , () => {
expect(resolveUserPath("~" , {}, () => "/Users/thoffman" )).toBe(path.resolve("/Users/thoffman" ));
});
it("expands ~/ to home dir" , () => {
expect(resolveUserPath("~/openclaw" , {}, () => "/Users/thoffman" )).toBe(
path.resolve("/Users/thoffman" , "openclaw" ),
);
});
it("resolves relative paths" , () => {
expect(resolveUserPath("tmp/dir" )).toBe(path.resolve("tmp/dir" ));
});
it("prefers OPENCLAW_HOME for tilde expansion" , () => {
vi.stubEnv("OPENCLAW_HOME" , "/srv/openclaw-home" );
vi.stubEnv("HOME" , "/home/other" );
expect(resolveUserPath("~/openclaw" )).toBe(path.resolve("/srv/openclaw-home" , "openclaw" ));
vi.unstubAllEnvs();
});
it("uses the provided env for tilde expansion" , () => {
const env = {
HOME: "/tmp/openclaw-home" ,
OPENCLAW_HOME: "/srv/openclaw-home" ,
} as NodeJS.ProcessEnv;
expect(resolveUserPath("~/openclaw" , env)).toBe(path.resolve("/srv/openclaw-home" , "openclaw" ));
});
it("keeps blank paths blank" , () => {
expect(resolveUserPath("" )).toBe("" );
expect(resolveUserPath(" " )).toBe("" );
});
it("returns empty string for undefined/null input" , () => {
expect(resolveUserPath(undefined as unknown as string)).toBe("" );
expect(resolveUserPath(null as unknown as string)).toBe("" );
});
});
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland