fix(tests): fix globalThis.fetch pollution between test files

- install.test.ts: save and restore globalThis.fetch in beforeEach/afterEach
  to prevent leaking a mock fetch (without .preconnect) into subsequent test files
- provider.test.ts: guard against originalFetch missing .preconnect when captured
  from a leaked mock (defensive null-safe binding)
- discovery.test.ts: add writable:true to all Object.defineProperty fetch assignments
  so downstream plain assignments (globalThis.fetch = ...) are not silently ignored

Root cause: install.test.ts set globalThis.fetch = mock(...) inside test bodies
without restoring it, leaving a mock fetch (no .preconnect method) that caused
provider.test.ts refresh tests to throw TypeError at the fetchMock construction
This commit is contained in:
YeonGyu-Kim
2026-04-06 18:20:28 +09:00
parent e62d5d7a22
commit 0de7453349
3 changed files with 12 additions and 9 deletions
+3
View File
@@ -13,6 +13,7 @@ const mockConsoleError = mock(() => {})
describe("install CLI - binary check behavior", () => {
let tempDir: string
let originalEnv: string | undefined
let originalFetch: typeof globalThis.fetch
let isOpenCodeInstalledSpy: ReturnType<typeof spyOn>
let getOpenCodeVersionSpy: ReturnType<typeof spyOn>
@@ -20,6 +21,7 @@ describe("install CLI - binary check behavior", () => {
// given temporary config directory
tempDir = join(tmpdir(), `omo-test-${Date.now()}-${Math.random().toString(36).slice(2)}`)
mkdirSync(tempDir, { recursive: true })
originalFetch = globalThis.fetch
originalEnv = process.env.OPENCODE_CONFIG_DIR
process.env.OPENCODE_CONFIG_DIR = tempDir
@@ -46,6 +48,7 @@ describe("install CLI - binary check behavior", () => {
isOpenCodeInstalledSpy?.mockRestore()
getOpenCodeVersionSpy?.mockRestore()
globalThis.fetch = originalFetch
})
test("non-TUI mode: should show warning but continue when OpenCode binary not found", async () => {
+8 -8
View File
@@ -9,7 +9,7 @@ describe("discoverOAuthServerMetadata", () => {
})
afterEach(() => {
Object.defineProperty(globalThis, "fetch", { value: originalFetch, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: originalFetch, configurable: true, writable: true })
})
test("returns endpoints from PRM + AS discovery", () => {
@@ -37,7 +37,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
return discoverOAuthServerMetadata(resource).then((result) => {
@@ -75,7 +75,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
return discoverOAuthServerMetadata(resource).then((result) => {
@@ -118,7 +118,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
return discoverOAuthServerMetadata(resource).then((result) => {
@@ -144,7 +144,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
const result = discoverOAuthServerMetadata(resource)
@@ -165,7 +165,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
const result = discoverOAuthServerMetadata(resource)
@@ -192,7 +192,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
const result = discoverOAuthServerMetadata(resource)
@@ -225,7 +225,7 @@ describe("discoverOAuthServerMetadata", () => {
}
return new Response("not found", { status: 404 })
}
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true })
Object.defineProperty(globalThis, "fetch", { value: fetchMock, configurable: true, writable: true })
// when
return discoverOAuthServerMetadata(resource)
+1 -1
View File
@@ -287,7 +287,7 @@ describe("McpOAuthProvider", () => {
})
const fetchMock = Object.assign(
async (...args: Parameters<typeof fetch>): ReturnType<typeof fetch> => fetchStub(...args),
{ preconnect: originalFetch.preconnect.bind(originalFetch) },
{ preconnect: originalFetch?.preconnect?.bind(originalFetch) ?? (() => {}) },
) satisfies typeof fetch
globalThis.fetch = fetchMock