296 lines · 10.3 KB · TypeScript
RawDownload
import { scopeThreadRef, scopedThreadKey } from "@t3tools/client-runtime/environment";import { ThreadId } from "@t3tools/contracts";import { beforeEach, describe, expect, it } from "vite-plus/test"; import {  migratePersistedTerminalUiStateStoreState,  selectThreadTerminalUiState,  useTerminalUiStateStore,} from "./terminalUiStateStore";import { DEFAULT_THREAD_TERMINAL_ID } from "./types"; const THREAD_ID = ThreadId.make("thread-1");const THREAD_REF = scopeThreadRef("environment-a" as never, THREAD_ID);const OTHER_THREAD_REF = scopeThreadRef("environment-b" as never, THREAD_ID); describe("terminalUiStateStore actions", () => {  beforeEach(() => {    useTerminalUiStateStore.persist.clearStorage();    useTerminalUiStateStore.setState({      terminalUiStateByThreadKey: {},      suppressedTerminalIdsByThreadKey: {},    });  });   it("returns an empty default terminal UI state for unknown threads", () => {    const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState).toEqual({      terminalOpen: false,      terminalHeight: 280,      terminalIds: [],      activeTerminalId: "",      terminalGroups: [],      activeTerminalGroupId: "",    });  });   it("opens and splits terminals into the active group", () => {    const store = useTerminalUiStateStore.getState();    store.setTerminalOpen(THREAD_REF, true);    store.splitTerminal(THREAD_REF, "terminal-2");     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.terminalOpen).toBe(true);    expect(terminalUiState.terminalIds).toEqual([DEFAULT_THREAD_TERMINAL_ID, "terminal-2"]);    expect(terminalUiState.activeTerminalId).toBe("terminal-2");    expect(terminalUiState.terminalGroups).toEqual([      {        id: `group-${DEFAULT_THREAD_TERMINAL_ID}`,        terminalIds: [DEFAULT_THREAD_TERMINAL_ID, "terminal-2"],      },    ]);  });   it("stacks vertically split terminals in the active group", () => {    const store = useTerminalUiStateStore.getState();    store.setTerminalOpen(THREAD_REF, true);    store.splitTerminalVertical(THREAD_REF, "terminal-2");     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.terminalGroups).toEqual([      {        id: `group-${DEFAULT_THREAD_TERMINAL_ID}`,        terminalIds: [DEFAULT_THREAD_TERMINAL_ID, "terminal-2"],        splitDirection: "vertical",      },    ]);  });   it("materializes the default terminal when opening an empty drawer", () => {    useTerminalUiStateStore.getState().setTerminalOpen(THREAD_REF, true);     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState).toEqual({      terminalOpen: true,      terminalHeight: 280,      terminalIds: [DEFAULT_THREAD_TERMINAL_ID],      activeTerminalId: DEFAULT_THREAD_TERMINAL_ID,      terminalGroups: [        {          id: `group-${DEFAULT_THREAD_TERMINAL_ID}`,          terminalIds: [DEFAULT_THREAD_TERMINAL_ID],        },      ],      activeTerminalGroupId: `group-${DEFAULT_THREAD_TERMINAL_ID}`,    });  });   it("caps splits at four terminals per group", () => {    const store = useTerminalUiStateStore.getState();    store.splitTerminal(THREAD_REF, "terminal-2");    store.splitTerminal(THREAD_REF, "terminal-3");    store.splitTerminal(THREAD_REF, "terminal-4");    store.splitTerminal(THREAD_REF, "terminal-5");    store.splitTerminal(THREAD_REF, "terminal-6");     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.terminalIds).toEqual([      "terminal-2",      "terminal-3",      "terminal-4",      "terminal-5",    ]);    expect(terminalUiState.terminalGroups).toEqual([      {        id: "group-terminal-2",        terminalIds: ["terminal-2", "terminal-3", "terminal-4", "terminal-5"],      },    ]);  });   it("creates new terminals in a separate group", () => {    useTerminalUiStateStore.getState().newTerminal(THREAD_REF, "terminal-2");     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.terminalIds).toEqual(["terminal-2"]);    expect(terminalUiState.activeTerminalId).toBe("terminal-2");    expect(terminalUiState.activeTerminalGroupId).toBe("group-terminal-2");    expect(terminalUiState.terminalGroups).toEqual([      { id: "group-terminal-2", terminalIds: ["terminal-2"] },    ]);  });   it("ensures unknown server terminals are registered, opened, and activated", () => {    const store = useTerminalUiStateStore.getState();    store.ensureTerminal(THREAD_REF, "setup-setup", { open: true, active: true });     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.terminalOpen).toBe(true);    expect(terminalUiState.terminalIds).toEqual(["setup-setup"]);    expect(terminalUiState.activeTerminalId).toBe("setup-setup");    expect(terminalUiState.terminalGroups).toEqual([      { id: "group-setup-setup", terminalIds: ["setup-setup"] },    ]);  });   it("keeps state isolated per environment when raw thread ids collide", () => {    const store = useTerminalUiStateStore.getState();    store.setTerminalOpen(THREAD_REF, true);    store.newTerminal(OTHER_THREAD_REF, "env-b-terminal");     expect(      selectThreadTerminalUiState(        useTerminalUiStateStore.getState().terminalUiStateByThreadKey,        THREAD_REF,      ).terminalOpen,    ).toBe(true);    expect(      selectThreadTerminalUiState(        useTerminalUiStateStore.getState().terminalUiStateByThreadKey,        OTHER_THREAD_REF,      ).terminalIds,    ).toEqual(["env-b-terminal"]);  });   it("drops persisted entries whose thread keys are not valid scoped keys", () => {    const migrated = migratePersistedTerminalUiStateStoreState(      {        terminalStateByThreadKey: {          [scopedThreadKey(THREAD_REF)]: {            terminalOpen: true,            terminalHeight: 320,            terminalIds: ["term-1"],            activeTerminalId: "term-1",            terminalGroups: [{ id: "group-term-1", terminalIds: ["term-1"] }],            activeTerminalGroupId: "group-term-1",          },          "legacy-thread-id": {            terminalOpen: true,            terminalHeight: 320,            terminalIds: ["term-1"],            activeTerminalId: "term-1",            terminalGroups: [{ id: "group-term-1", terminalIds: ["term-1"] }],            activeTerminalGroupId: "group-term-1",          },        },      },      2,    );     expect(migrated).toEqual({      terminalUiStateByThreadKey: {        [scopedThreadKey(THREAD_REF)]: {          terminalOpen: true,          terminalHeight: 320,          terminalIds: ["term-1"],          activeTerminalId: "term-1",          terminalGroups: [{ id: "group-term-1", terminalIds: ["term-1"] }],          activeTerminalGroupId: "group-term-1",        },      },    });  });   it("resets to default and clears persisted entry when closing the last terminal", () => {    const store = useTerminalUiStateStore.getState();    store.newTerminal(THREAD_REF, "terminal-only");    store.closeTerminal(THREAD_REF, "terminal-only");     expect(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey[scopedThreadKey(THREAD_REF)],    ).toBeUndefined();    expect(      selectThreadTerminalUiState(        useTerminalUiStateStore.getState().terminalUiStateByThreadKey,        THREAD_REF,      ).terminalIds,    ).toEqual([]);  });   it("keeps a valid active terminal after closing an active split terminal", () => {    const store = useTerminalUiStateStore.getState();    store.splitTerminal(THREAD_REF, "terminal-2");    store.splitTerminal(THREAD_REF, "terminal-3");    store.closeTerminal(THREAD_REF, "terminal-3");     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.activeTerminalId).toBe("terminal-2");    expect(terminalUiState.terminalIds).toEqual(["terminal-2"]);    expect(terminalUiState.terminalGroups).toEqual([      { id: "group-terminal-2", terminalIds: ["terminal-2"] },    ]);  });   it("reconciles terminal ids from an external ordered list", () => {    const store = useTerminalUiStateStore.getState();    store.setTerminalOpen(THREAD_REF, true);    store.reconcileTerminalIds(THREAD_REF, ["term-a", "term-b"]);     const terminalUiState = selectThreadTerminalUiState(      useTerminalUiStateStore.getState().terminalUiStateByThreadKey,      THREAD_REF,    );    expect(terminalUiState.terminalIds).toEqual(["term-a", "term-b"]);    expect(terminalUiState.activeTerminalId).toBe("term-a");    expect(terminalUiState.terminalGroups).toEqual([      { id: "group-term-a", terminalIds: ["term-a"] },      { id: "group-term-b", terminalIds: ["term-b"] },    ]);  });   it("does not import a closed panel terminal from stale metadata", () => {    const store = useTerminalUiStateStore.getState();    store.newTerminal(THREAD_REF, "term-2");    store.closeTerminal(THREAD_REF, "term-1");     store.reconcileTerminalIds(THREAD_REF, ["term-1", "term-2"]);     expect(      selectThreadTerminalUiState(        useTerminalUiStateStore.getState().terminalUiStateByThreadKey,        THREAD_REF,      ).terminalIds,    ).toEqual(["term-2"]);     store.newTerminal(THREAD_REF, "term-1");    expect(      selectThreadTerminalUiState(        useTerminalUiStateStore.getState().terminalUiStateByThreadKey,        THREAD_REF,      ).terminalIds,    ).toEqual(["term-2", "term-1"]);  });   it("is a no-op when clearing terminal UI state for a thread with no state", () => {    const store = useTerminalUiStateStore.getState();    const before = useTerminalUiStateStore.getState();     store.clearTerminalUiState(THREAD_REF);     expect(useTerminalUiStateStore.getState()).toBe(before);  });});