import { ThreadId } from "@t3tools/contracts"; import { beforeEach, describe, expect, it } from "vitest"; import { selectThreadTerminalState, useTerminalStateStore } from "./terminalStateStore"; const THREAD_ID = ThreadId.makeUnsafe("thread-1"); describe("terminalStateStore actions", () => { beforeEach(() => { if (typeof localStorage !== "undefined") { localStorage.clear(); } useTerminalStateStore.setState({ terminalStateByThreadId: {} }); }); it("returns a closed default terminal state for unknown threads", () => { const terminalState = selectThreadTerminalState( useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID, ); expect(terminalState).toEqual({ terminalOpen: false, terminalHeight: 280, terminalIds: ["default"], runningTerminalIds: [], activeTerminalId: "default", terminalGroups: [{ id: "group-default", terminalIds: ["default"] }], activeTerminalGroupId: "group-default", }); }); it("opens and splits terminals into the active group", () => { const store = useTerminalStateStore.getState(); store.setTerminalOpen(THREAD_ID, true); store.splitTerminal(THREAD_ID, "terminal-2"); const terminalState = selectThreadTerminalState( useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID, ); expect(terminalState.terminalOpen).toBe(true); expect(terminalState.terminalIds).toEqual(["default", "terminal-2"]); expect(terminalState.activeTerminalId).toBe("terminal-2"); expect(terminalState.terminalGroups).toEqual([ { id: "group-default", terminalIds: ["default", "terminal-2"] }, ]); }); it("caps splits at four terminals per group", () => { const store = useTerminalStateStore.getState(); store.splitTerminal(THREAD_ID, "terminal-2"); store.splitTerminal(THREAD_ID, "terminal-3"); store.splitTerminal(THREAD_ID, "terminal-4"); store.splitTerminal(THREAD_ID, "terminal-5"); const terminalState = selectThreadTerminalState( useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID, ); expect(terminalState.terminalIds).toEqual([ "default", "terminal-2", "terminal-3", "terminal-4", ]); expect(terminalState.terminalGroups).toEqual([ { id: "group-default", terminalIds: ["default", "terminal-2", "terminal-3", "terminal-4"] }, ]); }); it("creates new terminals in a separate group", () => { useTerminalStateStore.getState().newTerminal(THREAD_ID, "terminal-2"); const terminalState = selectThreadTerminalState( useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID, ); expect(terminalState.terminalIds).toEqual(["default", "terminal-2"]); expect(terminalState.activeTerminalId).toBe("terminal-2"); expect(terminalState.activeTerminalGroupId).toBe("group-terminal-2"); expect(terminalState.terminalGroups).toEqual([ { id: "group-default", terminalIds: ["default"] }, { id: "group-terminal-2", terminalIds: ["terminal-2"] }, ]); }); it("allows unlimited groups while keeping each group capped at four terminals", () => { const store = useTerminalStateStore.getState(); store.splitTerminal(THREAD_ID, "terminal-2"); store.splitTerminal(THREAD_ID, "terminal-3"); store.splitTerminal(THREAD_ID, "terminal-4"); store.newTerminal(THREAD_ID, "terminal-5"); store.newTerminal(THREAD_ID, "terminal-6"); const terminalState = selectThreadTerminalState( useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID, ); expect(terminalState.terminalIds).toEqual([ "default", "terminal-2", "terminal-3", "terminal-4", "terminal-5", "terminal-6", ]); expect(terminalState.terminalGroups).toEqual([ { id: "group-default", terminalIds: ["default", "terminal-2", "terminal-3", "terminal-4"] }, { id: "group-terminal-5", terminalIds: ["terminal-5"] }, { id: "group-terminal-6", terminalIds: ["terminal-6"] }, ]); }); it("tracks and clears terminal subprocess activity", () => { const store = useTerminalStateStore.getState(); store.splitTerminal(THREAD_ID, "terminal-2"); store.setTerminalActivity(THREAD_ID, "terminal-2", true); expect( selectThreadTerminalState(useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID) .runningTerminalIds, ).toEqual(["terminal-2"]); store.setTerminalActivity(THREAD_ID, "terminal-2", false); expect( selectThreadTerminalState(useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID) .runningTerminalIds, ).toEqual([]); }); it("resets to default and clears persisted entry when closing the last terminal", () => { const store = useTerminalStateStore.getState(); store.closeTerminal(THREAD_ID, "default"); expect(useTerminalStateStore.getState().terminalStateByThreadId[THREAD_ID]).toBeUndefined(); expect( selectThreadTerminalState(useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID) .terminalIds, ).toEqual(["default"]); }); it("keeps a valid active terminal after closing an active split terminal", () => { const store = useTerminalStateStore.getState(); store.splitTerminal(THREAD_ID, "terminal-2"); store.splitTerminal(THREAD_ID, "terminal-3"); store.closeTerminal(THREAD_ID, "terminal-3"); const terminalState = selectThreadTerminalState( useTerminalStateStore.getState().terminalStateByThreadId, THREAD_ID, ); expect(terminalState.activeTerminalId).toBe("terminal-2"); expect(terminalState.terminalIds).toEqual(["default", "terminal-2"]); expect(terminalState.terminalGroups).toEqual([ { id: "group-default", terminalIds: ["default", "terminal-2"] }, ]); }); });