test: fresh-import remaining contamination-prone modules
This commit is contained in:
@@ -2,14 +2,26 @@ import { describe, expect, it, beforeEach, afterEach, mock } from "bun:test"
|
|||||||
import { createHash, randomBytes } from "node:crypto"
|
import { createHash, randomBytes } from "node:crypto"
|
||||||
import type { OAuthTokenData } from "./storage"
|
import type { OAuthTokenData } from "./storage"
|
||||||
|
|
||||||
const {
|
type ProviderModule = typeof import("./provider")
|
||||||
McpOAuthProvider,
|
|
||||||
generateCodeVerifier,
|
async function importFreshProviderModule(): Promise<ProviderModule> {
|
||||||
generateCodeChallenge,
|
return await import(new URL(`./provider.ts?real-provider-test=${Date.now()}-${Math.random()}`, import.meta.url).href)
|
||||||
buildAuthorizationUrl,
|
}
|
||||||
} = await import(new URL("./provider.ts?real-provider-test", import.meta.url).href)
|
|
||||||
|
|
||||||
describe("McpOAuthProvider", () => {
|
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", () => {
|
describe("generateCodeVerifier", () => {
|
||||||
it("returns a base64url-encoded 32-byte random string", () => {
|
it("returns a base64url-encoded 32-byte random string", () => {
|
||||||
// given
|
// given
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
const { describe, expect, mock, test, afterAll } = require("bun:test")
|
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: <TData>(response: { data?: TData }, fallback: TData): TData => response.data ?? fallback,
|
|
||||||
}))
|
|
||||||
|
|
||||||
afterAll(() => { mock.restore() })
|
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 } }>) {
|
function createMockClient(messages: Array<{ info?: { agent?: string } }>) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -5,24 +5,25 @@ import type { MessageData } from "./types"
|
|||||||
let sqliteBackend = false
|
let sqliteBackend = false
|
||||||
let storedParts: Array<{ type: string; id?: string; callID?: string; [key: string]: unknown }> = []
|
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: <TData>(response: { data?: TData }, fallback: TData): TData => response.data ?? fallback,
|
|
||||||
}))
|
|
||||||
|
|
||||||
mock.module("./storage", () => ({
|
|
||||||
readParts: () => storedParts,
|
|
||||||
}))
|
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
mock.restore()
|
mock.restore()
|
||||||
})
|
})
|
||||||
|
|
||||||
const { recoverToolResultMissing } = await import("./recover-tool-result-missing")
|
async function importFreshRecoverToolResultMissingModule() {
|
||||||
mock.restore()
|
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[] = []) {
|
function createMockClient(messages: MessageData[] = []) {
|
||||||
const promptAsync = mock(() => Promise.resolve({}))
|
const promptAsync = mock(() => Promise.resolve({}))
|
||||||
|
|||||||
@@ -6,11 +6,17 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync
|
|||||||
import { tmpdir } from "node:os"
|
import { tmpdir } from "node:os"
|
||||||
import { join } from "node:path"
|
import { join } from "node:path"
|
||||||
|
|
||||||
const { createConnectedProvidersCacheStore, findProviderModelMetadata } = await import(
|
type ConnectedProvidersCacheModule = typeof import("./connected-providers-cache")
|
||||||
new URL("./connected-providers-cache.ts?real-connected-providers-cache-test", import.meta.url).href
|
|
||||||
)
|
|
||||||
|
|
||||||
function createTestCacheContext() {
|
async function importFreshConnectedProvidersCacheModule(): Promise<ConnectedProvidersCacheModule> {
|
||||||
|
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 fakeUserCacheRoot = mkdtempSync(join(tmpdir(), "connected-providers-user-cache-"))
|
||||||
const testCacheDir = join(fakeUserCacheRoot, "oh-my-opencode")
|
const testCacheDir = join(fakeUserCacheRoot, "oh-my-opencode")
|
||||||
const testCacheStore = createConnectedProvidersCacheStore(() => testCacheDir)
|
const testCacheStore = createConnectedProvidersCacheStore(() => testCacheDir)
|
||||||
@@ -30,7 +36,8 @@ function cleanupTestCacheContext(fakeUserCacheRoot: string): void {
|
|||||||
|
|
||||||
describe("updateConnectedProvidersCache", () => {
|
describe("updateConnectedProvidersCache", () => {
|
||||||
test("extracts models from provider.list().all response", async () => {
|
test("extracts models from provider.list().all response", async () => {
|
||||||
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext()
|
const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule()
|
||||||
|
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//#given
|
//#given
|
||||||
@@ -87,7 +94,8 @@ describe("updateConnectedProvidersCache", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("writes empty models when provider has no models", async () => {
|
test("writes empty models when provider has no models", async () => {
|
||||||
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext()
|
const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule()
|
||||||
|
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//#given
|
//#given
|
||||||
@@ -122,7 +130,8 @@ describe("updateConnectedProvidersCache", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("writes empty models when all field is missing", async () => {
|
test("writes empty models when all field is missing", async () => {
|
||||||
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext()
|
const { createConnectedProvidersCacheStore } = await importFreshConnectedProvidersCacheModule()
|
||||||
|
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//#given
|
//#given
|
||||||
@@ -149,7 +158,8 @@ describe("updateConnectedProvidersCache", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("does nothing when client.provider.list is not available", async () => {
|
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 {
|
try {
|
||||||
//#given
|
//#given
|
||||||
@@ -167,7 +177,8 @@ describe("updateConnectedProvidersCache", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("does not remove unrelated files in the cache directory", async () => {
|
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
|
//#given
|
||||||
const realCacheDir = join(fakeUserCacheRoot, "oh-my-opencode")
|
const realCacheDir = join(fakeUserCacheRoot, "oh-my-opencode")
|
||||||
@@ -210,7 +221,11 @@ describe("updateConnectedProvidersCache", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("findProviderModelMetadata returns rich cached metadata", async () => {
|
test("findProviderModelMetadata returns rich cached metadata", async () => {
|
||||||
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext()
|
const {
|
||||||
|
createConnectedProvidersCacheStore,
|
||||||
|
findProviderModelMetadata,
|
||||||
|
} = await importFreshConnectedProvidersCacheModule()
|
||||||
|
const { testCacheStore, fakeUserCacheRoot } = createTestCacheContext(createConnectedProvidersCacheStore)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//#given
|
//#given
|
||||||
@@ -264,7 +279,11 @@ describe("updateConnectedProvidersCache", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("keeps normalized fallback ids when raw metadata id is not a string", async () => {
|
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 {
|
try {
|
||||||
const mockClient = {
|
const mockClient = {
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
declare const require: (name: string) => any
|
declare const require: (name: string) => any
|
||||||
const { describe, test, expect, beforeEach, afterEach, spyOn, mock } = require("bun:test")
|
const { describe, test, expect, beforeEach, afterEach, spyOn, mock } = require("bun:test")
|
||||||
import { resolveSubagentExecution } from "./subagent-resolver"
|
|
||||||
import type { DelegateTaskArgs } from "./types"
|
import type { DelegateTaskArgs } from "./types"
|
||||||
import type { ExecutorContext } from "./executor-types"
|
import type { ExecutorContext } from "./executor-types"
|
||||||
import * as logger from "../../shared/logger"
|
import * as logger from "../../shared/logger"
|
||||||
import * as connectedProvidersCache from "../../shared/connected-providers-cache"
|
import * as connectedProvidersCache from "../../shared/connected-providers-cache"
|
||||||
|
|
||||||
|
type SubagentResolverModule = typeof import("./subagent-resolver")
|
||||||
|
|
||||||
|
async function importFreshSubagentResolverModule(): Promise<SubagentResolverModule> {
|
||||||
|
return await import(`./subagent-resolver?test=${Date.now()}-${Math.random()}`)
|
||||||
|
}
|
||||||
|
|
||||||
function createBaseArgs(overrides?: Partial<DelegateTaskArgs>): DelegateTaskArgs {
|
function createBaseArgs(overrides?: Partial<DelegateTaskArgs>): DelegateTaskArgs {
|
||||||
return {
|
return {
|
||||||
description: "Run review",
|
description: "Run review",
|
||||||
@@ -37,10 +42,12 @@ function createExecutorContext(
|
|||||||
|
|
||||||
describe("resolveSubagentExecution", () => {
|
describe("resolveSubagentExecution", () => {
|
||||||
let logSpy: ReturnType<typeof spyOn> | undefined
|
let logSpy: ReturnType<typeof spyOn> | undefined
|
||||||
|
let resolveSubagentExecution: SubagentResolverModule["resolveSubagentExecution"]
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
mock.restore()
|
mock.restore()
|
||||||
logSpy = spyOn(logger, "log").mockImplementation(() => {})
|
logSpy = spyOn(logger, "log").mockImplementation(() => {})
|
||||||
|
;({ resolveSubagentExecution } = await importFreshSubagentResolverModule())
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -648,9 +655,11 @@ describe("resolveSubagentExecution", () => {
|
|||||||
|
|
||||||
describe("resolveSubagentExecution - agent name sanitization", () => {
|
describe("resolveSubagentExecution - agent name sanitization", () => {
|
||||||
let logSpy: ReturnType<typeof spyOn> | undefined
|
let logSpy: ReturnType<typeof spyOn> | undefined
|
||||||
|
let resolveSubagentExecution: SubagentResolverModule["resolveSubagentExecution"]
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
logSpy = spyOn(logger, "log").mockImplementation(() => {})
|
logSpy = spyOn(logger, "log").mockImplementation(() => {})
|
||||||
|
;({ resolveSubagentExecution } = await importFreshSubagentResolverModule())
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user