97 lines · 3.5 KB · TypeScript
RawDownload
import { describe, expect, it } from "vitest"; import { DEFAULT_THREAD_TERMINAL_HEIGHT, DEFAULT_THREAD_TERMINAL_ID, type Thread } from "./types";import { formatWorktreePathForDisplay, getOrphanedWorktreePathForThread } from "./worktreeCleanup"; function makeThread(overrides: Partial<Thread> = {}): Thread {  return {    id: "thread-1",    codexThreadId: null,    projectId: "project-1",    title: "Thread",    model: "gpt-5.3-codex",    terminalOpen: false,    terminalHeight: DEFAULT_THREAD_TERMINAL_HEIGHT,    terminalIds: [DEFAULT_THREAD_TERMINAL_ID],    runningTerminalIds: [],    activeTerminalId: DEFAULT_THREAD_TERMINAL_ID,    terminalGroups: [      {        id: `group-${DEFAULT_THREAD_TERMINAL_ID}`,        terminalIds: [DEFAULT_THREAD_TERMINAL_ID],      },    ],    activeTerminalGroupId: `group-${DEFAULT_THREAD_TERMINAL_ID}`,    session: null,    messages: [],    events: [],    error: null,    createdAt: "2026-02-13T00:00:00.000Z",    branch: null,    worktreePath: null,    ...overrides,  };} describe("getOrphanedWorktreePathForThread", () => {  it("returns null when the target thread does not exist", () => {    const result = getOrphanedWorktreePathForThread([], "missing-thread");    expect(result).toBeNull();  });   it("returns null when the target thread has no worktree", () => {    const threads = [makeThread()];    const result = getOrphanedWorktreePathForThread(threads, "thread-1");    expect(result).toBeNull();  });   it("returns the path when no other thread links to that worktree", () => {    const threads = [makeThread({ worktreePath: "/tmp/repo/worktrees/feature-a" })];    const result = getOrphanedWorktreePathForThread(threads, "thread-1");    expect(result).toBe("/tmp/repo/worktrees/feature-a");  });   it("returns null when another thread links to the same worktree", () => {    const threads = [      makeThread({ id: "thread-1", worktreePath: "/tmp/repo/worktrees/feature-a" }),      makeThread({ id: "thread-2", worktreePath: "/tmp/repo/worktrees/feature-a" }),    ];    const result = getOrphanedWorktreePathForThread(threads, "thread-1");    expect(result).toBeNull();  });   it("ignores threads linked to different worktrees", () => {    const threads = [      makeThread({ id: "thread-1", worktreePath: "/tmp/repo/worktrees/feature-a" }),      makeThread({ id: "thread-2", worktreePath: "/tmp/repo/worktrees/feature-b" }),    ];    const result = getOrphanedWorktreePathForThread(threads, "thread-1");    expect(result).toBe("/tmp/repo/worktrees/feature-a");  });}); describe("formatWorktreePathForDisplay", () => {  it("shows only the last path segment for unix-like paths", () => {    const result = formatWorktreePathForDisplay(      "/Users/julius/.t3/worktrees/codething-mvp/codething-4e609bb8",    );    expect(result).toBe("codething-4e609bb8");  });   it("normalizes windows separators before selecting the final segment", () => {    const result = formatWorktreePathForDisplay(      "C:\\Users\\julius\\.t3\\worktrees\\codething-mvp\\codething-4e609bb8",    );    expect(result).toBe("codething-4e609bb8");  });   it("uses the final segment even when outside ~/.t3/worktrees", () => {    const result = formatWorktreePathForDisplay("/tmp/custom-worktrees/my-worktree");    expect(result).toBe("my-worktree");  });   it("ignores trailing slashes", () => {    const result = formatWorktreePathForDisplay("/tmp/custom-worktrees/my-worktree/");    expect(result).toBe("my-worktree");  });});