mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 02:10:21 +00:00
test(config): align snapshot fixtures and isolation
This commit is contained in:
@@ -62,7 +62,7 @@ describe("config io write", () => {
|
||||
}
|
||||
|
||||
async function writeTokenAuthAndReadConfig(params: {
|
||||
io: { writeConfigFile: (config: Record<string, unknown>) => Promise<void> };
|
||||
io: { writeConfigFile: (config: Record<string, unknown>) => Promise<unknown> };
|
||||
snapshot: { config: Record<string, unknown> };
|
||||
configPath: string;
|
||||
}) {
|
||||
|
||||
58
src/config/mutate.test.ts
Normal file
58
src/config/mutate.test.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
ConfigMutationConflictError,
|
||||
mutateConfigFile,
|
||||
readSourceConfigSnapshot,
|
||||
replaceConfigFile,
|
||||
} from "./config.js";
|
||||
import { withTempHome } from "./home-env.test-harness.js";
|
||||
|
||||
describe("config mutate helpers", () => {
|
||||
it("mutates source config with optimistic hash protection", async () => {
|
||||
await withTempHome("openclaw-config-mutate-source-", async (home) => {
|
||||
const configPath = path.join(home, ".openclaw", "openclaw.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(configPath, `${JSON.stringify({ gateway: { port: 18789 } }, null, 2)}\n`);
|
||||
|
||||
const snapshot = await readSourceConfigSnapshot();
|
||||
await mutateConfigFile({
|
||||
baseHash: snapshot.hash,
|
||||
base: "source",
|
||||
mutate(draft) {
|
||||
draft.gateway = {
|
||||
...draft.gateway,
|
||||
auth: { mode: "token" },
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const persisted = JSON.parse(await fs.readFile(configPath, "utf8")) as {
|
||||
gateway?: { port?: number; auth?: unknown };
|
||||
};
|
||||
expect(persisted.gateway).toEqual({
|
||||
port: 18789,
|
||||
auth: { mode: "token" },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects stale replace attempts when the base hash changed", async () => {
|
||||
await withTempHome("openclaw-config-replace-conflict-", async (home) => {
|
||||
const configPath = path.join(home, ".openclaw", "openclaw.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(configPath, `${JSON.stringify({ gateway: { port: 18789 } }, null, 2)}\n`);
|
||||
|
||||
const snapshot = await readSourceConfigSnapshot();
|
||||
await fs.writeFile(configPath, `${JSON.stringify({ gateway: { port: 19001 } }, null, 2)}\n`);
|
||||
|
||||
await expect(
|
||||
replaceConfigFile({
|
||||
baseHash: snapshot.hash,
|
||||
nextConfig: { gateway: { port: 19002 } },
|
||||
}),
|
||||
).rejects.toBeInstanceOf(ConfigMutationConflictError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,7 +5,9 @@ import type { ConfigFileSnapshot } from "./types.openclaw.js";
|
||||
|
||||
export type TestSnapshot<TConfig extends Record<string, unknown>> = ConfigFileSnapshot & {
|
||||
parsed: TConfig;
|
||||
sourceConfig: TConfig;
|
||||
resolved: TConfig;
|
||||
runtimeConfig: TConfig;
|
||||
config: TConfig;
|
||||
};
|
||||
|
||||
@@ -18,8 +20,10 @@ export function makeSnapshot<TConfig extends Record<string, unknown>>(
|
||||
exists: true,
|
||||
raw: raw ?? JSON.stringify(config),
|
||||
parsed: config,
|
||||
sourceConfig: config as ConfigFileSnapshot["sourceConfig"],
|
||||
resolved: config as ConfigFileSnapshot["resolved"],
|
||||
valid: true,
|
||||
runtimeConfig: config as ConfigFileSnapshot["runtimeConfig"],
|
||||
config: config as ConfigFileSnapshot["config"],
|
||||
hash: "abc123",
|
||||
issues: [],
|
||||
|
||||
@@ -401,8 +401,10 @@ describe("redactConfigSnapshot", () => {
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: null,
|
||||
sourceConfig: {} as ConfigFileSnapshot["sourceConfig"],
|
||||
resolved: {} as ConfigFileSnapshot["resolved"],
|
||||
valid: false,
|
||||
runtimeConfig: {} as ConfigFileSnapshot["runtimeConfig"],
|
||||
config: {} as ConfigFileSnapshot["config"],
|
||||
issues: [],
|
||||
warnings: [],
|
||||
@@ -419,8 +421,12 @@ describe("redactConfigSnapshot", () => {
|
||||
exists: true,
|
||||
raw: '{ "gateway": { "auth": { "token": "leaky-secret" } } }',
|
||||
parsed: { gateway: { auth: { token: "leaky-secret" } } },
|
||||
sourceConfig: {
|
||||
gateway: { auth: { token: "leaky-secret" } },
|
||||
} as ConfigFileSnapshot["sourceConfig"],
|
||||
resolved: { gateway: { auth: { token: "leaky-secret" } } } as ConfigFileSnapshot["resolved"],
|
||||
valid: false,
|
||||
runtimeConfig: {} as ConfigFileSnapshot["runtimeConfig"],
|
||||
config: {} as ConfigFileSnapshot["config"],
|
||||
issues: [{ path: "", message: "invalid config" }],
|
||||
warnings: [],
|
||||
|
||||
@@ -25,8 +25,10 @@ function makeSnapshot(params: { valid: boolean; config?: OpenClawConfig }): Conf
|
||||
raw: "{}",
|
||||
parsed: params.config ?? {},
|
||||
resolved: params.config ?? {},
|
||||
sourceConfig: params.config ?? {},
|
||||
valid: params.valid,
|
||||
config: params.config ?? {},
|
||||
runtimeConfig: params.config ?? {},
|
||||
issues: params.valid ? [] : [{ path: "gateway", message: "invalid" }],
|
||||
warnings: [],
|
||||
legacyIssues: [],
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
|
||||
import type { OpenClawConfig } from "./config.js";
|
||||
import { resetConfigRuntimeState, type OpenClawConfig } from "./config.js";
|
||||
|
||||
export async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
|
||||
return withTempHomeBase(fn, { prefix: "openclaw-config-" });
|
||||
resetConfigRuntimeState();
|
||||
try {
|
||||
return await withTempHomeBase(fn, { prefix: "openclaw-config-" });
|
||||
} finally {
|
||||
resetConfigRuntimeState();
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeOpenClawConfig(home: string, config: unknown): Promise<string> {
|
||||
|
||||
Reference in New Issue
Block a user