diff --git a/src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts b/src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts index 2e8772776..a3ab348c8 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts @@ -1,13 +1,21 @@ -import { describe, test, expect, mock, beforeEach } from "bun:test" +import { describe, test, expect, mock, beforeEach, afterAll } from "bun:test" import type { PluginInput } from "@opencode-ai/plugin" import type { ExperimentalConfig } from "../../config" -const attemptDeduplicationRecoveryMock = mock(async () => {}) +const realDeduplicationRecovery = await import("./deduplication-recovery") + +const attemptDeduplicationRecoveryMock = mock<(sessionID: string) => Promise>( + async () => {} +) mock.module("./deduplication-recovery", () => ({ attemptDeduplicationRecovery: attemptDeduplicationRecoveryMock, })) +afterAll(() => { + mock.module("./deduplication-recovery", () => ({ ...realDeduplicationRecovery })) +}) + function createImmediateTimeouts(): () => void { const originalSetTimeout = globalThis.setTimeout const originalClearTimeout = globalThis.clearTimeout @@ -37,13 +45,15 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => { const experimental = { dynamic_context_pruning: { enabled: true, + notification: "off", + protected_tools: [], strategies: { deduplication: { enabled: true }, }, }, } satisfies ExperimentalConfig - let resolveSummarize: (() => void) | null = null + let resolveSummarize: ((value?: void) => void) | null = null const summarizePromise = new Promise((resolve) => { resolveSummarize = resolve }) @@ -62,7 +72,7 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => { try { const { createAnthropicContextWindowLimitRecoveryHook } = await import("./recovery-hook") - const ctx = { client: mockClient, directory: "/tmp" } as PluginInput + const ctx = { client: mockClient, directory: "/tmp" } as unknown as PluginInput const hook = createAnthropicContextWindowLimitRecoveryHook(ctx, { experimental }) // first error triggers compaction (setTimeout runs immediately due to mock) @@ -105,7 +115,7 @@ describe("createAnthropicContextWindowLimitRecoveryHook", () => { } const { createAnthropicContextWindowLimitRecoveryHook } = await import("./recovery-hook") - const ctx = { client: mockClient, directory: "/tmp" } as PluginInput + const ctx = { client: mockClient, directory: "/tmp" } as unknown as PluginInput const hook = createAnthropicContextWindowLimitRecoveryHook(ctx) //#when - single error (no compaction in progress) diff --git a/src/hooks/atlas/index.test.ts b/src/hooks/atlas/index.test.ts index 1713789b2..41e040aa1 100644 --- a/src/hooks/atlas/index.test.ts +++ b/src/hooks/atlas/index.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test, beforeEach, afterEach, mock } from "bun:test" +import { describe, expect, test, beforeEach, afterEach, afterAll, mock } from "bun:test" import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs" import { join } from "node:path" import { tmpdir } from "node:os" @@ -9,20 +9,19 @@ import { readBoulderState, } from "../../features/boulder-state" import type { BoulderState } from "../../features/boulder-state" - -const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-message-storage-${randomUUID()}`) -const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message") -const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part") - -mock.module("../../features/hook-message-injector/constants", () => ({ - OPENCODE_STORAGE: TEST_STORAGE_ROOT, - MESSAGE_STORAGE: TEST_MESSAGE_STORAGE, - PART_STORAGE: TEST_PART_STORAGE, -})) +const realClaudeCodeSessionState = await import( + "../../features/claude-code-session-state" +) const { createAtlasHook } = await import("./index") const { MESSAGE_STORAGE } = await import("../../features/hook-message-injector") +afterAll(() => { + mock.module("../../features/claude-code-session-state", () => ({ + ...realClaudeCodeSessionState, + })) +}) + describe("atlas hook", () => { let TEST_DIR: string let SISYPHUS_DIR: string @@ -77,7 +76,6 @@ describe("atlas hook", () => { if (existsSync(TEST_DIR)) { rmSync(TEST_DIR, { recursive: true, force: true }) } - rmSync(TEST_STORAGE_ROOT, { recursive: true, force: true }) }) describe("tool.execute.after handler", () => { diff --git a/src/hooks/compaction-todo-preserver/index.test.ts b/src/hooks/compaction-todo-preserver/index.test.ts index 04cc577a8..985c59dd2 100644 --- a/src/hooks/compaction-todo-preserver/index.test.ts +++ b/src/hooks/compaction-todo-preserver/index.test.ts @@ -30,7 +30,7 @@ function createMockContext(todoResponses: TodoSnapshot[][]): PluginInput { }, }, directory: "/tmp/test", - } as PluginInput + } as unknown as PluginInput } describe("compaction-todo-preserver", () => { @@ -38,7 +38,7 @@ describe("compaction-todo-preserver", () => { //#given updateMock.mockClear() const sessionID = "session-compaction-missing" - const todos = [ + const todos: TodoSnapshot[] = [ { id: "1", content: "Task 1", status: "pending", priority: "high" }, { id: "2", content: "Task 2", status: "in_progress", priority: "medium" }, ] @@ -58,7 +58,7 @@ describe("compaction-todo-preserver", () => { //#given updateMock.mockClear() const sessionID = "session-compaction-present" - const todos = [ + const todos: TodoSnapshot[] = [ { id: "1", content: "Task 1", status: "pending", priority: "high" }, ] const ctx = createMockContext([todos, todos]) diff --git a/src/hooks/prometheus-md-only/index.test.ts b/src/hooks/prometheus-md-only/index.test.ts index 2c99b6e51..0c94c6b60 100644 --- a/src/hooks/prometheus-md-only/index.test.ts +++ b/src/hooks/prometheus-md-only/index.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test, beforeEach, afterEach, mock } from "bun:test" +import { describe, expect, test, beforeEach, afterEach } from "bun:test" import { mkdirSync, rmSync, writeFileSync } from "node:fs" import { join } from "node:path" import { tmpdir } from "node:os" @@ -6,16 +6,6 @@ import { randomUUID } from "node:crypto" import { SYSTEM_DIRECTIVE_PREFIX } from "../../shared/system-directive" import { clearSessionAgent } from "../../features/claude-code-session-state" -const TEST_STORAGE_ROOT = join(tmpdir(), `prometheus-md-only-${randomUUID()}`) -const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message") -const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part") - -mock.module("../../features/hook-message-injector/constants", () => ({ - OPENCODE_STORAGE: TEST_STORAGE_ROOT, - MESSAGE_STORAGE: TEST_MESSAGE_STORAGE, - PART_STORAGE: TEST_PART_STORAGE, -})) - const { createPrometheusMdOnlyHook } = await import("./index") const { MESSAGE_STORAGE } = await import("../../features/hook-message-injector") @@ -52,7 +42,6 @@ describe("prometheus-md-only", () => { // ignore } } - rmSync(TEST_STORAGE_ROOT, { recursive: true, force: true }) }) describe("agent name matching", () => { diff --git a/src/hooks/todo-continuation-enforcer/todo-continuation-enforcer.test.ts b/src/hooks/todo-continuation-enforcer/todo-continuation-enforcer.test.ts index 91cb173b0..d880ce397 100644 --- a/src/hooks/todo-continuation-enforcer/todo-continuation-enforcer.test.ts +++ b/src/hooks/todo-continuation-enforcer/todo-continuation-enforcer.test.ts @@ -518,7 +518,7 @@ describe("todo-continuation-enforcer", () => { //#then expect(promptCalls).toHaveLength(2) - }) + }, 20000) test("should keep injecting even when todos remain unchanged across cycles", async () => { //#given @@ -553,7 +553,7 @@ describe("todo-continuation-enforcer", () => { //#then — all 5 injections should fire (no stagnation cap) expect(promptCalls).toHaveLength(5) - }) + }, 30000) test("should skip idle handling while injection is in flight", async () => { //#given @@ -613,7 +613,7 @@ describe("todo-continuation-enforcer", () => { //#then expect(promptCalls).toHaveLength(2) - }) + }, 20000) test("should accept skipAgents option without error", async () => { // given - session with skipAgents configured for Prometheus diff --git a/src/tools/call-omo-agent/sync-executor.test.ts b/src/tools/call-omo-agent/sync-executor.test.ts index 744f08ffb..5b5f4e47c 100644 --- a/src/tools/call-omo-agent/sync-executor.test.ts +++ b/src/tools/call-omo-agent/sync-executor.test.ts @@ -1,16 +1,28 @@ -const { describe, test, expect, mock } = require("bun:test") +const { describe, test, expect, mock, beforeEach, afterEach } = require("bun:test") -mock.module("./session-creator", () => ({ - createOrGetSession: mock(async () => ({ sessionID: "ses-test-123" })), -})) +const realCompletionPoller = require("./completion-poller") +const realMessageProcessor = require("./message-processor") -mock.module("./completion-poller", () => ({ - waitForCompletion: mock(async () => {}), -})) +const waitForCompletionMock = mock(async () => {}) +const processMessagesMock = mock(async () => "agent response") -mock.module("./message-processor", () => ({ - processMessages: mock(async () => "agent response"), -})) +beforeEach(() => { + waitForCompletionMock.mockClear() + processMessagesMock.mockClear() + + mock.module("./completion-poller", () => ({ + waitForCompletion: waitForCompletionMock, + })) + + mock.module("./message-processor", () => ({ + processMessages: processMessagesMock, + })) +}) + +afterEach(() => { + mock.module("./completion-poller", () => ({ ...realCompletionPoller })) + mock.module("./message-processor", () => ({ ...realMessageProcessor })) +}) describe("executeSync", () => { test("passes question=false via tools parameter to block question tool", async () => { @@ -27,6 +39,7 @@ describe("executeSync", () => { subagent_type: "explore", description: "test task", prompt: "find something", + session_id: "ses-test-123", } const toolContext = { @@ -39,7 +52,10 @@ describe("executeSync", () => { const ctx = { client: { - session: { promptAsync }, + session: { + promptAsync, + get: mock(async () => ({ data: { id: "ses-test-123" } })), + }, }, } @@ -65,6 +81,7 @@ describe("executeSync", () => { subagent_type: "librarian", description: "search docs", prompt: "find docs", + session_id: "ses-test-123", } const toolContext = { @@ -77,7 +94,10 @@ describe("executeSync", () => { const ctx = { client: { - session: { promptAsync }, + session: { + promptAsync, + get: mock(async () => ({ data: { id: "ses-test-123" } })), + }, }, }