fix(test): use static imports and strategy-level spies in executor.test.ts for CI stability

This commit is contained in:
YeonGyu-Kim 2026-02-22 02:42:59 +09:00
parent dd9df78564
commit b6b970d9cd

View File

@ -1,10 +1,9 @@
/// <reference types="bun-types" /> /// <reference types="bun-types" />
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test" import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test"
import { executeCompact } from "./executor"
import type { AutoCompactState } from "./types" import type { AutoCompactState } from "./types"
import * as recoveryStrategy from "./recovery-strategy"
type ExecuteCompact = typeof import("./executor").executeCompact import * as messagesReader from "../session-recovery/storage/messages-reader"
type StorageModule = typeof import("./storage")
type MessagesReaderModule = typeof import("../session-recovery/storage/messages-reader")
type TimerCallback = (...args: any[]) => void type TimerCallback = (...args: any[]) => void
@ -78,9 +77,6 @@ function createFakeTimeouts(): FakeTimeouts {
} }
describe("executeCompact lock management", () => { describe("executeCompact lock management", () => {
let executeCompact: ExecuteCompact
let storageModule: StorageModule
let messagesReaderModule: MessagesReaderModule
let autoCompactState: AutoCompactState let autoCompactState: AutoCompactState
let mockClient: any let mockClient: any
let fakeTimeouts: FakeTimeouts let fakeTimeouts: FakeTimeouts
@ -88,13 +84,7 @@ describe("executeCompact lock management", () => {
const directory = "/test/dir" const directory = "/test/dir"
const msg = { providerID: "anthropic", modelID: "claude-opus-4-6" } const msg = { providerID: "anthropic", modelID: "claude-opus-4-6" }
beforeEach(async () => { beforeEach(() => {
mock.restore()
const executorModule = await import("./executor")
executeCompact = executorModule.executeCompact
storageModule = await import("./storage")
messagesReaderModule = await import("../session-recovery/storage/messages-reader")
// given: Fresh state for each test // given: Fresh state for each test
autoCompactState = { autoCompactState = {
pendingCompact: new Set<string>(), pendingCompact: new Set<string>(),
@ -121,7 +111,6 @@ describe("executeCompact lock management", () => {
}) })
afterEach(() => { afterEach(() => {
mock.restore()
fakeTimeouts.restore() fakeTimeouts.restore()
}) })
@ -182,7 +171,7 @@ describe("executeCompact lock management", () => {
test("clears lock when fixEmptyMessages path executes", async () => { test("clears lock when fixEmptyMessages path executes", async () => {
//#given - Empty content error scenario with no messages in storage //#given - Empty content error scenario with no messages in storage
const readMessagesSpy = spyOn(messagesReaderModule, "readMessages").mockReturnValue([]) const readMessagesSpy = spyOn(messagesReader, "readMessages").mockReturnValue([])
autoCompactState.errorDataBySession.set(sessionID, { autoCompactState.errorDataBySession.set(sessionID, {
errorType: "non-empty content required", errorType: "non-empty content required",
messageIndex: 0, messageIndex: 0,
@ -200,7 +189,7 @@ describe("executeCompact lock management", () => {
test("clears lock when truncation is sufficient", async () => { test("clears lock when truncation is sufficient", async () => {
//#given - Aggressive truncation scenario with no messages in storage //#given - Aggressive truncation scenario with no messages in storage
const readMessagesSpy = spyOn(messagesReaderModule, "readMessages").mockReturnValue([]) const readMessagesSpy = spyOn(messagesReader, "readMessages").mockReturnValue([])
autoCompactState.errorDataBySession.set(sessionID, { autoCompactState.errorDataBySession.set(sessionID, {
errorType: "token_limit", errorType: "token_limit",
currentTokens: 250000, currentTokens: 250000,
@ -325,18 +314,13 @@ describe("executeCompact lock management", () => {
maxTokens: 200000, maxTokens: 200000,
}) })
const truncateSpy = spyOn(storageModule, "truncateUntilTargetTokens").mockResolvedValue({ const truncateSpy = spyOn(
success: true, recoveryStrategy,
sufficient: false, "runAggressiveTruncationStrategy",
truncatedCount: 3, ).mockImplementation(async (params) => ({
totalBytesRemoved: 10000, handled: false,
targetBytesToRemove: 50000, nextTruncateAttempt: params.truncateAttempt + 1,
truncatedTools: [ }))
{ toolName: "Grep", originalSize: 5000 },
{ toolName: "Read", originalSize: 3000 },
{ toolName: "Bash", originalSize: 2000 },
],
})
// when: Execute compaction // when: Execute compaction
await executeCompact(sessionID, msg, autoCompactState, mockClient, directory) await executeCompact(sessionID, msg, autoCompactState, mockClient, directory)
@ -366,16 +350,24 @@ describe("executeCompact lock management", () => {
maxTokens: 200000, maxTokens: 200000,
}) })
const truncateSpy = spyOn(storageModule, "truncateUntilTargetTokens").mockResolvedValue({ const truncateSpy = spyOn(
success: true, recoveryStrategy,
sufficient: true, "runAggressiveTruncationStrategy",
truncatedCount: 5, ).mockImplementation(async (params) => {
totalBytesRemoved: 60000, setTimeout(() => {
targetBytesToRemove: 50000, void params.client.session
truncatedTools: [ .promptAsync({
{ toolName: "Grep", originalSize: 30000 }, path: { id: params.sessionID },
{ toolName: "Read", originalSize: 30000 }, body: { auto: true } as never,
], query: { directory: params.directory },
})
.catch(() => {})
}, 500)
return {
handled: true,
nextTruncateAttempt: params.truncateAttempt + 1,
}
}) })
// when: Execute compaction // when: Execute compaction