From a6adc5f4f1411d6d018833c4e223f49c694e896f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 20:40:54 +0100 Subject: [PATCH] test(gateway): mock runtime config io imports --- src/gateway/server-chat.agent-events.test.ts | 4 +- src/gateway/server-session-key.test.ts | 2 +- .../server-startup-config.recovery.test.ts | 42 ++++++++++++++----- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/gateway/server-chat.agent-events.test.ts b/src/gateway/server-chat.agent-events.test.ts index 2772e3d6772..1eeb74ece64 100644 --- a/src/gateway/server-chat.agent-events.test.ts +++ b/src/gateway/server-chat.agent-events.test.ts @@ -8,7 +8,7 @@ vi.mock("./server-chat.persist-session-lifecycle.runtime.js", () => ({ persistGatewaySessionLifecycleEventMock(...args), })); -vi.mock("../config/config.js", () => ({ +vi.mock("../config/io.js", () => ({ getRuntimeConfig: vi.fn(() => ({})), })); @@ -24,7 +24,7 @@ vi.mock("./server-chat.load-gateway-session-row.runtime.js", () => ({ loadGatewaySessionRow: vi.fn(), })); -import { getRuntimeConfig } from "../config/config.js"; +import { getRuntimeConfig } from "../config/io.js"; import { resolveHeartbeatVisibility } from "../infra/heartbeat-visibility.js"; import { createAgentEventHandler, diff --git a/src/gateway/server-session-key.test.ts b/src/gateway/server-session-key.test.ts index 81423fcd4ee..be39eb318b0 100644 --- a/src/gateway/server-session-key.test.ts +++ b/src/gateway/server-session-key.test.ts @@ -7,7 +7,7 @@ const hoisted = vi.hoisted(() => ({ loadCombinedSessionStoreForGatewayMock: vi.fn(), })); -vi.mock("../config/config.js", () => ({ +vi.mock("../config/io.js", () => ({ getRuntimeConfig: () => hoisted.loadConfigMock(), })); diff --git a/src/gateway/server-startup-config.recovery.test.ts b/src/gateway/server-startup-config.recovery.test.ts index cdf33526347..d7b7263afd2 100644 --- a/src/gateway/server-startup-config.recovery.test.ts +++ b/src/gateway/server-startup-config.recovery.test.ts @@ -10,6 +10,9 @@ const applyPluginAutoEnable = vi.hoisted(() => autoEnabledReasons: {} as Record, })), ); +const configMocks = vi.hoisted(() => ({ + isNixMode: { value: false }, +})); const pluginManifestRegistry = vi.hoisted(() => ({ plugins: [], diagnostics: [] })); const pluginMetadataSnapshot = vi.hoisted( (): PluginMetadataSnapshot => ({ @@ -52,20 +55,30 @@ const pluginMetadataSnapshot = vi.hoisted( }), ); -vi.mock("../config/config.js", () => ({ - applyConfigOverrides: vi.fn((config: OpenClawConfig) => config), - isNixMode: false, +vi.mock("../config/io.js", () => ({ readConfigFileSnapshot: vi.fn(), readConfigFileSnapshotWithPluginMetadata: vi.fn(), recoverConfigFromLastKnownGood: vi.fn(), recoverConfigFromJsonRootSuffix: vi.fn(), +})); + +vi.mock("../config/paths.js", () => ({ + get isNixMode() { + return configMocks.isNixMode.value; + }, +})); + +vi.mock("../config/runtime-overrides.js", () => ({ + applyConfigOverrides: vi.fn((config: OpenClawConfig) => config), +})); + +vi.mock("../config/recovery-policy.js", () => ({ isPluginLocalInvalidConfigSnapshot: vi.fn((snapshot: ConfigFileSnapshot) => { if (snapshot.valid || snapshot.legacyIssues.length > 0 || snapshot.issues.length === 0) { return false; } return snapshot.issues.every((issue) => issue.path.startsWith("plugins.entries.")); }), - replaceConfigFile: vi.fn(), shouldAttemptLastKnownGoodRecovery: vi.fn((snapshot: ConfigFileSnapshot) => { if (snapshot.valid) { return false; @@ -76,12 +89,18 @@ vi.mock("../config/config.js", () => ({ snapshot.issues.every((issue) => issue.path.startsWith("plugins.entries.")) ); }), +})); + +vi.mock("../config/mutate.js", () => ({ + replaceConfigFile: vi.fn(), +})); + +vi.mock("../config/validation.js", () => ({ validateConfigObjectWithPlugins: vi.fn((config: OpenClawConfig) => ({ ok: true, config, warnings: [], })), - writeConfigFile: vi.fn(), })); vi.mock("../config/plugin-auto-enable.js", () => ({ @@ -93,7 +112,8 @@ vi.mock("./config-recovery-notice.js", () => ({ })); let loadGatewayStartupConfigSnapshot: typeof import("./server-startup-config.js").loadGatewayStartupConfigSnapshot; -let configIo: typeof import("../config/config.js"); +let configIo: typeof import("../config/io.js"); +let configMutate: typeof import("../config/mutate.js"); let recoveryNotice: typeof import("./config-recovery-notice.js"); const configPath = "/tmp/openclaw-startup-recovery.json"; @@ -123,12 +143,14 @@ function buildSnapshot(params: { describe("gateway startup config recovery", () => { beforeAll(async () => { ({ loadGatewayStartupConfigSnapshot } = await import("./server-startup-config.js")); - configIo = await import("../config/config.js"); + configIo = await import("../config/io.js"); + configMutate = await import("../config/mutate.js"); recoveryNotice = await import("./config-recovery-notice.js"); }); beforeEach(() => { vi.clearAllMocks(); + configMocks.isNixMode.value = false; vi.mocked(configIo.readConfigFileSnapshotWithPluginMetadata).mockImplementation(async () => ({ snapshot: await vi.mocked(configIo.readConfigFileSnapshot)(), })); @@ -200,7 +222,7 @@ describe("gateway startup config recovery", () => { env: process.env, manifestRegistry: pluginManifestRegistry, }); - expect(configIo.replaceConfigFile).not.toHaveBeenCalled(); + expect(configMutate.replaceConfigFile).not.toHaveBeenCalled(); expect(log.info).not.toHaveBeenCalled(); }); @@ -291,7 +313,7 @@ describe("gateway startup config recovery", () => { snapshot: legacySnapshot, pluginMetadataSnapshot, }); - vi.mocked(configIo, true).isNixMode = true; + configMocks.isNixMode.value = true; await expect( loadGatewayStartupConfigSnapshot({ @@ -495,7 +517,7 @@ describe("gateway startup config recovery", () => { config.models?.providers?.anthropic, ); expect(configIo.recoverConfigFromLastKnownGood).not.toHaveBeenCalled(); - expect(configIo.writeConfigFile).not.toHaveBeenCalled(); + expect(configMutate.replaceConfigFile).not.toHaveBeenCalled(); expect(log.warn).toHaveBeenCalledWith( 'gateway: skipped model provider openrouter; configured provider api is invalid. Run "openclaw doctor --fix" to repair the config.', );