diff --git a/src/acp/control-plane/manager.test.ts b/src/acp/control-plane/manager.test.ts index c87858a18cd..d527bbe0845 100644 --- a/src/acp/control-plane/manager.test.ts +++ b/src/acp/control-plane/manager.test.ts @@ -33,8 +33,8 @@ vi.mock("../runtime/registry.js", async (importOriginal) => { }; }); -const { AcpSessionManager } = await import("./manager.js"); -const { AcpRuntimeError } = await import("../runtime/errors.js"); +let AcpSessionManager: typeof import("./manager.js").AcpSessionManager; +let AcpRuntimeError: typeof import("../runtime/errors.js").AcpRuntimeError; const baseCfg = { acp: { @@ -149,7 +149,10 @@ function extractRuntimeOptionsFromUpserts(): Array { - beforeEach(() => { + beforeEach(async () => { + vi.resetModules(); + ({ AcpSessionManager } = await import("./manager.js")); + ({ AcpRuntimeError } = await import("../runtime/errors.js")); vi.useRealTimers(); hoisted.listAcpSessionEntriesMock.mockReset().mockResolvedValue([]); hoisted.readAcpSessionEntryMock.mockReset(); diff --git a/src/acp/persistent-bindings.test.ts b/src/acp/persistent-bindings.test.ts index a98d319cbdd..27564626e2f 100644 --- a/src/acp/persistent-bindings.test.ts +++ b/src/acp/persistent-bindings.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import { parseFeishuConversationId } from "../../extensions/feishu/src/conversation-id.js"; import { resolveAgentWorkspaceDir } from "../agents/agent-scope.js"; import type { ChannelConfiguredBindingProvider, ChannelPlugin } from "../channels/plugins/types.js"; @@ -6,7 +6,6 @@ import type { OpenClawConfig } from "../config/config.js"; import { setActivePluginRegistry } from "../plugins/runtime.js"; import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js"; import { parseTelegramTopicConversation } from "./conversation-id.js"; -import * as persistentBindingsResolveModule from "./persistent-bindings.resolve.js"; import { buildConfiguredAcpSessionKey } from "./persistent-bindings.types.js"; const managerMocks = vi.hoisted(() => ({ resolveSession: vi.fn(), @@ -43,6 +42,10 @@ let lifecycleBindingsModule: Pick< typeof import("./persistent-bindings.lifecycle.js"), "ensureConfiguredAcpBindingSession" | "resetAcpSessionInPlace" >; +let persistentBindingsResolveModule: Pick< + typeof import("./persistent-bindings.resolve.js"), + "resolveConfiguredAcpBindingRecord" | "resolveConfiguredAcpBindingSpecBySessionKey" +>; type ConfiguredBinding = NonNullable[number]; type BindingRecordInput = Parameters< @@ -308,7 +311,10 @@ function mockReadySession(params: { return sessionKey; } -beforeEach(() => { +beforeEach(async () => { + vi.resetModules(); + persistentBindingsResolveModule = await import("./persistent-bindings.resolve.js"); + lifecycleBindingsModule = await import("./persistent-bindings.lifecycle.js"); persistentBindings = { resolveConfiguredAcpBindingRecord: persistentBindingsResolveModule.resolveConfiguredAcpBindingRecord, @@ -346,10 +352,6 @@ beforeEach(() => { sessionMetaMocks.readAcpSessionEntry.mockReset().mockReturnValue(undefined); }); -beforeAll(async () => { - lifecycleBindingsModule = await import("./persistent-bindings.lifecycle.js"); -}); - describe("resolveConfiguredAcpBindingRecord", () => { it("resolves discord channel ACP binding from top-level typed bindings", () => { const cfg = createCfgWithBindings([ diff --git a/src/acp/runtime/session-meta.test.ts b/src/acp/runtime/session-meta.test.ts index f9a0f399f81..ca137e3f2f0 100644 --- a/src/acp/runtime/session-meta.test.ts +++ b/src/acp/runtime/session-meta.test.ts @@ -22,10 +22,12 @@ vi.mock("../../config/sessions.js", async () => { }; }); -const { listAcpSessionEntries } = await import("./session-meta.js"); +let listAcpSessionEntries: typeof import("./session-meta.js").listAcpSessionEntries; describe("listAcpSessionEntries", () => { - beforeEach(() => { + beforeEach(async () => { + vi.resetModules(); + ({ listAcpSessionEntries } = await import("./session-meta.js")); vi.clearAllMocks(); }); diff --git a/src/channels/plugins/actions/actions.test.ts b/src/channels/plugins/actions/actions.test.ts index 42d5224b93b..0752c1e7a4e 100644 --- a/src/channels/plugins/actions/actions.test.ts +++ b/src/channels/plugins/actions/actions.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../../config/config.js"; import type { ChannelMessageActionAdapter } from "../types.js"; @@ -199,15 +199,13 @@ async function expectSlackSendRejected(params: Record, error: R expect(handleSlackAction).not.toHaveBeenCalled(); } -beforeAll(async () => { +beforeEach(async () => { + vi.resetModules(); ({ discordMessageActions } = await import("../../../../extensions/discord/runtime-api.js")); ({ handleDiscordMessageAction } = await import("./discord/handle-action.js")); ({ telegramMessageActions } = await import("../../../../extensions/telegram/runtime-api.js")); ({ signalMessageActions } = await import("../../../../extensions/signal/src/message-actions.js")); ({ createSlackActions } = await import("../../../../extensions/slack/src/channel-actions.js")); -}); - -beforeEach(() => { vi.clearAllMocks(); }); diff --git a/src/cli/command-secret-gateway.test.ts b/src/cli/command-secret-gateway.test.ts index 38cedb54204..f95408fe157 100644 --- a/src/cli/command-secret-gateway.test.ts +++ b/src/cli/command-secret-gateway.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; const callGateway = vi.fn(); @@ -18,11 +18,9 @@ vi.mock("../utils/message-channel.js", () => ({ let resolveCommandSecretRefsViaGateway: typeof import("./command-secret-gateway.js").resolveCommandSecretRefsViaGateway; -beforeAll(async () => { +beforeEach(async () => { + vi.resetModules(); ({ resolveCommandSecretRefsViaGateway } = await import("./command-secret-gateway.js")); -}); - -beforeEach(() => { callGateway.mockReset(); }); diff --git a/src/config/config.web-search-provider.test.ts b/src/config/config.web-search-provider.test.ts index b0319f219eb..eb320e1078e 100644 --- a/src/config/config.web-search-provider.test.ts +++ b/src/config/config.web-search-provider.test.ts @@ -1,5 +1,4 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { validateConfigObjectWithPlugins } from "./config.js"; import { buildWebSearchProviderConfig } from "./test-helpers.js"; vi.mock("../runtime.js", () => ({ @@ -121,8 +120,16 @@ vi.mock("../plugins/web-search-providers.js", () => { }; }); -const { __testing } = await import("../agents/tools/web-search.js"); -const { resolveSearchProvider } = __testing; +let validateConfigObjectWithPlugins: typeof import("./config.js").validateConfigObjectWithPlugins; +let resolveSearchProvider: typeof import("../agents/tools/web-search.js").__testing.resolveSearchProvider; + +beforeEach(async () => { + vi.resetModules(); + ({ validateConfigObjectWithPlugins } = await import("./config.js")); + ({ + __testing: { resolveSearchProvider }, + } = await import("../agents/tools/web-search.js")); +}); function pluginWebSearchApiKey( config: Record | undefined, diff --git a/src/config/sessions/store.pruning.integration.test.ts b/src/config/sessions/store.pruning.integration.test.ts index cba88dda8b9..be63f0652fc 100644 --- a/src/config/sessions/store.pruning.integration.test.ts +++ b/src/config/sessions/store.pruning.integration.test.ts @@ -10,8 +10,10 @@ vi.mock("../config.js", () => ({ loadConfig: vi.fn().mockReturnValue({}), })); -import { loadConfig } from "../config.js"; -import { clearSessionStoreCacheForTest, loadSessionStore, saveSessionStore } from "./store.js"; +let loadConfig: typeof import("../config.js").loadConfig; +let clearSessionStoreCacheForTest: typeof import("./store.js").clearSessionStoreCacheForTest; +let loadSessionStore: typeof import("./store.js").loadSessionStore; +let saveSessionStore: typeof import("./store.js").saveSessionStore; let mockLoadConfig: ReturnType; @@ -79,6 +81,10 @@ describe("Integration: saveSessionStore with pruning", () => { }); beforeEach(async () => { + vi.resetModules(); + ({ loadConfig } = await import("../config.js")); + ({ clearSessionStoreCacheForTest, loadSessionStore, saveSessionStore } = + await import("./store.js")); mockLoadConfig = vi.mocked(loadConfig) as ReturnType; testDir = await createCaseDir("pruning-integ"); storePath = path.join(testDir, "sessions.json"); diff --git a/src/infra/outbound/agent-delivery.test.ts b/src/infra/outbound/agent-delivery.test.ts index abb3bb67d16..f31fb34006e 100644 --- a/src/infra/outbound/agent-delivery.test.ts +++ b/src/infra/outbound/agent-delivery.test.ts @@ -70,9 +70,12 @@ vi.mock("./targets.js", () => ({ })); import type { OpenClawConfig } from "../../config/config.js"; -import { resolveAgentDeliveryPlan, resolveAgentOutboundTarget } from "./agent-delivery.js"; +let resolveAgentDeliveryPlan: typeof import("./agent-delivery.js").resolveAgentDeliveryPlan; +let resolveAgentOutboundTarget: typeof import("./agent-delivery.js").resolveAgentOutboundTarget; -beforeEach(() => { +beforeEach(async () => { + vi.resetModules(); + ({ resolveAgentDeliveryPlan, resolveAgentOutboundTarget } = await import("./agent-delivery.js")); mocks.resolveOutboundTarget.mockClear(); mocks.resolveSessionDeliveryTarget.mockClear(); }); diff --git a/src/infra/outbound/deliver.lifecycle.test.ts b/src/infra/outbound/deliver.lifecycle.test.ts index dd32b1648d8..c8ce22b826b 100644 --- a/src/infra/outbound/deliver.lifecycle.test.ts +++ b/src/infra/outbound/deliver.lifecycle.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; @@ -77,11 +77,9 @@ function expectSuccessfulWhatsAppInternalHookPayload( } describe("deliverOutboundPayloads lifecycle", () => { - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); ({ deliverOutboundPayloads } = await import("./deliver.js")); - }); - - beforeEach(() => { resetDeliverTestState(); resetDeliverTestMocks({ includeSessionMocks: true }); }); diff --git a/src/infra/outbound/deliver.test.ts b/src/infra/outbound/deliver.test.ts index 2f97906e892..d2373480103 100644 --- a/src/infra/outbound/deliver.test.ts +++ b/src/infra/outbound/deliver.test.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { markdownToSignalTextChunks } from "../../../extensions/signal/src/format.js"; import { signalOutbound, @@ -7,7 +7,6 @@ import { whatsappOutbound, } from "../../../test/channel-outbounds.js"; import type { OpenClawConfig } from "../../config/config.js"; -import { STATE_DIR } from "../../config/paths.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; import { withEnvAsync } from "../../test-utils/env.js"; @@ -201,11 +200,9 @@ function expectSuccessfulWhatsAppInternalHookPayload( } describe("deliverOutboundPayloads", () => { - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); ({ deliverOutboundPayloads, normalizeOutboundPayloads } = await import("./deliver.js")); - }); - - beforeEach(() => { setActivePluginRegistry(defaultRegistry); mocks.appendAssistantMessageToSessionTranscript.mockClear(); hookMocks.runner.hasHooks.mockClear(); @@ -454,14 +451,19 @@ describe("deliverOutboundPayloads", () => { payload: { text: "hi", mediaUrl: "file:///tmp/f.png" }, }); + const sendOpts = sendTelegram.mock.calls[0]?.[2] as { mediaLocalRoots?: string[] } | undefined; expect(sendTelegram).toHaveBeenCalledWith( "123", "hi", expect.objectContaining({ mediaUrl: "file:///tmp/f.png", - mediaLocalRoots: expect.arrayContaining([path.join(STATE_DIR, "workspace-work")]), }), ); + expect( + sendOpts?.mediaLocalRoots?.some((root) => + root.endsWith(path.join(".openclaw", "workspace-work")), + ), + ).toBe(true); }); it("includes OpenClaw tmp root in telegram mediaLocalRoots", async () => { diff --git a/src/infra/outbound/message-action-runner.media.test.ts b/src/infra/outbound/message-action-runner.media.test.ts index 9665e44f558..293dfffca69 100644 --- a/src/infra/outbound/message-action-runner.media.test.ts +++ b/src/infra/outbound/message-action-runner.media.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { jsonResult } from "../../agents/tools/common.js"; import type { ChannelPlugin } from "../../channels/plugins/types.js"; import type { OpenClawConfig } from "../../config/config.js"; @@ -117,12 +117,10 @@ const slackPlugin: ChannelPlugin = { }; describe("runMessageAction media behavior", () => { - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); ({ runMessageAction } = await import("./message-action-runner.js")); ({ loadWebMedia } = await import("../../media/web-media.js")); - }); - - beforeEach(() => { vi.clearAllMocks(); }); diff --git a/src/infra/outbound/message.channels.test.ts b/src/infra/outbound/message.channels.test.ts index 0e99a7af2b7..6167c3c250c 100644 --- a/src/infra/outbound/message.channels.test.ts +++ b/src/infra/outbound/message.channels.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { ChannelOutboundAdapter, ChannelPlugin } from "../../channels/plugins/types.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; import { createMSTeamsTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; @@ -19,11 +19,9 @@ vi.mock("../../gateway/call.js", () => ({ let sendMessage: typeof import("./message.js").sendMessage; let sendPoll: typeof import("./message.js").sendPoll; -beforeAll(async () => { +beforeEach(async () => { + vi.resetModules(); ({ sendMessage, sendPoll } = await import("./message.js")); -}); - -beforeEach(() => { callGatewayMock.mockClear(); setRegistry(emptyRegistry); }); diff --git a/src/media/fetch.test.ts b/src/media/fetch.test.ts index ea0044a1c8b..9b06bff7b2d 100644 --- a/src/media/fetch.test.ts +++ b/src/media/fetch.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; const fetchWithSsrFGuardMock = vi.hoisted(() => vi.fn()); @@ -67,11 +67,9 @@ describe("fetchRemoteMedia", () => { const redactedTelegramToken = `${telegramToken.slice(0, 6)}…${telegramToken.slice(-4)}`; const telegramFileUrl = `https://api.telegram.org/file/bot${telegramToken}/photos/1.jpg`; - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); ({ fetchRemoteMedia } = await import("./fetch.js")); - }); - - beforeEach(() => { vi.useRealTimers(); fetchWithSsrFGuardMock.mockReset().mockImplementation(async (paramsUnknown: unknown) => { const params = paramsUnknown as { diff --git a/src/memory/manager.atomic-reindex.test.ts b/src/memory/manager.atomic-reindex.test.ts index ae92c4a4d2d..3954df1ce90 100644 --- a/src/memory/manager.atomic-reindex.test.ts +++ b/src/memory/manager.atomic-reindex.test.ts @@ -24,14 +24,15 @@ describe("memory manager atomic reindex", () => { beforeAll(async () => { fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-mem-atomic-")); + }); + + beforeEach(async () => { + vi.resetModules(); const embeddingMocks = await import("./embedding.test-mocks.js"); embedBatch = embeddingMocks.getEmbedBatchMock(); resetEmbeddingMocks = embeddingMocks.resetEmbeddingMocks; ({ getRequiredMemoryIndexManager } = await import("./test-manager-helpers.js")); ({ closeAllMemorySearchManagers } = await import("./index.js")); - }); - - beforeEach(async () => { vi.stubEnv("OPENCLAW_TEST_MEMORY_UNSAFE_REINDEX", "0"); resetEmbeddingMocks(); shouldFail = false; diff --git a/src/memory/manager.get-concurrency.test.ts b/src/memory/manager.get-concurrency.test.ts index 87ab3394a58..113306c5e7a 100644 --- a/src/memory/manager.get-concurrency.test.ts +++ b/src/memory/manager.get-concurrency.test.ts @@ -2,7 +2,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { setTimeout as sleep } from "node:timers/promises"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import "./test-runtime-mocks.js"; import type { MemoryIndexManager } from "./index.js"; @@ -42,13 +42,11 @@ let RawMemoryIndexManager: ManagerModule["MemoryIndexManager"]; describe("memory manager cache hydration", () => { let workspaceDir = ""; - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); ({ getMemorySearchManager, closeAllMemorySearchManagers } = await import("./index.js")); ({ closeAllMemoryIndexManagers, MemoryIndexManager: RawMemoryIndexManager } = await import("./manager.js")); - }); - - beforeEach(async () => { vi.clearAllMocks(); workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-mem-concurrent-")); await fs.mkdir(path.join(workspaceDir, "memory"), { recursive: true }); diff --git a/src/memory/manager.mistral-provider.test.ts b/src/memory/manager.mistral-provider.test.ts index ceb369330be..828c857d3dc 100644 --- a/src/memory/manager.mistral-provider.test.ts +++ b/src/memory/manager.mistral-provider.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import { DEFAULT_OLLAMA_EMBEDDING_MODEL } from "./embeddings-ollama.js"; import type { @@ -68,11 +68,9 @@ describe("memory manager mistral provider wiring", () => { let indexPath = ""; let manager: MemoryIndexManager | null = null; - beforeAll(async () => { - ({ getMemorySearchManager, closeAllMemorySearchManagers } = await import("./index.js")); - }); - beforeEach(async () => { + vi.resetModules(); + ({ getMemorySearchManager, closeAllMemorySearchManagers } = await import("./index.js")); vi.clearAllMocks(); createEmbeddingProviderMock.mockReset(); workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-memory-mistral-")); diff --git a/src/memory/manager.vector-dedupe.test.ts b/src/memory/manager.vector-dedupe.test.ts index d41dda1d750..1fbc034ad5e 100644 --- a/src/memory/manager.vector-dedupe.test.ts +++ b/src/memory/manager.vector-dedupe.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import type { MemoryIndexManager } from "./index.js"; @@ -45,13 +45,11 @@ describe("memory vector dedupe", () => { manager = null; } - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); ({ buildFileEntry } = await import("./internal.js")); ({ createMemoryManagerOrThrow } = await import("./test-manager.js")); ({ closeAllMemorySearchManagers } = await import("./index.js")); - }); - - beforeEach(async () => { workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-mem-")); indexPath = path.join(workspaceDir, "index.sqlite"); await seedMemoryWorkspace(workspaceDir); diff --git a/src/memory/manager.watcher-config.test.ts b/src/memory/manager.watcher-config.test.ts index 4dd26d43102..531ef4d6e2e 100644 --- a/src/memory/manager.watcher-config.test.ts +++ b/src/memory/manager.watcher-config.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import type { MemorySearchConfig } from "../config/types.tools.js"; import type { MemoryIndexManager } from "./index.js"; @@ -44,11 +44,9 @@ describe("memory watcher config", () => { let workspaceDir = ""; let extraDir = ""; - beforeAll(async () => { - ({ getMemorySearchManager, closeAllMemorySearchManagers } = await import("./index.js")); - }); - beforeEach(async () => { + vi.resetModules(); + ({ getMemorySearchManager, closeAllMemorySearchManagers } = await import("./index.js")); vi.clearAllMocks(); }); diff --git a/src/plugins/contracts/discovery.contract.test.ts b/src/plugins/contracts/discovery.contract.test.ts index 77606c8dcf9..546bcbe25ff 100644 --- a/src/plugins/contracts/discovery.contract.test.ts +++ b/src/plugins/contracts/discovery.contract.test.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { AuthProfileStore } from "../../agents/auth-profiles/types.js"; import { QWEN_OAUTH_MARKER } from "../../agents/model-auth-markers.js"; import type { ModelDefinitionConfig } from "../../config/types.models.js"; @@ -113,7 +113,8 @@ function runCatalog(params: { } describe("provider discovery contract", () => { - beforeAll(async () => { + beforeEach(async () => { + vi.resetModules(); vi.doMock("openclaw/plugin-sdk/agent-runtime", async () => { // Import the direct source module, not the mocked subpath, so bundled // provider helpers still see the full agent-runtime surface. @@ -201,9 +202,6 @@ describe("provider discovery contract", () => { registerProviders(cloudflareAiGatewayPlugin), "cloudflare-ai-gateway", ); - }); - - beforeEach(() => { setRuntimeAuthStore(); }); diff --git a/src/secrets/runtime-web-tools.test.ts b/src/secrets/runtime-web-tools.test.ts index d4e13194620..23ac0a6079c 100644 --- a/src/secrets/runtime-web-tools.test.ts +++ b/src/secrets/runtime-web-tools.test.ts @@ -1,11 +1,6 @@ import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; -import * as bundledWebSearchProviders from "../plugins/web-search-providers.js"; -import * as runtimeWebSearchProviders from "../plugins/web-search-providers.runtime.js"; -import * as secretResolve from "./resolve.js"; -import { createResolverContext } from "./runtime-shared.js"; -import { resolveRuntimeWebTools } from "./runtime-web-tools.js"; type ProviderUnderTest = "brave" | "gemini" | "grok" | "kimi" | "perplexity" | "duckduckgo"; @@ -22,6 +17,12 @@ const mockedModuleIds = [ "../plugins/web-search-providers.runtime.js", ] as const; +let bundledWebSearchProviders: typeof import("../plugins/web-search-providers.js"); +let runtimeWebSearchProviders: typeof import("../plugins/web-search-providers.runtime.js"); +let secretResolve: typeof import("./resolve.js"); +let createResolverContext: typeof import("./runtime-shared.js").createResolverContext; +let resolveRuntimeWebTools: typeof import("./runtime-web-tools.js").resolveRuntimeWebTools; + vi.mock("../plugins/web-search-providers.js", () => ({ resolveBundledPluginWebSearchProviders: resolveBundledPluginWebSearchProvidersMock, })); @@ -194,7 +195,13 @@ function expectInactiveFirecrawlSecretRef(params: { } describe("runtime web tools resolution", () => { - beforeEach(() => { + beforeEach(async () => { + vi.resetModules(); + bundledWebSearchProviders = await import("../plugins/web-search-providers.js"); + runtimeWebSearchProviders = await import("../plugins/web-search-providers.runtime.js"); + secretResolve = await import("./resolve.js"); + ({ createResolverContext } = await import("./runtime-shared.js")); + ({ resolveRuntimeWebTools } = await import("./runtime-web-tools.js")); vi.mocked(bundledWebSearchProviders.resolveBundledPluginWebSearchProviders).mockClear(); vi.mocked(runtimeWebSearchProviders.resolvePluginWebSearchProviders).mockClear(); }); diff --git a/src/secrets/runtime.coverage.test.ts b/src/secrets/runtime.coverage.test.ts index 74c0e966651..1a04e5b97c2 100644 --- a/src/secrets/runtime.coverage.test.ts +++ b/src/secrets/runtime.coverage.test.ts @@ -1,9 +1,8 @@ -import { afterAll, afterEach, describe, expect, it, vi } from "vitest"; +import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { AuthProfileStore } from "../agents/auth-profiles.js"; import type { OpenClawConfig } from "../config/config.js"; import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; import { getPath, setPathCreateStrict } from "./path-utils.js"; -import { clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } from "./runtime.js"; import { listSecretTargetRegistryEntries } from "./target-registry.js"; type SecretRegistryEntry = ReturnType[number]; @@ -19,6 +18,9 @@ const mockedModuleIds = [ "../plugins/web-search-providers.runtime.js", ] as const; +let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot; +let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot; + vi.mock("../plugins/web-search-providers.js", () => ({ resolveBundledPluginWebSearchProviders: resolveBundledPluginWebSearchProvidersMock, })); @@ -251,6 +253,11 @@ describe("secrets runtime target coverage", () => { resolvePluginWebSearchProvidersMock.mockReset(); }); + beforeEach(async () => { + vi.resetModules(); + ({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js")); + }); + afterAll(() => { for (const id of mockedModuleIds) { vi.doUnmock(id); diff --git a/src/secrets/runtime.test.ts b/src/secrets/runtime.test.ts index 166e16ec238..13ab208da68 100644 --- a/src/secrets/runtime.test.ts +++ b/src/secrets/runtime.test.ts @@ -3,14 +3,8 @@ import os from "node:os"; import path from "node:path"; import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { AuthProfileStore } from "../agents/auth-profiles.js"; -import { clearConfigCache, type OpenClawConfig } from "../config/config.js"; +import type { OpenClawConfig } from "../config/config.js"; import type { PluginWebSearchProviderEntry } from "../plugins/types.js"; -import { - activateSecretsRuntimeSnapshot, - clearSecretsRuntimeSnapshot, - getActiveRuntimeWebToolsMetadata, - prepareSecretsRuntimeSnapshot, -} from "./runtime.js"; type WebProviderUnderTest = "brave" | "gemini" | "grok" | "kimi" | "perplexity" | "firecrawl"; @@ -103,6 +97,12 @@ function buildTestWebSearchProviders(): PluginWebSearchProviderEntry[] { const OPENAI_ENV_KEY_REF = { source: "env", provider: "default", id: "OPENAI_API_KEY" } as const; +let clearConfigCache: typeof import("../config/config.js").clearConfigCache; +let activateSecretsRuntimeSnapshot: typeof import("./runtime.js").activateSecretsRuntimeSnapshot; +let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot; +let getActiveRuntimeWebToolsMetadata: typeof import("./runtime.js").getActiveRuntimeWebToolsMetadata; +let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot; + function createOpenAiFileModelsConfig(): NonNullable { return { providers: { @@ -123,7 +123,15 @@ function loadAuthStoreWithProfiles(profiles: AuthProfileStore["profiles"]): Auth } describe("secrets runtime snapshot", () => { - beforeEach(() => { + beforeEach(async () => { + vi.resetModules(); + ({ clearConfigCache } = await import("../config/config.js")); + ({ + activateSecretsRuntimeSnapshot, + clearSecretsRuntimeSnapshot, + getActiveRuntimeWebToolsMetadata, + prepareSecretsRuntimeSnapshot, + } = await import("./runtime.js")); resolveBundledPluginWebSearchProvidersMock.mockReset(); resolveBundledPluginWebSearchProvidersMock.mockReturnValue(buildTestWebSearchProviders()); resolvePluginWebSearchProvidersMock.mockReset();