diff --git a/src/create-managers.test.ts b/src/create-managers.test.ts index 56f6e8cfc..e246e1dcb 100644 --- a/src/create-managers.test.ts +++ b/src/create-managers.test.ts @@ -1,49 +1,23 @@ /// -import { afterAll, beforeEach, describe, expect, it, mock } from "bun:test" +import { beforeEach, describe, expect, it, mock } from "bun:test" -const markServerRunningInProcess = mock(() => {}) +import { createManagers } from "./create-managers" -mock.module("./features/background-agent", () => ({ - BackgroundManager: class BackgroundManager { - constructor(..._args: unknown[]) {} - }, -})) +class MockBackgroundManager { + constructor(..._args: unknown[]) {} +} -mock.module("./features/skill-mcp-manager", () => ({ - SkillMcpManager: class SkillMcpManager { - constructor(..._args: unknown[]) {} - }, -})) +class MockSkillMcpManager { + constructor(..._args: unknown[]) {} +} -mock.module("./features/task-toast-manager", () => ({ - initTaskToastManager: mock(() => {}), -})) +class MockTmuxSessionManager { + constructor(..._args: unknown[]) {} -mock.module("./features/tmux-subagent", () => ({ - TmuxSessionManager: class TmuxSessionManager { - constructor(..._args: unknown[]) {} - - async cleanup(): Promise {} - async onSessionCreated(..._args: unknown[]): Promise {} - }, -})) - -mock.module("./features/background-agent/process-cleanup", () => ({ - registerManagerForCleanup: mock(() => {}), -})) - -mock.module("./plugin-handlers", () => ({ - createConfigHandler: mock(() => ({ kind: "config-handler" })), -})) - -mock.module("./shared/tmux/tmux-utils/server-health", () => ({ - isServerRunning: mock(async () => true), - markServerRunningInProcess, - resetServerCheck: mock(() => {}), -})) - -const { createManagers } = await import("./create-managers") + async cleanup(): Promise {} + async onSessionCreated(..._args: unknown[]): Promise {} +} function createTmuxConfig(enabled: boolean) { return { @@ -57,23 +31,47 @@ function createTmuxConfig(enabled: boolean) { } describe("createManagers", () => { + const markServerRunningInProcess = mock(() => {}) + const initTaskToastManager = mock(() => ({}) as never) + const registerManagerForCleanup = mock(() => {}) + const createConfigHandler = mock(() => (async () => {}) as never) + + function createMockArgs(enabled: boolean): Parameters[0] { + return { + ctx: { + directory: "/tmp", + client: {} as never, + project: {} as never, + worktree: "/tmp", + serverUrl: new URL("https://example.com"), + $: Bun.$, + }, + pluginConfig: {} as never, + tmuxConfig: createTmuxConfig(enabled), + modelCacheState: {} as never, + backgroundNotificationHookEnabled: false, + deps: { + BackgroundManagerClass: MockBackgroundManager as never, + SkillMcpManagerClass: MockSkillMcpManager as never, + TmuxSessionManagerClass: MockTmuxSessionManager as never, + initTaskToastManagerFn: initTaskToastManager, + registerManagerForCleanupFn: registerManagerForCleanup, + createConfigHandlerFn: createConfigHandler, + markServerRunningInProcessFn: markServerRunningInProcess, + }, + } + } + beforeEach(() => { markServerRunningInProcess.mockClear() - }) - - afterAll(() => { - mock.restore() + initTaskToastManager.mockClear() + registerManagerForCleanup.mockClear() + createConfigHandler.mockClear() }) it("#given tmux integration is disabled #when managers are created #then it does not mark the tmux server as running", () => { // #given - const args = { - ctx: { directory: "/tmp", client: {} }, - pluginConfig: {}, - tmuxConfig: createTmuxConfig(false), - modelCacheState: {}, - backgroundNotificationHookEnabled: false, - } as Parameters[0] + const args = createMockArgs(false) // #when createManagers(args) @@ -84,13 +82,7 @@ describe("createManagers", () => { it("#given tmux integration is enabled #when managers are created #then it marks the tmux server as running", () => { // #given - const args = { - ctx: { directory: "/tmp", client: {} }, - pluginConfig: {}, - tmuxConfig: createTmuxConfig(true), - modelCacheState: {}, - backgroundNotificationHookEnabled: false, - } as Parameters[0] + const args = createMockArgs(true) // #when createManagers(args) diff --git a/src/create-managers.ts b/src/create-managers.ts index 14e8873c4..51b93270e 100644 --- a/src/create-managers.ts +++ b/src/create-managers.ts @@ -12,6 +12,26 @@ import { createConfigHandler } from "./plugin-handlers" import { log } from "./shared" import { markServerRunningInProcess } from "./shared/tmux/tmux-utils/server-health" +type CreateManagersDeps = { + BackgroundManagerClass: typeof BackgroundManager + SkillMcpManagerClass: typeof SkillMcpManager + TmuxSessionManagerClass: typeof TmuxSessionManager + initTaskToastManagerFn: typeof initTaskToastManager + registerManagerForCleanupFn: typeof registerManagerForCleanup + createConfigHandlerFn: typeof createConfigHandler + markServerRunningInProcessFn: typeof markServerRunningInProcess +} + +const defaultCreateManagersDeps: CreateManagersDeps = { + BackgroundManagerClass: BackgroundManager, + SkillMcpManagerClass: SkillMcpManager, + TmuxSessionManagerClass: TmuxSessionManager, + initTaskToastManagerFn: initTaskToastManager, + registerManagerForCleanupFn: registerManagerForCleanup, + createConfigHandlerFn: createConfigHandler, + markServerRunningInProcessFn: markServerRunningInProcess, +} + export type Managers = { tmuxSessionManager: TmuxSessionManager backgroundManager: BackgroundManager @@ -25,15 +45,17 @@ export function createManagers(args: { tmuxConfig: TmuxConfig modelCacheState: ModelCacheState backgroundNotificationHookEnabled: boolean + deps?: Partial }): Managers { const { ctx, pluginConfig, tmuxConfig, modelCacheState, backgroundNotificationHookEnabled } = args + const deps = { ...defaultCreateManagersDeps, ...args.deps } if (tmuxConfig.enabled) { - markServerRunningInProcess() + deps.markServerRunningInProcessFn() } - const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig) + const tmuxSessionManager = new deps.TmuxSessionManagerClass(ctx, tmuxConfig) - registerManagerForCleanup({ + deps.registerManagerForCleanupFn({ shutdown: async () => { await tmuxSessionManager.cleanup().catch((error) => { log("[create-managers] tmux cleanup error during process shutdown:", error) @@ -41,7 +63,7 @@ export function createManagers(args: { }, }) - const backgroundManager = new BackgroundManager( + const backgroundManager = new deps.BackgroundManagerClass( ctx, pluginConfig.background_task, { @@ -75,11 +97,11 @@ export function createManagers(args: { }, ) - initTaskToastManager(ctx.client) + deps.initTaskToastManagerFn(ctx.client) - const skillMcpManager = new SkillMcpManager() + const skillMcpManager = new deps.SkillMcpManagerClass() - const configHandler = createConfigHandler({ + const configHandler = deps.createConfigHandlerFn({ ctx: { directory: ctx.directory, client: ctx.client }, pluginConfig, modelCacheState,