diff --git a/src/features/team-mode/team-layout-tmux/layout.test.ts b/src/features/team-mode/team-layout-tmux/layout.test.ts index c23f878f4..aa9a90ff5 100644 --- a/src/features/team-mode/team-layout-tmux/layout.test.ts +++ b/src/features/team-mode/team-layout-tmux/layout.test.ts @@ -1,21 +1,32 @@ import { beforeEach, describe, expect, mock, test } from "bun:test" +type LayoutModule = typeof import("./layout") + const spawnMock = mock(() => ({ exited: Promise.resolve(0), stdout: new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode("%1\n")); controller.close() } }), stderr: new ReadableStream({ start(controller) { controller.close() } }), })) -mock.module("bun", () => ({ spawn: spawnMock })) +const layoutSpecifier = import.meta.resolve("./layout") +const spawnProcessSpecifier = import.meta.resolve("../../../shared/tmux/tmux-utils/spawn-process") +const tmuxPathResolverSpecifier = import.meta.resolve("../../../tools/interactive-bash/tmux-path-resolver") +const sharedSpecifier = import.meta.resolve("../../../shared") -mock.module("../../../tools/interactive-bash/tmux-path-resolver", () => ({ getTmuxPath: mock(() => Promise.resolve("tmux")) })) +function registerModuleMocks(): void { + mock.module(spawnProcessSpecifier, () => ({ spawn: spawnMock })) + mock.module(tmuxPathResolverSpecifier, () => ({ getTmuxPath: mock(() => Promise.resolve("tmux")) })) + mock.module(sharedSpecifier, () => ({ log: mock(() => undefined) })) +} -mock.module("../../../shared", () => ({ log: mock(() => undefined) })) - -import { createTeamLayout, removeTeamLayout, canVisualize } from "./layout" +async function loadLayoutModule(): Promise { + const module = await import(`${layoutSpecifier}?test=${crypto.randomUUID()}`) + return module as LayoutModule +} describe("team-layout-tmux", () => { beforeEach(() => { + registerModuleMocks() spawnMock.mockClear() process.env.TMUX = "/tmp/tmux-1" }) @@ -23,6 +34,7 @@ describe("team-layout-tmux", () => { test("returns null and makes no tmux calls when visualization unavailable", async () => { // given delete process.env.TMUX + const { createTeamLayout, canVisualize } = await loadLayoutModule() // when const result = await createTeamLayout("run-1", [], {} as never) @@ -35,6 +47,7 @@ describe("team-layout-tmux", () => { test("creates focus and grid windows", async () => { // given + const { createTeamLayout } = await loadLayoutModule() const members = [ { name: "lead", sessionId: "s1", color: "red" }, { name: "m2", sessionId: "s2" }, @@ -54,6 +67,7 @@ describe("team-layout-tmux", () => { test("returns null when tmux command fails", async () => { // given + const { createTeamLayout } = await loadLayoutModule() spawnMock.mockImplementationOnce(() => ({ exited: Promise.resolve(1), stdout: new ReadableStream({ start(controller) { controller.close() } }), @@ -69,6 +83,8 @@ describe("team-layout-tmux", () => { test("cleans up the tmux session", async () => { // given + const { removeTeamLayout } = await loadLayoutModule() + // when await removeTeamLayout("run-4", {} as never) diff --git a/src/features/team-mode/team-layout-tmux/layout.ts b/src/features/team-mode/team-layout-tmux/layout.ts index b41354d06..f414ccbfe 100644 --- a/src/features/team-mode/team-layout-tmux/layout.ts +++ b/src/features/team-mode/team-layout-tmux/layout.ts @@ -1,4 +1,4 @@ -import { spawn } from "bun" +import { spawn } from "../../../shared/tmux/tmux-utils/spawn-process" import { log } from "../../../shared" import { getTmuxPath } from "../../../tools/interactive-bash/tmux-path-resolver" import type { TmuxSessionManager } from "../../tmux-subagent/manager"