740 lines · 22.0 KB · TypeScript
RawDownload
import { describe, expect, it, vi } from "vite-plus/test";import { EnvironmentId, ProjectId, ProviderInstanceId, ThreadId } from "@t3tools/contracts";import type { Project, Thread } from "../types";import {  buildBrowseGroups,  buildCommandPaletteProjectMetadata,  buildProjectActionItems,  buildThreadActionItems,  buildLinkedThreadActionItems,  enumerateCommandPaletteItems,  filterPinnedBrowseEntries,  filterCommandPaletteGroups,  reduceCommandPaletteUiState,  type CommandPaletteGroup,} from "./CommandPalette.logic"; describe("linked pull request thread navigation", () => {  it("keeps archived relations searchable and routes them through the PR environment", async () => {    const environmentId = EnvironmentId.make("remote");    const id = ThreadId.make("archived-thread");    const runThread = vi.fn(async () => {});    const query = "https://github.com/acme/web/pull/42";    const linkedThreads = {      environmentId,      threads: [        {          id,          projectId: ProjectId.make("project"),          title: "Completed work",          archivedAt: "2026-09-01T00:00:00.000Z",        },      ],    };    const state = reduceCommandPaletteUiState(      { open: false, mode: "command", openIntent: null },      {        _tag: "OpenSearch",        query,        linkedThreads,      },    );    expect(state.openIntent).toEqual({ kind: "search", query, linkedThreads });    const items = buildLinkedThreadActionItems({ ...linkedThreads, query, icon: null, runThread });    const groups = filterCommandPaletteGroups({      activeGroups: [],      query,      isInSubmenu: false,      projectSearchItems: [],      settingsSearchItems: [],      threadSearchItems: items,    });    expect(groups.flatMap((group) => group.items)).toEqual(items);    expect(items[0]?.description).toBe("Archived thread");    await items[0]?.run();    expect(runThread).toHaveBeenCalledWith({ environmentId, id });  });}); describe("buildCommandPaletteProjectMetadata", () => {  const localEnvironmentId = EnvironmentId.make("environment-local");  const remoteEnvironmentId = EnvironmentId.make("environment-build-box");  const locations = new Map([    [localEnvironmentId, { kind: "local" as const, label: "Local", machine: "laptop" as const }],    [      remoteEnvironmentId,      { kind: "remote" as const, label: "Build box", machine: "server" as const },    ],  ]);   it("makes every member environment and path searchable", () => {    const metadata = buildCommandPaletteProjectMetadata({      projects: [        {          environmentId: localEnvironmentId,          title: "T3 Code",          workspaceRoot: "/Users/theo/Projects/t3code",        },        {          environmentId: remoteEnvironmentId,          title: "t3code",          workspaceRoot: "/srv/t3code",        },      ],      locationByEnvironmentId: locations,    });     expect(metadata.searchTerms).toEqual([      "T3 Code",      "/Users/theo/Projects/t3code",      "Local",      "t3code",      "/srv/t3code",      "Build box",    ]);    expect(metadata.environmentLabels).toEqual(["Local", "Build box"]);     const [filteredGroup] = filterCommandPaletteGroups({      activeGroups: [],      query: "build box",      isInSubmenu: false,      projectSearchItems: [        {          kind: "action",          value: "project:t3code",          title: "T3 Code",          searchTerms: metadata.searchTerms,          icon: null,          run: async () => undefined,        },      ],      threadSearchItems: [],    });    expect(filteredGroup?.items).toHaveLength(1);  });   it("deduplicates grouped checkouts by environment", () => {    const metadata = buildCommandPaletteProjectMetadata({      projects: [        {          environmentId: remoteEnvironmentId,          title: "T3 Code",          workspaceRoot: "/srv/t3code",        },        {          environmentId: remoteEnvironmentId,          title: "T3 Code worktree",          workspaceRoot: "/srv/t3code-feature",        },      ],      locationByEnvironmentId: locations,    });     expect(metadata.environmentLabels).toEqual(["Build box"]);  });   it("deduplicates distinct environments with the same label", () => {    const secondRemoteEnvironmentId = EnvironmentId.make("environment-build-box-2");    const metadata = buildCommandPaletteProjectMetadata({      projects: [        {          environmentId: remoteEnvironmentId,          title: "T3 Code",          workspaceRoot: "/srv/t3code",        },        {          environmentId: secondRemoteEnvironmentId,          title: "T3 Code mirror",          workspaceRoot: "/srv/mirror/t3code",        },      ],      locationByEnvironmentId: new Map([        [remoteEnvironmentId, { label: "Build box" }],        [secondRemoteEnvironmentId, { label: "Build box" }],      ]),    });     expect(metadata.environmentLabels).toEqual(["Build box"]);  });   it("uses a human-readable fallback when presentation data is unavailable", () => {    const metadata = buildCommandPaletteProjectMetadata({      projects: [        {          environmentId: remoteEnvironmentId,          title: "T3 Code",          workspaceRoot: "/srv/t3code",        },      ],      locationByEnvironmentId: new Map(),    });     expect(metadata.searchTerms).toContain("Remote");    expect(metadata.environmentLabels).toEqual(["Remote"]);  });}); describe("reduceCommandPaletteUiState", () => {  const closedState = { open: false, mode: "command", openIntent: null } as const;   it("toggles each overlay mode open and closed", () => {    const filesOpen = reduceCommandPaletteUiState(closedState, {      _tag: "ToggleMode",      mode: "files",    });    expect(filesOpen).toEqual({ open: true, mode: "files", openIntent: null });     const contentOpen = reduceCommandPaletteUiState(filesOpen, {      _tag: "ToggleMode",      mode: "content",    });    expect(contentOpen).toEqual({ open: true, mode: "content", openIntent: null });     expect(      reduceCommandPaletteUiState(contentOpen, { _tag: "ToggleMode", mode: "content" }),    ).toEqual({ open: false, mode: "content", openIntent: null });  });   it("switches between open modes without closing", () => {    const filesOpen = reduceCommandPaletteUiState(closedState, {      _tag: "ToggleMode",      mode: "files",    });    expect(reduceCommandPaletteUiState(filesOpen, { _tag: "ToggleMode", mode: "command" })).toEqual(      {        open: true,        mode: "command",        openIntent: null,      },    );  });   it("opens PR search from another overlay and replaces an earlier search", () => {    const first = reduceCommandPaletteUiState(      { open: true, mode: "files", openIntent: null },      {        _tag: "OpenSearch",        query: "https://github.com/acme/web/pull/7",      },    );    expect(first).toEqual({      open: true,      mode: "command",      openIntent: { kind: "search", query: "https://github.com/acme/web/pull/7" },    });    const second = reduceCommandPaletteUiState(first, {      _tag: "OpenSearch",      query: "https://github.com/acme/web/pull/8",    });    expect(second.openIntent).toEqual({      kind: "search",      query: "https://github.com/acme/web/pull/8",    });    expect(      reduceCommandPaletteUiState(second, { _tag: "SetOpen", open: false }).openIntent,    ).toBeNull();  });   it("routes open intents to command mode", () => {    const filesOpen = reduceCommandPaletteUiState(closedState, {      _tag: "ToggleMode",      mode: "files",    });    expect(reduceCommandPaletteUiState(filesOpen, { _tag: "OpenAddProject" })).toEqual({      open: true,      mode: "command",      openIntent: { kind: "add-project" },    });    expect(reduceCommandPaletteUiState(filesOpen, { _tag: "OpenNewThreadIn" })).toEqual({      open: true,      mode: "command",      openIntent: { kind: "new-thread-in" },    });  });   it("preserves the mode on close and resets it on open", () => {    const filesOpen = reduceCommandPaletteUiState(closedState, {      _tag: "ToggleMode",      mode: "files",    });     expect(reduceCommandPaletteUiState(filesOpen, { _tag: "SetOpen", open: false })).toEqual({      open: false,      mode: "files",      openIntent: null,    });    expect(reduceCommandPaletteUiState(filesOpen, { _tag: "SetOpen", open: true })).toEqual({      open: true,      mode: "command",      openIntent: null,    });  });}); describe("enumerateCommandPaletteItems", () => {  it("assigns positional jump shortcuts to the first nine displayed items", () => {    const items = Array.from({ length: 10 }, (_, index) => ({      kind: "action" as const,      value: `project-${index + 1}`,      searchTerms: [],      title: `Project ${index + 1}`,      icon: null,      shortcutCommand: "chat.new" as const,      run: async () => undefined,    }));     expect(enumerateCommandPaletteItems(items).map((item) => item.shortcutCommand)).toEqual([      "thread.jump.1",      "thread.jump.2",      "thread.jump.3",      "thread.jump.4",      "thread.jump.5",      "thread.jump.6",      "thread.jump.7",      "thread.jump.8",      "thread.jump.9",      undefined,    ]);  });}); const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local");const PROJECT_ID = ProjectId.make("project-1"); function makeProject(overrides: Partial<Project> = {}): Project {  return {    id: PROJECT_ID,    environmentId: LOCAL_ENVIRONMENT_ID,    title: "Project",    workspaceRoot: "/workspace/project",    defaultModelSelection: null,    scripts: [],    createdAt: "2026-03-01T00:00:00.000Z",    updatedAt: "2026-03-01T00:00:00.000Z",    ...overrides,  };} function makeThread(overrides: Partial<Thread> = {}): Thread {  return {    id: ThreadId.make("thread-1"),    environmentId: LOCAL_ENVIRONMENT_ID,    projectId: PROJECT_ID,    title: "Thread",    modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5" },    runtimeMode: "full-access",    interactionMode: "default",    session: null,    messages: [],    proposedPlans: [],    createdAt: "2026-03-01T00:00:00.000Z",    archivedAt: null,    settledOverride: null,    settledAt: null,    deletedAt: null,    updatedAt: "2026-03-01T00:00:00.000Z",    latestTurn: null,    branch: null,    worktreePath: null,    checkpoints: [],    pullRequests: [],    activities: [],    ...overrides,  };} describe("buildProjectActionItems", () => {  it("shows the grouped display name but keeps the real title for icons", () => {    const project = makeProject({ title: "fleet", workspaceRoot: "/Users/theo/Code/p/fleet" });    const iconTitles: string[] = [];    const [item] = buildProjectActionItems({      projects: [{ ...project, displayName: "t3dotgg/fleet" }],      valuePrefix: "project",      icon: (candidate) => {        iconTitles.push(candidate.title);        return null;      },      runProject: async () => undefined,    });     expect(item?.title).toBe("t3dotgg/fleet");    expect(item?.searchTerms).toEqual(      expect.arrayContaining(["t3dotgg/fleet", "fleet", "/Users/theo/Code/p/fleet"]),    );    expect(iconTitles).toEqual(["fleet"]);  });}); describe("buildThreadActionItems", () => {  it("orders threads by most recent activity and formats timestamps from updatedAt", () => {    vi.useFakeTimers();    vi.setSystemTime(new Date("2026-03-25T12:00:00.000Z"));     try {      const items = buildThreadActionItems({        threads: [          makeThread({            id: ThreadId.make("thread-older"),            title: "Older thread",            updatedAt: "2026-03-24T12:00:00.000Z",          }),          makeThread({            id: ThreadId.make("thread-newer"),            title: "Newer thread",            createdAt: "2026-03-20T00:00:00.000Z",            updatedAt: "2026-03-20T00:00:00.000Z",          }),        ],        projectTitleById: new Map([[PROJECT_ID, "Project"]]),        sortOrder: "updated_at",        icon: null,        runThread: async (_thread) => undefined,      });       expect(items.map((item) => item.value)).toEqual([        "thread:thread-older",        "thread:thread-newer",      ]);      expect(items[0]?.timestamp).toBe("1d ago");      expect(items[1]?.timestamp).toBe("5d ago");    } finally {      vi.useRealTimers();    }  });   it("ranks thread title matches ahead of contextual project-name matches", () => {    const threadItems = buildThreadActionItems({      threads: [        makeThread({          id: ThreadId.make("thread-context-match"),          title: "Fix navbar spacing",          updatedAt: "2026-03-20T00:00:00.000Z",        }),        makeThread({          id: ThreadId.make("thread-title-match"),          title: "Project kickoff notes",          createdAt: "2026-03-02T00:00:00.000Z",          updatedAt: "2026-03-19T00:00:00.000Z",        }),      ],      projectTitleById: new Map([[PROJECT_ID, "Project"]]),      sortOrder: "updated_at",      icon: null,      runThread: async (_thread) => undefined,    });     const groups = filterCommandPaletteGroups({      activeGroups: [],      query: "project",      isInSubmenu: false,      projectSearchItems: [],      threadSearchItems: threadItems,    });     expect(groups).toHaveLength(1);    expect(groups[0]?.value).toBe("threads-search");    expect(groups[0]?.items.map((item) => item.value)).toEqual([      "thread:thread-title-match",      "thread:thread-context-match",    ]);  });   it("preserves thread project-name matches when there is no stronger title match", () => {    const group: CommandPaletteGroup = {      value: "threads-search",      label: "Threads",      items: [        {          kind: "action",          value: "thread:project-context-only",          searchTerms: ["Fix navbar spacing", "Project"],          title: "Fix navbar spacing",          description: "Project",          icon: null,          run: async () => undefined,        },      ],    };     const groups = filterCommandPaletteGroups({      activeGroups: [group],      query: "project",      isInSubmenu: false,      projectSearchItems: [],      threadSearchItems: [],    });     expect(groups).toHaveLength(1);    expect(groups[0]?.items.map((item) => item.value)).toEqual(["thread:project-context-only"]);  });   it("ranks an order-independent setting title match above a split context match", () => {    const settingsSearchItems = [      {        kind: "action" as const,        value: "setting:context-match",        searchTerms: ["Pairing settings", "remote backend"],        title: "Context match",        icon: null,        run: async () => undefined,      },      {        kind: "action" as const,        value: "setting:remote-pairing",        searchTerms: ["Remote pairing", "connections"],        title: "Remote pairing",        icon: null,        run: async () => undefined,      },    ];     const groups = filterCommandPaletteGroups({      activeGroups: [],      query: "pairing remote",      isInSubmenu: false,      projectSearchItems: [],      settingsSearchItems,      threadSearchItems: [],    });     expect(groups).toHaveLength(1);

Lines 1–500 of 740.