import fs from "node:fs" ;
import path from "node:path" ;
import { describe, expect, it } from "vitest" ;
import { withTempDir } from "../test-helpers/temp-dir.js" ;
import {
autoMigrateLegacyStateDir,
resetAutoMigrateLegacyStateDirForTest,
} from "./state-migrations.js" ;
async function withStateDirFixture(run: (root: string) => Promise<void >): Promise<void > {
try {
await withTempDir({ prefix: "openclaw-state-dir-" }, async (root) => {
await run(root);
});
} finally {
resetAutoMigrateLegacyStateDirForTest();
}
}
describe("legacy state dir auto-migration" , () => {
it("skips a legacy symlinked state dir when it points outside supported legacy roots" , async () => {
await withStateDirFixture(async (root) => {
const legacySymlink = path.join(root, ".clawdbot" );
const legacyDir = path.join(root, "legacy-state-source" );
fs.mkdirSync(legacyDir, { recursive: true });
fs.writeFileSync(path.join(legacyDir, "marker.txt" ), "ok" , "utf-8" );
const dirLinkType = process.platform === "win32" ? "junction" : "dir" ;
fs.symlinkSync(legacyDir, legacySymlink, dirLinkType);
const result = await autoMigrateLegacyStateDir({
env: {} as NodeJS.ProcessEnv,
homedir: () => root,
});
expect(result.migrated).toBe(false );
expect(result.warnings).toEqual([
`Legacy state dir is a symlink (${legacySymlink} → ${legacyDir}); skipping auto-migration.`,
]);
expect(fs.readFileSync(path.join(root, "legacy-state-source" , "marker.txt" ), "utf-8" )).toBe(
"ok" ,
);
expect(fs.readFileSync(path.join(root, ".clawdbot" , "marker.txt" ), "utf-8" )).toBe("ok" );
});
});
it("skips state-dir migration when OPENCLAW_STATE_DIR is explicitly set" , async () => {
await withStateDirFixture(async (root) => {
const legacyDir = path.join(root, ".clawdbot" );
fs.mkdirSync(legacyDir, { recursive: true });
const result = await autoMigrateLegacyStateDir({
env: { OPENCLAW_STATE_DIR: path.join(root, "custom-state" ) } as NodeJS.ProcessEnv,
homedir: () => root,
});
expect(result).toEqual({
migrated: false ,
skipped: true ,
changes: [],
warnings: [],
});
expect(fs.existsSync(legacyDir)).toBe(true );
});
});
it("only runs once per process until reset" , async () => {
await withStateDirFixture(async (root) => {
const legacyDir = path.join(root, ".clawdbot" );
fs.mkdirSync(legacyDir, { recursive: true });
fs.writeFileSync(path.join(legacyDir, "marker.txt" ), "ok" , "utf-8" );
const first = await autoMigrateLegacyStateDir({
env: {} as NodeJS.ProcessEnv,
homedir: () => root,
});
const second = await autoMigrateLegacyStateDir({
env: {} as NodeJS.ProcessEnv,
homedir: () => root,
});
expect(first.migrated).toBe(true );
expect(second).toEqual({
migrated: false ,
skipped: true ,
changes: [],
warnings: [],
});
});
});
});
Messung V0.5 in Prozent C=91 H=88 G=89
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-06)
¤
*© Formatika GbR, Deutschland