145 lines · 4.4 KB · TypeScript
RawDownload
import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import {  shouldClearTerminalSelectionAction,  shouldHandleTerminalExit,  terminalContextMenuItems,  terminalSelectionLineRange,  terminalSelectionMenuItems,  terminalThemeFromApp,} from "./ThreadTerminalDrawer"; describe("terminal selection menus", () => {  it("omits Add to chat when the terminal has no chat target", () => {    expect(terminalSelectionMenuItems().map(({ id }) => id)).toEqual(["add-to-chat", "copy"]);    expect(terminalContextMenuItems({ hasSelection: true }).map(({ id }) => id)).toEqual([      "add-to-chat",      "copy",      "paste",    ]);     expect(terminalSelectionMenuItems({ canAddToChat: false }).map(({ id }) => id)).toEqual([      "copy",    ]);    expect(      terminalContextMenuItems({ hasSelection: true, canAddToChat: false }).map(({ id }) => id),    ).toEqual(["copy", "paste"]);  });}); describe("terminalThemeFromApp", () => {  afterEach(() => {    vi.unstubAllGlobals();  });   it("uses terminal colors inherited by the mount instead of a light document theme", () => {    const root = { classList: { contains: () => false } };    const body = {};    const drawer = {};    let canvasColor = "#000";    const colors: Record<string, [number, number, number, number]> = {      "#000": [0, 0, 0, 255],      "#fff": [255, 255, 255, 255],      "#ddd": [221, 221, 221, 255],      "#111": [17, 17, 17, 255],    };     vi.stubGlobal("document", {      documentElement: root,      body,      querySelector: () => drawer,      createElement: () => ({        width: 0,        height: 0,        getContext: () => ({          clearRect: () => undefined,          fillRect: () => undefined,          get fillStyle() {            return canvasColor;          },          set fillStyle(value: string) {            canvasColor = value;          },          getImageData: () => ({ data: colors[canvasColor] ?? [0, 0, 0, 0] }),        }),      }),    });    vi.stubGlobal("getComputedStyle", (element: object) => {      const local = element === drawer;      const values = local        ? {            "--terminal-background": "#000",            "--terminal-foreground": "#fff",            "--terminal-cursor": "#ddd",            "--terminal-selection-background": "rgba(255, 255, 255, 0.2)",          }        : {            "--terminal-background": "#fff",            "--terminal-foreground": "#111",          };      return {        backgroundColor: local ? "#000" : "#fff",        color: local ? "#fff" : "#111",        colorScheme: local ? "dark" : "light",        getPropertyValue: (name: string) => values[name as keyof typeof values] ?? "",      };    });     const theme = terminalThemeFromApp();     expect(theme.background).toEqual({ r: 0, g: 0, b: 0 });    expect(theme.foreground).toEqual({ r: 255, g: 255, b: 255 });    expect(theme.cursor).toEqual({ r: 221, g: 221, b: 221 });  });}); describe("terminal selection actions", () => {  it("clears a pending or currently owned menu when the selection disappears", () => {    expect(      shouldClearTerminalSelectionAction({        actionPending: true,        openMenuRequestId: null,        currentRequestId: 4,      }),    ).toBe(true);    expect(      shouldClearTerminalSelectionAction({        actionPending: false,        openMenuRequestId: 4,        currentRequestId: 4,      }),    ).toBe(true);  });   it("does not let an old selection popup cancel its replacement right-click menu", () => {    expect(      shouldClearTerminalSelectionAction({        actionPending: false,        openMenuRequestId: 3,        currentRequestId: 4,      }),    ).toBe(false);    expect(      shouldClearTerminalSelectionAction({        actionPending: false,        openMenuRequestId: null,        currentRequestId: 4,      }),    ).toBe(false);  });   it("uses Ghostty's physical screen range for visually wrapped selections", () => {    expect(      terminalSelectionLineRange({        start: { y: 4 },        end: { y: 6 },      }),    ).toEqual({ lineStart: 5, lineEnd: 7 });  });   it("handles an exit that lands while the terminal surface is still loading", () => {    expect(shouldHandleTerminalExit("exited", "running", false)).toBe(true);    expect(shouldHandleTerminalExit("exited", "exited", false)).toBe(false);    expect(shouldHandleTerminalExit("closed", "running", true)).toBe(false);  });});