test: isolate recovery hook mocks from full suite
This commit is contained in:
@@ -1,81 +1,11 @@
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, mock, test } from "bun:test"
|
||||
import type { PluginInput } from "@opencode-ai/plugin"
|
||||
import * as originalExecutor from "./executor"
|
||||
import * as originalParser from "./parser"
|
||||
import * as originalLogger from "../../shared/logger"
|
||||
|
||||
const executeCompactMock = mock(async () => {})
|
||||
const getLastAssistantMock = mock(async () => ({
|
||||
info: {
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-sonnet-4-6",
|
||||
},
|
||||
hasContent: true,
|
||||
}))
|
||||
const parseAnthropicTokenLimitErrorMock = mock(() => ({
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-sonnet-4-6",
|
||||
}))
|
||||
|
||||
mock.module("./executor", () => ({
|
||||
executeCompact: executeCompactMock,
|
||||
getLastAssistant: getLastAssistantMock,
|
||||
}))
|
||||
|
||||
mock.module("./parser", () => ({
|
||||
parseAnthropicTokenLimitError: parseAnthropicTokenLimitErrorMock,
|
||||
}))
|
||||
|
||||
mock.module("../../shared/logger", () => ({
|
||||
log: () => {},
|
||||
}))
|
||||
|
||||
afterAll(() => {
|
||||
mock.module("./executor", () => originalExecutor)
|
||||
mock.module("./parser", () => originalParser)
|
||||
mock.module("../../shared/logger", () => originalLogger)
|
||||
})
|
||||
|
||||
function createMockContext(): PluginInput {
|
||||
return {
|
||||
client: {
|
||||
session: {
|
||||
messages: mock(() => Promise.resolve({ data: [] })),
|
||||
},
|
||||
tui: {
|
||||
showToast: mock(() => Promise.resolve()),
|
||||
},
|
||||
},
|
||||
directory: "/tmp",
|
||||
} as PluginInput
|
||||
}
|
||||
|
||||
function setupDelayedTimeoutMocks(): {
|
||||
restore: () => void
|
||||
getClearTimeoutCalls: () => Array<ReturnType<typeof setTimeout>>
|
||||
} {
|
||||
const originalSetTimeout = globalThis.setTimeout
|
||||
const originalClearTimeout = globalThis.clearTimeout
|
||||
const clearTimeoutCalls: Array<ReturnType<typeof setTimeout>> = []
|
||||
let timeoutCounter = 0
|
||||
|
||||
globalThis.setTimeout = ((_: () => void, _delay?: number) => {
|
||||
timeoutCounter += 1
|
||||
return timeoutCounter as ReturnType<typeof setTimeout>
|
||||
}) as typeof setTimeout
|
||||
|
||||
globalThis.clearTimeout = ((timeoutID: ReturnType<typeof setTimeout>) => {
|
||||
clearTimeoutCalls.push(timeoutID)
|
||||
}) as typeof clearTimeout
|
||||
|
||||
return {
|
||||
restore: () => {
|
||||
globalThis.setTimeout = originalSetTimeout
|
||||
globalThis.clearTimeout = originalClearTimeout
|
||||
},
|
||||
getClearTimeoutCalls: () => clearTimeoutCalls,
|
||||
}
|
||||
}
|
||||
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"
|
||||
import {
|
||||
createRecoveryHook,
|
||||
executeCompactMock,
|
||||
getLastAssistantMock,
|
||||
parseAnthropicTokenLimitErrorMock,
|
||||
setupDelayedTimeoutMocks,
|
||||
} from "./recovery-hook.test-support"
|
||||
|
||||
describe("createAnthropicContextWindowLimitRecoveryHook", () => {
|
||||
beforeEach(() => {
|
||||
@@ -90,9 +20,12 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => {
|
||||
|
||||
test("cancels pending timer when session.idle handles compaction first", async () => {
|
||||
//#given
|
||||
const { restore, getClearTimeoutCalls } = setupDelayedTimeoutMocks()
|
||||
const { createAnthropicContextWindowLimitRecoveryHook } = await import("./recovery-hook")
|
||||
const hook = createAnthropicContextWindowLimitRecoveryHook(createMockContext())
|
||||
const { restore, getClearTimeoutCalls, getScheduledTimeouts } = setupDelayedTimeoutMocks()
|
||||
let compactedSessionID: unknown
|
||||
executeCompactMock.mockImplementationOnce(async (...args: unknown[]) => {
|
||||
compactedSessionID = args[0]
|
||||
})
|
||||
const hook = createRecoveryHook()
|
||||
|
||||
try {
|
||||
//#when
|
||||
@@ -111,9 +44,9 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => {
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(getClearTimeoutCalls()).toEqual([1 as ReturnType<typeof setTimeout>])
|
||||
expect(getClearTimeoutCalls()).toEqual([getScheduledTimeouts()[0]])
|
||||
expect(executeCompactMock).toHaveBeenCalledTimes(1)
|
||||
expect(executeCompactMock.mock.calls[0]?.[0]).toBe("session-race")
|
||||
expect(compactedSessionID).toBe("session-race")
|
||||
} finally {
|
||||
restore()
|
||||
}
|
||||
@@ -121,7 +54,11 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => {
|
||||
|
||||
test("does not treat empty summary assistant messages as successful compaction", async () => {
|
||||
//#given
|
||||
const { restore, getClearTimeoutCalls } = setupDelayedTimeoutMocks()
|
||||
const { restore, getClearTimeoutCalls, getScheduledTimeouts } = setupDelayedTimeoutMocks()
|
||||
let compactedSessionID: unknown
|
||||
executeCompactMock.mockImplementationOnce(async (...args: unknown[]) => {
|
||||
compactedSessionID = args[0]
|
||||
})
|
||||
getLastAssistantMock.mockResolvedValueOnce({
|
||||
info: {
|
||||
summary: true,
|
||||
@@ -130,8 +67,7 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => {
|
||||
},
|
||||
hasContent: false,
|
||||
})
|
||||
const { createAnthropicContextWindowLimitRecoveryHook } = await import("./recovery-hook")
|
||||
const hook = createAnthropicContextWindowLimitRecoveryHook(createMockContext())
|
||||
const hook = createRecoveryHook()
|
||||
|
||||
try {
|
||||
//#when
|
||||
@@ -150,11 +86,12 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => {
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(getClearTimeoutCalls()).toEqual([1 as ReturnType<typeof setTimeout>])
|
||||
expect(getClearTimeoutCalls()).toEqual([getScheduledTimeouts()[0]])
|
||||
expect(executeCompactMock).toHaveBeenCalledTimes(1)
|
||||
expect(executeCompactMock.mock.calls[0]?.[0]).toBe("session-empty-summary")
|
||||
expect(compactedSessionID).toBe("session-empty-summary")
|
||||
} finally {
|
||||
restore()
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user