Merge pull request #3058 from code-yeongyu/fix/p1-11-remove-as-any-tests

fix(tests): remove as any from new test files
This commit is contained in:
YeonGyu-Kim
2026-04-03 18:30:30 +09:00
committed by GitHub
4 changed files with 189 additions and 103 deletions
+4 -2
View File
@@ -31,6 +31,8 @@ function createPluginConfig(overrides: Partial<OhMyOpenCodeConfig> = {}): OhMyOp
} }
} }
let setAdditionalAllowedMcpEnvVarsSpy: ReturnType<typeof spyOn> | undefined
beforeEach(() => { beforeEach(() => {
spyOn(agents, "createBuiltinAgents" as any).mockResolvedValue({ spyOn(agents, "createBuiltinAgents" as any).mockResolvedValue({
sisyphus: { name: "sisyphus", prompt: "test", mode: "primary" }, sisyphus: { name: "sisyphus", prompt: "test", mode: "primary" },
@@ -57,7 +59,7 @@ beforeEach(() => {
spyOn(agentLoader, "loadProjectAgents" as any).mockReturnValue({}) spyOn(agentLoader, "loadProjectAgents" as any).mockReturnValue({})
spyOn(mcpLoader, "loadMcpConfigs" as any).mockResolvedValue({ servers: {} }) spyOn(mcpLoader, "loadMcpConfigs" as any).mockResolvedValue({ servers: {} })
spyOn(mcpLoader, "setAdditionalAllowedMcpEnvVars").mockImplementation(() => {}) setAdditionalAllowedMcpEnvVarsSpy = spyOn(mcpLoader, "setAdditionalAllowedMcpEnvVars").mockImplementation(() => {})
spyOn(pluginLoader, "loadAllPluginComponents" as any).mockResolvedValue({ spyOn(pluginLoader, "loadAllPluginComponents" as any).mockResolvedValue({
commands: {}, commands: {},
@@ -104,7 +106,7 @@ afterEach(() => {
;(agentLoader.loadUserAgents as any)?.mockRestore?.() ;(agentLoader.loadUserAgents as any)?.mockRestore?.()
;(agentLoader.loadProjectAgents as any)?.mockRestore?.() ;(agentLoader.loadProjectAgents as any)?.mockRestore?.()
;(mcpLoader.loadMcpConfigs as any)?.mockRestore?.() ;(mcpLoader.loadMcpConfigs as any)?.mockRestore?.()
;(mcpLoader.setAdditionalAllowedMcpEnvVars as any)?.mockRestore?.() setAdditionalAllowedMcpEnvVarsSpy?.mockRestore()
;(pluginLoader.loadAllPluginComponents as any)?.mockRestore?.() ;(pluginLoader.loadAllPluginComponents as any)?.mockRestore?.()
;(mcpModule.createBuiltinMcps as any)?.mockRestore?.() ;(mcpModule.createBuiltinMcps as any)?.mockRestore?.()
;(shared.log as any)?.mockRestore?.() ;(shared.log as any)?.mockRestore?.()
+102 -67
View File
@@ -7,6 +7,60 @@ import { clearPendingModelFallback, createModelFallbackHook } from "../hooks/mod
import { getSessionPromptParams, setSessionPromptParams } from "../shared/session-prompt-params-state" import { getSessionPromptParams, setSessionPromptParams } from "../shared/session-prompt-params-state"
type EventInput = { event: { type: string; properties?: unknown } } type EventInput = { event: { type: string; properties?: unknown } }
type EventHandlerArgs = Parameters<typeof createEventHandler>[0]
type EventHandlerInput = Parameters<ReturnType<typeof createEventHandler>>[0]
type ChatMessageHandlerArgs = Parameters<typeof createChatMessageHandler>[0]
function asEventHandlerInput(input: EventInput): EventHandlerInput {
return input as unknown as EventHandlerInput
}
function asEventHandlerContext(ctx: unknown): EventHandlerArgs["ctx"] {
return ctx as unknown as EventHandlerArgs["ctx"]
}
function asChatMessageHandlerContext(ctx: unknown): ChatMessageHandlerArgs["ctx"] {
return ctx as unknown as ChatMessageHandlerArgs["ctx"]
}
function asPluginConfig(config: unknown): EventHandlerArgs["pluginConfig"] {
return config as unknown as EventHandlerArgs["pluginConfig"]
}
function asChatPluginConfig(config: unknown): ChatMessageHandlerArgs["pluginConfig"] {
return config as unknown as ChatMessageHandlerArgs["pluginConfig"]
}
function createEventHandlerManagers(
overrides: Record<string, unknown> = {},
): EventHandlerArgs["managers"] {
return {
...({} as EventHandlerArgs["managers"]),
tmuxSessionManager: {
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
...overrides,
} as unknown as EventHandlerArgs["managers"]
}
function createEventHandlerHooks(
overrides: Record<string, unknown>,
): EventHandlerArgs["hooks"] {
return {
...({} as EventHandlerArgs["hooks"]),
...overrides,
} as unknown as EventHandlerArgs["hooks"]
}
function createChatMessageHandlerHooks(
overrides: Record<string, unknown>,
): ChatMessageHandlerArgs["hooks"] {
return {
...({} as ChatMessageHandlerArgs["hooks"]),
...overrides,
} as unknown as ChatMessageHandlerArgs["hooks"]
}
afterEach(() => { afterEach(() => {
_resetForTesting() _resetForTesting()
@@ -429,12 +483,12 @@ describe("createEventHandler - event forwarding", () => {
const sessionID = "ses_forward_delete_event" const sessionID = "ses_forward_delete_event"
//#when //#when
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.deleted", type: "session.deleted",
properties: { info: { id: sessionID } }, properties: { info: { id: sessionID } },
}, },
} as any) }))
//#then //#then
expect(forwardedEvents.length).toBe(1) expect(forwardedEvents.length).toBe(1)
@@ -471,12 +525,12 @@ describe("createEventHandler - event forwarding", () => {
}) })
//#when //#when
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.deleted", type: "session.deleted",
properties: { info: { id: sessionID } }, properties: { info: { id: sessionID } },
}, },
}) }))
//#then //#then
expect(getSessionPromptParams(sessionID)).toBeUndefined() expect(getSessionPromptParams(sessionID)).toBeUndefined()
@@ -495,7 +549,7 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
const modelFallback = createModelFallbackHook() const modelFallback = createModelFallbackHook()
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx: { ctx: asEventHandlerContext({
directory: "/tmp", directory: "/tmp",
client: { client: {
session: { session: {
@@ -509,41 +563,37 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
}, },
}, },
}, },
} as any, }),
pluginConfig: {} as any, pluginConfig: asPluginConfig({}),
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
}, },
managers: { managers: createEventHandlerManagers({
tmuxSessionManager: {
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
skillMcpManager: { skillMcpManager: {
disconnectSession: async () => {}, disconnectSession: async () => {},
}, },
} as any, }),
hooks: { hooks: createEventHandlerHooks({
modelFallback, modelFallback,
stopContinuationGuard: { isStopped: () => false }, stopContinuationGuard: { isStopped: () => false },
} as any, }),
}) })
const chatMessageHandler = createChatMessageHandler({ const chatMessageHandler = createChatMessageHandler({
ctx: { ctx: asChatMessageHandlerContext({
client: { client: {
tui: { tui: {
showToast: async () => ({}), showToast: async () => ({}),
}, },
}, },
} as any, }),
pluginConfig: {} as any, pluginConfig: asChatPluginConfig({}),
firstMessageVariantGate: { firstMessageVariantGate: {
shouldOverride: () => false, shouldOverride: () => false,
markApplied: () => {}, markApplied: () => {},
}, },
hooks: { hooks: createChatMessageHandlerHooks({
modelFallback, modelFallback,
stopContinuationGuard: null, stopContinuationGuard: null,
keywordDetector: null, keywordDetector: null,
@@ -551,7 +601,7 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
autoSlashCommand: null, autoSlashCommand: null,
startWork: null, startWork: null,
ralphLoop: null, ralphLoop: null,
} as any, }),
}) })
const retryStatus = { const retryStatus = {
@@ -561,7 +611,7 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
next: 476, next: 476,
} as const } as const
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "message.updated", type: "message.updated",
properties: { properties: {
@@ -575,10 +625,10 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
}, },
}, },
}, },
} as any) }))
//#when - first retry key is handled //#when - first retry key is handled
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.status", type: "session.status",
properties: { properties: {
@@ -586,7 +636,7 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
status: retryStatus, status: retryStatus,
}, },
}, },
} as any) }))
const firstOutput = { message: {}, parts: [] as Array<{ type: string; text?: string }> } const firstOutput = { message: {}, parts: [] as Array<{ type: string; text?: string }> }
await chatMessageHandler( await chatMessageHandler(
@@ -599,7 +649,7 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
) )
//#when - session recovers to non-retry idle state //#when - session recovers to non-retry idle state
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.status", type: "session.status",
properties: { properties: {
@@ -607,10 +657,10 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
status: { type: "idle" }, status: { type: "idle" },
}, },
}, },
} as any) }))
//#when - same retry key appears again after recovery //#when - same retry key appears again after recovery
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.status", type: "session.status",
properties: { properties: {
@@ -618,7 +668,7 @@ describe("createEventHandler - retry dedupe lifecycle", () => {
status: retryStatus, status: retryStatus,
}, },
}, },
} as any) }))
//#then //#then
expect(abortCalls).toEqual([sessionID, sessionID]) expect(abortCalls).toEqual([sessionID, sessionID])
@@ -634,7 +684,7 @@ describe("createEventHandler - session recovery compaction", () => {
const callOrder: string[] = [] const callOrder: string[] = []
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx: { ctx: asEventHandlerContext({
directory: "/tmp", directory: "/tmp",
client: { client: {
session: { session: {
@@ -649,29 +699,24 @@ describe("createEventHandler - session recovery compaction", () => {
}, },
}, },
}, },
} as any, }),
pluginConfig: {} as any, pluginConfig: asPluginConfig({}),
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
}, },
managers: { managers: createEventHandlerManagers(),
tmuxSessionManager: { hooks: createEventHandlerHooks({
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
} as any,
hooks: {
sessionRecovery: { sessionRecovery: {
isRecoverableError: () => true, isRecoverableError: () => true,
handleSessionRecovery: async () => true, handleSessionRecovery: async () => true,
}, },
stopContinuationGuard: { isStopped: () => false }, stopContinuationGuard: { isStopped: () => false },
} as any, }),
}) })
//#when //#when
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.error", type: "session.error",
properties: { properties: {
@@ -680,7 +725,7 @@ describe("createEventHandler - session recovery compaction", () => {
error: { name: "Error", message: "tool_result block(s) that are not immediately" }, error: { name: "Error", message: "tool_result block(s) that are not immediately" },
}, },
}, },
} as any) }))
//#then - summarize (compaction) must be called before prompt (continue) //#then - summarize (compaction) must be called before prompt (continue)
expect(callOrder).toEqual(["summarize", "prompt"]) expect(callOrder).toEqual(["summarize", "prompt"])
@@ -693,7 +738,7 @@ describe("createEventHandler - session recovery compaction", () => {
const callOrder: string[] = [] const callOrder: string[] = []
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx: { ctx: asEventHandlerContext({
directory: "/tmp", directory: "/tmp",
client: { client: {
session: { session: {
@@ -708,29 +753,24 @@ describe("createEventHandler - session recovery compaction", () => {
}, },
}, },
}, },
} as any, }),
pluginConfig: {} as any, pluginConfig: asPluginConfig({}),
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
}, },
managers: { managers: createEventHandlerManagers(),
tmuxSessionManager: { hooks: createEventHandlerHooks({
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
} as any,
hooks: {
sessionRecovery: { sessionRecovery: {
isRecoverableError: () => true, isRecoverableError: () => true,
handleSessionRecovery: async () => true, handleSessionRecovery: async () => true,
}, },
stopContinuationGuard: { isStopped: () => false }, stopContinuationGuard: { isStopped: () => false },
} as any, }),
}) })
//#when //#when
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.error", type: "session.error",
properties: { properties: {
@@ -739,7 +779,7 @@ describe("createEventHandler - session recovery compaction", () => {
error: { name: "Error", message: "tool_result block(s) that are not immediately" }, error: { name: "Error", message: "tool_result block(s) that are not immediately" },
}, },
}, },
} as any) }))
//#then - continue is still sent even when compaction fails //#then - continue is still sent even when compaction fails
expect(callOrder).toEqual(["summarize", "prompt"]) expect(callOrder).toEqual(["summarize", "prompt"])
@@ -750,7 +790,7 @@ describe("createEventHandler - session recovery compaction", () => {
const runtimeFallbackCalls: EventInput[] = [] const runtimeFallbackCalls: EventInput[] = []
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx: { ctx: asEventHandlerContext({
directory: "/tmp", directory: "/tmp",
client: { client: {
session: { session: {
@@ -758,19 +798,14 @@ describe("createEventHandler - session recovery compaction", () => {
prompt: async () => ({}), prompt: async () => ({}),
}, },
}, },
} as any, }),
pluginConfig: {} as any, pluginConfig: asPluginConfig({}),
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
}, },
managers: { managers: createEventHandlerManagers(),
tmuxSessionManager: { hooks: createEventHandlerHooks({
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
} as any,
hooks: {
autoUpdateChecker: { autoUpdateChecker: {
event: async () => { event: async () => {
throw new Error("upstream hook failed") throw new Error("upstream hook failed")
@@ -782,13 +817,13 @@ describe("createEventHandler - session recovery compaction", () => {
}, },
}, },
stopContinuationGuard: { isStopped: () => false }, stopContinuationGuard: { isStopped: () => false },
} as any, }),
}) })
//#when //#when
let thrownError: unknown let thrownError: unknown
try { try {
await eventHandler({ await eventHandler(asEventHandlerInput({
event: { event: {
type: "session.error", type: "session.error",
properties: { properties: {
@@ -796,7 +831,7 @@ describe("createEventHandler - session recovery compaction", () => {
error: { name: "Error", message: "retry me" }, error: { name: "Error", message: "retry me" },
}, },
}, },
} as any) }))
} catch (error) { } catch (error) {
thrownError = error thrownError = error
} }
+65 -24
View File
@@ -14,10 +14,55 @@ import { createEventHandler } from "./event"
import { createChatMessageHandler } from "./chat-message" import { createChatMessageHandler } from "./chat-message"
import { createModelFallbackHook } from "../hooks/model-fallback/hook" import { createModelFallbackHook } from "../hooks/model-fallback/hook"
import { createRuntimeFallbackHook } from "../hooks/runtime-fallback" import { createRuntimeFallbackHook } from "../hooks/runtime-fallback"
import type { RuntimeFallbackPluginInput } from "../hooks/runtime-fallback/types"
import { _resetForTesting } from "../features/claude-code-session-state" import { _resetForTesting } from "../features/claude-code-session-state"
import { _resetForTesting as _resetModelFallbackForTesting } from "../hooks/model-fallback/hook" import { _resetForTesting as _resetModelFallbackForTesting } from "../hooks/model-fallback/hook"
import { SessionCategoryRegistry } from "../shared/session-category-registry" import { SessionCategoryRegistry } from "../shared/session-category-registry"
type EventHandlerArgs = Parameters<typeof createEventHandler>[0]
type ChatMessageHandlerArgs = Parameters<typeof createChatMessageHandler>[0]
type HarnessContext = EventHandlerArgs["ctx"] & RuntimeFallbackPluginInput
type HarnessEventInput = Parameters<ReturnType<typeof createHarness>["eventHandler"]>[0]
function asHarnessEventInput(input: unknown): HarnessEventInput {
return input as unknown as HarnessEventInput
}
function asHarnessContext(ctx: unknown): HarnessContext {
return ctx as unknown as HarnessContext
}
function createEventHandlerManagers(
overrides: Record<string, unknown> = {},
): EventHandlerArgs["managers"] {
return {
...({} as EventHandlerArgs["managers"]),
tmuxSessionManager: {
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
...overrides,
} as unknown as EventHandlerArgs["managers"]
}
function createEventHandlerHooks(
overrides: Record<string, unknown>,
): EventHandlerArgs["hooks"] {
return {
...({} as EventHandlerArgs["hooks"]),
...overrides,
} as unknown as EventHandlerArgs["hooks"]
}
function createChatMessageHandlerHooks(
overrides: Record<string, unknown>,
): ChatMessageHandlerArgs["hooks"] {
return {
...({} as ChatMessageHandlerArgs["hooks"]),
...overrides,
} as unknown as ChatMessageHandlerArgs["hooks"]
}
const PRIMARY_MODEL = { const PRIMARY_MODEL = {
providerID: PROVIDER_ID, providerID: PROVIDER_ID,
modelID: "claude-opus-4-6", modelID: "claude-opus-4-6",
@@ -59,7 +104,7 @@ function createPluginConfig(mode: HarnessMode) {
}, },
} }
: {}), : {}),
} } as unknown as EventHandlerArgs["pluginConfig"]
} }
function createHarness(args: { function createHarness(args: {
@@ -72,7 +117,7 @@ function createHarness(args: {
const promptAsyncCalls: PromptAsyncCall[] = [] const promptAsyncCalls: PromptAsyncCall[] = []
const pluginConfig = createPluginConfig(args.mode) const pluginConfig = createPluginConfig(args.mode)
const ctx = { const ctx = asHarnessContext({
directory: "/tmp", directory: "/tmp",
client: { client: {
session: { session: {
@@ -119,7 +164,7 @@ function createHarness(args: {
showToast: async () => ({}), showToast: async () => ({}),
}, },
}, },
} as any })
const hooks: Record<string, unknown> = { const hooks: Record<string, unknown> = {
stopContinuationGuard: null, stopContinuationGuard: null,
@@ -145,38 +190,34 @@ function createHarness(args: {
timeout_seconds: args.sessionTimeoutMs ? 30 : 0, timeout_seconds: args.sessionTimeoutMs ? 30 : 0,
notify_on_fallback: false, notify_on_fallback: false,
}, },
pluginConfig, pluginConfig: pluginConfig as unknown as EventHandlerArgs["pluginConfig"],
...(args.sessionTimeoutMs ? { session_timeout_ms: args.sessionTimeoutMs } : {}), ...(args.sessionTimeoutMs ? { session_timeout_ms: args.sessionTimeoutMs } : {}),
}) })
} }
const eventHandler = createEventHandler({ const eventHandler = createEventHandler({
ctx, ctx,
pluginConfig: pluginConfig as any, pluginConfig: pluginConfig as unknown as EventHandlerArgs["pluginConfig"],
firstMessageVariantGate: { firstMessageVariantGate: {
markSessionCreated: () => {}, markSessionCreated: () => {},
clear: () => {}, clear: () => {},
}, },
managers: { managers: createEventHandlerManagers({
tmuxSessionManager: {
onSessionCreated: async () => {},
onSessionDeleted: async () => {},
},
skillMcpManager: { skillMcpManager: {
disconnectSession: async () => {}, disconnectSession: async () => {},
}, },
} as any, }),
hooks: hooks as any, hooks: createEventHandlerHooks(hooks),
}) })
const chatMessageHandler = createChatMessageHandler({ const chatMessageHandler = createChatMessageHandler({
ctx, ctx,
pluginConfig: pluginConfig as any, pluginConfig: pluginConfig as unknown as ChatMessageHandlerArgs["pluginConfig"],
firstMessageVariantGate: { firstMessageVariantGate: {
shouldOverride: () => false, shouldOverride: () => false,
markApplied: () => {}, markApplied: () => {},
}, },
hooks: hooks as any, hooks: createChatMessageHandlerHooks(hooks),
}) })
return { return {
@@ -192,7 +233,7 @@ async function primeMainSession(
eventHandler: ReturnType<typeof createHarness>["eventHandler"], eventHandler: ReturnType<typeof createHarness>["eventHandler"],
sessionID: string, sessionID: string,
) { ) {
await eventHandler({ await eventHandler(asHarnessEventInput({
event: { event: {
type: "session.created", type: "session.created",
properties: { properties: {
@@ -202,9 +243,9 @@ async function primeMainSession(
}, },
}, },
}, },
}) }))
await eventHandler({ await eventHandler(asHarnessEventInput({
event: { event: {
type: "message.updated", type: "message.updated",
properties: { properties: {
@@ -221,7 +262,7 @@ async function primeMainSession(
}, },
}, },
}, },
}) }))
} }
async function sendNextMessage( async function sendNextMessage(
@@ -241,7 +282,7 @@ async function triggerSessionError(
eventHandler: ReturnType<typeof createHarness>["eventHandler"], eventHandler: ReturnType<typeof createHarness>["eventHandler"],
sessionID: string, sessionID: string,
) { ) {
await eventHandler({ await eventHandler(asHarnessEventInput({
event: { event: {
type: "session.error", type: "session.error",
properties: { properties: {
@@ -256,14 +297,14 @@ async function triggerSessionError(
}, },
}, },
}, },
}) }))
} }
async function triggerSessionStatusRetry( async function triggerSessionStatusRetry(
eventHandler: ReturnType<typeof createHarness>["eventHandler"], eventHandler: ReturnType<typeof createHarness>["eventHandler"],
sessionID: string, sessionID: string,
) { ) {
await eventHandler({ await eventHandler(asHarnessEventInput({
event: { event: {
type: "session.status", type: "session.status",
properties: { properties: {
@@ -279,14 +320,14 @@ async function triggerSessionStatusRetry(
}, },
}, },
}, },
}) }))
} }
async function triggerAssistantMessageError( async function triggerAssistantMessageError(
eventHandler: ReturnType<typeof createHarness>["eventHandler"], eventHandler: ReturnType<typeof createHarness>["eventHandler"],
sessionID: string, sessionID: string,
) { ) {
await eventHandler({ await eventHandler(asHarnessEventInput({
event: { event: {
type: "message.updated", type: "message.updated",
properties: { properties: {
@@ -307,7 +348,7 @@ async function triggerAssistantMessageError(
}, },
}, },
}, },
}) }))
} }
afterEach(() => { afterEach(() => {
+18 -10
View File
@@ -10,6 +10,14 @@ import {
} from "./tmux-utils" } from "./tmux-utils"
import { isInsideTmuxEnvironment } from "./tmux-utils/environment" import { isInsideTmuxEnvironment } from "./tmux-utils/environment"
function createFetchMock(responseFactory: () => Promise<Response>): typeof fetch & ReturnType<typeof mock> {
const fetchMock = mock(async (_input: RequestInfo | URL, _init?: RequestInit) => responseFactory())
const preconnect = globalThis.fetch.preconnect?.bind(globalThis.fetch)
return Object.assign(fetchMock, {
preconnect,
}) as typeof fetch & ReturnType<typeof mock>
}
describe("isInsideTmux", () => { describe("isInsideTmux", () => {
test("returns true when TMUX env is set", () => { test("returns true when TMUX env is set", () => {
// given // given
@@ -66,7 +74,7 @@ describe("isServerRunning", () => {
test("returns true when server responds OK", async () => { test("returns true when server responds OK", async () => {
// given // given
globalThis.fetch = mock(async () => ({ ok: true })) as any globalThis.fetch = createFetchMock(async () => new Response(null, { status: 200 }))
// when // when
const result = await isServerRunning("http://localhost:4096") const result = await isServerRunning("http://localhost:4096")
@@ -77,9 +85,9 @@ describe("isServerRunning", () => {
test("returns false when server not reachable", async () => { test("returns false when server not reachable", async () => {
// given // given
globalThis.fetch = mock(async () => { globalThis.fetch = createFetchMock(async () => {
throw new Error("ECONNREFUSED") throw new Error("ECONNREFUSED")
}) as any })
// when // when
const result = await isServerRunning("http://localhost:4096") const result = await isServerRunning("http://localhost:4096")
@@ -90,7 +98,7 @@ describe("isServerRunning", () => {
test("returns false when fetch returns not ok", async () => { test("returns false when fetch returns not ok", async () => {
// given // given
globalThis.fetch = mock(async () => ({ ok: false })) as any globalThis.fetch = createFetchMock(async () => new Response(null, { status: 500 }))
// when // when
const result = await isServerRunning("http://localhost:4096") const result = await isServerRunning("http://localhost:4096")
@@ -101,7 +109,7 @@ describe("isServerRunning", () => {
test("caches successful result", async () => { test("caches successful result", async () => {
// given // given
const fetchMock = mock(async () => ({ ok: true })) as any const fetchMock = createFetchMock(async () => new Response(null, { status: 200 }))
globalThis.fetch = fetchMock globalThis.fetch = fetchMock
// when // when
@@ -114,9 +122,9 @@ describe("isServerRunning", () => {
test("does not cache failed result", async () => { test("does not cache failed result", async () => {
// given // given
const fetchMock = mock(async () => { const fetchMock = createFetchMock(async () => {
throw new Error("ECONNREFUSED") throw new Error("ECONNREFUSED")
}) as any })
globalThis.fetch = fetchMock globalThis.fetch = fetchMock
// when // when
@@ -129,7 +137,7 @@ describe("isServerRunning", () => {
test("uses different cache for different URLs", async () => { test("uses different cache for different URLs", async () => {
// given // given
const fetchMock = mock(async () => ({ ok: true })) as any const fetchMock = createFetchMock(async () => new Response(null, { status: 200 }))
globalThis.fetch = fetchMock globalThis.fetch = fetchMock
// when // when
@@ -150,7 +158,7 @@ describe("resetServerCheck", () => {
test("allows re-checking after reset", async () => { test("allows re-checking after reset", async () => {
// given // given
const originalFetch = globalThis.fetch const originalFetch = globalThis.fetch
const fetchMock = mock(async () => ({ ok: true })) as any const fetchMock = createFetchMock(async () => new Response(null, { status: 200 }))
globalThis.fetch = fetchMock globalThis.fetch = fetchMock
// when // when
@@ -182,7 +190,7 @@ describe("markServerRunningInProcess", () => {
test("skips HTTP fetch when marked as running in-process", async () => { test("skips HTTP fetch when marked as running in-process", async () => {
// given // given
const fetchMock = mock(async () => ({ ok: true })) as any const fetchMock = createFetchMock(async () => new Response(null, { status: 200 }))
globalThis.fetch = fetchMock globalThis.fetch = fetchMock
markServerRunningInProcess() markServerRunningInProcess()