From b669a11ab1b1a38fe960593f8983b8a3c0f0411c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 29 May 2026 18:27:04 +0900 Subject: [PATCH] test(tmux): inject session-created handler seams Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- .../session-created-handler.test.ts | 23 +++++-------------- .../tmux-subagent/session-created-handler.ts | 9 ++++++-- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/features/tmux-subagent/session-created-handler.test.ts b/src/features/tmux-subagent/session-created-handler.test.ts index 8b0fdd4aa..77b8c2782 100644 --- a/src/features/tmux-subagent/session-created-handler.test.ts +++ b/src/features/tmux-subagent/session-created-handler.test.ts @@ -1,11 +1,6 @@ -import { describe, test, expect, mock, afterEach } from "bun:test" +/// -// --------------------------------------------------------------------------- -// Module-level mocks — must be registered BEFORE importing the handler so the -// handler picks up the mocked exports instead of the real implementations. -// queryWindowState and executeActions hit real tmux/spawn subprocesses; we -// replace them with spies so the spawn path can actually be exercised in tests. -// --------------------------------------------------------------------------- +import { describe, test, expect, mock, afterEach } from "bun:test" const mockQueryWindowState = mock(async (_paneId: string) => ({ windowWidth: 244, @@ -20,9 +15,6 @@ const mockExecuteActions = mock(async (_actions: unknown[], _ctx: unknown) => ({ results: [], })) -mock.module("./pane-state-querier", () => ({ queryWindowState: mockQueryWindowState })) -mock.module("./action-executor", () => ({ executeActions: mockExecuteActions })) - import type { SessionCreatedHandlerDeps } from "./session-created-handler" import { handleSessionCreated } from "./session-created-handler" import type { SessionCreatedEvent } from "./session-created-event" @@ -50,12 +42,6 @@ function makeDeps(overrides: Partial = {}): { mockExecuteActions: ReturnType mockWaitForSessionReady: ReturnType } { - const mockExecuteActions = mock(async () => ({ - success: true, - spawnedPaneId: "%99", - results: [], - })) - const mockWaitForSessionReady = mock(async (_sessionId: string) => true) const deps: SessionCreatedHandlerDeps = { @@ -72,6 +58,8 @@ function makeDeps(overrides: Partial = {}): { getSessionMappings: () => [], waitForSessionReady: mockWaitForSessionReady, startPolling: mock(() => {}), + queryWindowState: mockQueryWindowState, + executeActions: mockExecuteActions, ...overrides, } @@ -132,7 +120,7 @@ describe("handleSessionCreated – #3505 session readiness race", () => { callLog.push("waitForSessionReady:end") return ready }) - mockExecuteActions.mockImplementation(async (_actions, _ctx) => { + mockExecuteActions.mockImplementation(async (_actions: unknown[], _ctx: unknown) => { callLog.push("executeActions") return { success: true, spawnedPaneId: "%99", results: [] } }) @@ -195,6 +183,7 @@ describe("handleSessionCreated – #3505 session readiness race", () => { sessionId: "ses_existing", paneId: "%5", description: "TestAgent", + attachActivated: false, createdAt: new Date(), lastSeenAt: new Date(), closePending: false, diff --git a/src/features/tmux-subagent/session-created-handler.ts b/src/features/tmux-subagent/session-created-handler.ts index 1d806ecc7..a4a08639d 100644 --- a/src/features/tmux-subagent/session-created-handler.ts +++ b/src/features/tmux-subagent/session-created-handler.ts @@ -25,6 +25,8 @@ export interface SessionCreatedHandlerDeps { getSessionMappings: () => SessionMapping[] waitForSessionReady: (sessionId: string) => Promise startPolling: () => void + queryWindowState?: typeof queryWindowState + executeActions?: typeof executeActions } export async function handleSessionCreated( @@ -63,7 +65,10 @@ export async function handleSessionCreated( deps.pendingSessions.add(sessionId) try { - const state = await queryWindowState(deps.sourcePaneId) + const queryWindowStateImpl = deps.queryWindowState ?? queryWindowState + const executeActionsImpl = deps.executeActions ?? executeActions + + const state = await queryWindowStateImpl(deps.sourcePaneId) if (!state) { log("[tmux-session-manager] failed to query window state") return @@ -115,7 +120,7 @@ export async function handleSessionCreated( return } - const result = await executeActions(decision.actions, { + const result = await executeActionsImpl(decision.actions, { config: deps.tmuxConfig, directory: deps.directory, serverUrl: deps.serverUrl,