Files
openclaw/src/wizard/setup.migration-import.test.ts
Peter Steinberger c7e7ac2728 refactor: remove expired plugin compatibility surfaces (#111451)
* docs(secrets): remove retired web credential paths

* refactor(web): remove retired provider compatibility paths

* refactor(providers): delete retired compatibility routes

* refactor(secrets): remove retired credential aliases

* refactor(plugin-sdk): delete retired compatibility surfaces

* docs(plugin-sdk): remove retired migration guidance

* chore(plugin-sdk): refresh rebased surface budgets

* chore(plugin-sdk): refresh API removal baseline

* refactor(compat): migrate retired internal callers

* chore(plugin-sdk): refresh current-main baselines

* test(config): migrate plugin-owned secret assertions

* test(gateway): narrow plugin secret refs

* fix(plugin-sdk): preserve private boundary type identity

* chore(compat): remove stale sweep references

* chore(lint): lower max-lines budget

* refactor(secrets): remove unused web helper

* build(plugin-sdk): drop removed compat entries

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): use Linux API baseline hash

* fix(plugin-sdk): preserve private bundled build entries

* fix(plugin-sdk): package private runtime facades

* fix(plugins): preserve external credential contracts
2026-07-19 11:04:48 -07:00

150 lines
5.0 KiB
TypeScript

// Setup migration import tests cover importing existing config into onboarding.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeAll, describe, expect, it } from "vitest";
import { listSetupMigrationOptions } from "./setup.migration-import.js";
import {
assertFreshSetupMigrationTarget,
inspectSetupMigrationFreshness,
preserveSetupMigrationSecurityAcknowledgement,
} from "./setup.migration-snapshot.js";
const tempRoots = new Set<string>();
async function makeTempRoot() {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-setup-migration-"));
tempRoots.add(root);
return root;
}
async function writeFile(filePath: string, content: string) {
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, content, "utf8");
}
describe("setup migration import freshness", () => {
afterEach(async () => {
for (const root of tempRoots) {
await fs.rm(root, { force: true, recursive: true });
}
tempRoots.clear();
});
it("allows empty config and empty target directories", async () => {
const root = await makeTempRoot();
const result = await inspectSetupMigrationFreshness({
baseConfig: {},
stateDir: path.join(root, "state"),
workspaceDir: path.join(root, "workspace"),
});
expect(result).toEqual({ fresh: true, reasons: [] });
});
it("allows the first-launch security acknowledgement before import", async () => {
const root = await makeTempRoot();
const result = await inspectSetupMigrationFreshness({
baseConfig: {
wizard: { securityAcknowledgedAt: "2026-06-30T00:00:00.000Z" },
},
stateDir: path.join(root, "state"),
workspaceDir: path.join(root, "workspace"),
});
expect(result).toEqual({ fresh: true, reasons: [] });
});
it("preserves the first-launch acknowledgement across the lock-time config reread", () => {
expect(
preserveSetupMigrationSecurityAcknowledgement(
{},
{ wizard: { securityAcknowledgedAt: "2026-06-30T00:00:00.000Z" } },
),
).toEqual({ wizard: { securityAcknowledgedAt: "2026-06-30T00:00:00.000Z" } });
});
it("rejects other wizard config during import freshness checks", async () => {
const root = await makeTempRoot();
const result = await inspectSetupMigrationFreshness({
baseConfig: {
wizard: {
securityAcknowledgedAt: "2026-06-30T00:00:00.000Z",
lastRunMode: "local",
},
},
stateDir: path.join(root, "state"),
workspaceDir: path.join(root, "workspace"),
});
expect(result.fresh).toBe(false);
expect(result.reasons).toEqual(["existing config values are loaded"]);
});
it("rejects existing config, workspace files, and state", async () => {
const root = await makeTempRoot();
const stateDir = path.join(root, "state");
const workspaceDir = path.join(root, "workspace");
await writeFile(path.join(workspaceDir, "MEMORY.md"), "existing memory\n");
await writeFile(path.join(stateDir, "agents", "main", "agent", "auth-profiles.json"), "{}\n");
const result = await inspectSetupMigrationFreshness({
baseConfig: { gateway: { port: 3131 } },
stateDir,
workspaceDir,
});
expect(result.fresh).toBe(false);
expect(result.reasons).toEqual([
"existing config values are loaded",
"workspace MEMORY.md exists",
"state agents/ exists",
]);
expect(() => assertFreshSetupMigrationTarget(result)).toThrow(
"Migration import during onboarding requires a fresh OpenClaw setup.",
);
});
});
describe("setup migration import options", () => {
let initialOptions: Awaited<ReturnType<typeof listSetupMigrationOptions>>;
beforeAll(async () => {
initialOptions = await listSetupMigrationOptions({
baseConfig: {},
detections: [],
});
});
it("offers bundled manifest migration providers before plugin activation", () => {
expect(initialOptions).toEqual(
expect.arrayContaining([
expect.objectContaining({ providerId: "codex", label: "Codex" }),
expect.objectContaining({ providerId: "claude", label: "Claude" }),
expect.objectContaining({ providerId: "hermes", label: "Hermes" }),
]),
);
});
it("offers official installable Codex when bundled plugins are unavailable", async () => {
const previousDisableBundled = process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS;
process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS = "1";
try {
const options = await listSetupMigrationOptions({
baseConfig: {},
detections: [],
});
expect(options).toEqual(
expect.arrayContaining([expect.objectContaining({ providerId: "codex", label: "Codex" })]),
);
} finally {
if (previousDisableBundled === undefined) {
delete process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS;
} else {
process.env.OPENCLAW_DISABLE_BUNDLED_PLUGINS = previousDisableBundled;
}
}
});
});