diff --git a/src/features/mcp-oauth/provider.test.ts b/src/features/mcp-oauth/provider.test.ts index e55ea7540..bc4feec09 100644 --- a/src/features/mcp-oauth/provider.test.ts +++ b/src/features/mcp-oauth/provider.test.ts @@ -2,14 +2,26 @@ import { describe, expect, it, beforeEach, afterEach, mock } from "bun:test" import { createHash, randomBytes } from "node:crypto" import type { OAuthTokenData } from "./storage" -const { - McpOAuthProvider, - generateCodeVerifier, - generateCodeChallenge, - buildAuthorizationUrl, -} = await import(new URL("./provider.ts?real-provider-test", import.meta.url).href) +type ProviderModule = typeof import("./provider") + +async function importFreshProviderModule(): Promise { + return await import(new URL(`./provider.ts?real-provider-test=${Date.now()}-${Math.random()}`, import.meta.url).href) +} describe("McpOAuthProvider", () => { + let McpOAuthProvider: ProviderModule["McpOAuthProvider"] + let generateCodeVerifier: ProviderModule["generateCodeVerifier"] + let generateCodeChallenge: ProviderModule["generateCodeChallenge"] + let buildAuthorizationUrl: ProviderModule["buildAuthorizationUrl"] + + beforeEach(async () => { + const providerModule = await importFreshProviderModule() + McpOAuthProvider = providerModule.McpOAuthProvider + generateCodeVerifier = providerModule.generateCodeVerifier + generateCodeChallenge = providerModule.generateCodeChallenge + buildAuthorizationUrl = providerModule.buildAuthorizationUrl + }) + describe("generateCodeVerifier", () => { it("returns a base64url-encoded 32-byte random string", () => { // given diff --git a/src/hooks/atlas/session-last-agent.sqlite.test.ts b/src/hooks/atlas/session-last-agent.sqlite.test.ts index 074d17cc7..9b2a0eb62 100644 --- a/src/hooks/atlas/session-last-agent.sqlite.test.ts +++ b/src/hooks/atlas/session-last-agent.sqlite.test.ts @@ -1,20 +1,22 @@ const { describe, expect, mock, test, afterAll } = require("bun:test") -mock.module("../../shared/opencode-message-dir", () => ({ - getMessageDir: () => null, -})) - -mock.module("../../shared/opencode-storage-detection", () => ({ - isSqliteBackend: () => true, -})) - -mock.module("../../shared/normalize-sdk-response", () => ({ - normalizeSDKResponse: (response: { data?: TData }, fallback: TData): TData => response.data ?? fallback, -})) - afterAll(() => { mock.restore() }) -const { getLastAgentFromSession } = await import("./session-last-agent") +async function importFreshSessionLastAgentModule() { + mock.module("../../shared/opencode-message-dir", () => ({ + getMessageDir: () => null, + })) + + mock.module("../../shared/opencode-storage-detection", () => ({ + isSqliteBackend: () => true, + })) + + const module = await import(`./session-last-agent?test=${Date.now()}-${Math.random()}`) + mock.restore() + return module +} + +const { getLastAgentFromSession } = await importFreshSessionLastAgentModule() function createMockClient(messages: Array<{ info?: { agent?: string } }>) { return { diff --git a/src/hooks/session-recovery/recover-tool-result-missing.test.ts b/src/hooks/session-recovery/recover-tool-result-missing.test.ts index aabc6e797..15efb41a0 100644 --- a/src/hooks/session-recovery/recover-tool-result-missing.test.ts +++ b/src/hooks/session-recovery/recover-tool-result-missing.test.ts @@ -5,24 +5,25 @@ import type { MessageData } from "./types" let sqliteBackend = false let storedParts: Array<{ type: string; id?: string; callID?: string; [key: string]: unknown }> = [] -mock.module("../../shared/opencode-storage-detection", () => ({ - isSqliteBackend: () => sqliteBackend, -})) - -mock.module("../../shared/normalize-sdk-response", () => ({ - normalizeSDKResponse: (response: { data?: TData }, fallback: TData): TData => response.data ?? fallback, -})) - -mock.module("./storage", () => ({ - readParts: () => storedParts, -})) - afterAll(() => { mock.restore() }) -const { recoverToolResultMissing } = await import("./recover-tool-result-missing") -mock.restore() +async function importFreshRecoverToolResultMissingModule() { + mock.module("../../shared/opencode-storage-detection", () => ({ + isSqliteBackend: () => sqliteBackend, + })) + + mock.module("./storage", () => ({ + readParts: () => storedParts, + })) + + const module = await import(`./recover-tool-result-missing?test=${Date.now()}-${Math.random()}`) + mock.restore() + return module +} + +const { recoverToolResultMissing } = await importFreshRecoverToolResultMissingModule() function createMockClient(messages: MessageData[] = []) { const promptAsync = mock(() => Promise.resolve({})) diff --git a/src/shared/connected-providers-cache.test.ts b/src/shared/connected-providers-cache.test.ts index 85c7ab27b..6572a59cc 100644 --- a/src/shared/connected-providers-cache.test.ts +++ b/src/shared/connected-providers-cache.test.ts @@ -6,11 +6,17 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync import { tmpdir } from "node:os" import { join } from "node:path" -const { createConnectedProvidersCacheStore, findProviderModelMetadata } = await import( - new URL("./connected-providers-cache.ts?real-connected-providers-cache-test", import.meta.url).href -) +type ConnectedProvidersCacheModule = typeof import("./connected-providers-cache") -function createTestCacheContext() { +async function importFreshConnectedProvidersCacheModule(): Promise { + return await import( + new URL(`./connected-providers-cache.ts?real-connected-providers-cache-test=${Date.now()}-${Math.random()}`, import.meta.url).href + ) +} + +function createTestCacheContext( + createConnectedProvidersCacheStore: ConnectedProvidersCacheModule["createConnectedProvidersCacheStore"], +) { const fakeUserCacheRoot = mkdtempSync(join(tmpdir(), "connected-providers-user-cache-")) const testCacheDir = join(fakeUserCacheRoot, "oh-my-opencode") const testCacheStore = createConnectedProvidersCacheStore(() => testCacheDir) @@ -30,7 +36,8 @@ function cleanupTestCacheContext(fakeUserCacheRoot: string): void { describe("updateConnectedProvidersCache", () => { test("extracts models from provider.list().all response", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) try { //#given @@ -87,7 +94,8 @@ describe("updateConnectedProvidersCache", () => { }) test("writes empty models when provider has no models", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) try { //#given @@ -122,7 +130,8 @@ describe("updateConnectedProvidersCache", () => { }) test("writes empty models when all field is missing", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) try { //#given @@ -149,7 +158,8 @@ describe("updateConnectedProvidersCache", () => { }) test("does nothing when client.provider.list is not available", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) try { //#given @@ -167,7 +177,8 @@ describe("updateConnectedProvidersCache", () => { }) test("does not remove unrelated files in the cache directory", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) //#given const realCacheDir = join(fakeUserCacheRoot, "oh-my-opencode") @@ -210,7 +221,11 @@ describe("updateConnectedProvidersCache", () => { }) test("findProviderModelMetadata returns rich cached metadata", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { + createConnectedProvidersCacheStore, + findProviderModelMetadata, + } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) try { //#given @@ -264,7 +279,11 @@ describe("updateConnectedProvidersCache", () => { }) test("keeps normalized fallback ids when raw metadata id is not a string", async () => { - const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext() + const { + createConnectedProvidersCacheStore, + findProviderModelMetadata, + } = await importFreshConnectedProvidersCacheModule() + const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore) try { const mockClient = { diff --git a/src/tools/delegate-task/subagent-resolver.test.ts b/src/tools/delegate-task/subagent-resolver.test.ts index 7f87f8531..d03a3d2bf 100644 --- a/src/tools/delegate-task/subagent-resolver.test.ts +++ b/src/tools/delegate-task/subagent-resolver.test.ts @@ -1,11 +1,16 @@ declare const require: (name: string) => any const { describe, test, expect, beforeEach, afterEach, spyOn, mock } = require("bun:test") -import { resolveSubagentExecution } from "./subagent-resolver" import type { DelegateTaskArgs } from "./types" import type { ExecutorContext } from "./executor-types" import * as logger from "../../shared/logger" import * as connectedProvidersCache from "../../shared/connected-providers-cache" +type SubagentResolverModule = typeof import("./subagent-resolver") + +async function importFreshSubagentResolverModule(): Promise { + return await import(`./subagent-resolver?test=${Date.now()}-${Math.random()}`) +} + function createBaseArgs(overrides?: Partial): DelegateTaskArgs { return { description: "Run review", @@ -37,10 +42,12 @@ function createExecutorContext( describe("resolveSubagentExecution", () => { let logSpy: ReturnType | undefined + let resolveSubagentExecution: SubagentResolverModule["resolveSubagentExecution"] - beforeEach(() => { + beforeEach(async () => { mock.restore() logSpy = spyOn(logger, "log").mockImplementation(() => {}) + ;({ resolveSubagentExecution } = await importFreshSubagentResolverModule()) }) afterEach(() => { @@ -648,9 +655,11 @@ describe("resolveSubagentExecution", () => { describe("resolveSubagentExecution - agent name sanitization", () => { let logSpy: ReturnType | undefined + let resolveSubagentExecution: SubagentResolverModule["resolveSubagentExecution"] - beforeEach(() => { + beforeEach(async () => { logSpy = spyOn(logger, "log").mockImplementation(() => {}) + ;({ resolveSubagentExecution } = await importFreshSubagentResolverModule()) }) afterEach(() => {