Files
fusion/packages/dashboard/app/hooks/__tests__/useWorktrunkInstallStatus.test.ts
gsxdsm 6b19e36ca1 Address PR review feedback (#1889)
- probeWorktrunk: also refuse a bare wt/wt.exe override on Windows (resolves to
  Windows Terminal via PATH), and tighten the package-dir match from a broad
  'windowsterminal' substring to 'microsoft.windowsterminal' so a genuine
  worktrunk under an unrelated *windowsterminal* folder is still probed.
- Fix worktrunk enable deadlock/save-race: probe status when the user views the
  Worktrees section (not gated on 'enabled', which deadlocked since the toggle is
  disabled until status==installed), and re-verify on Save so a fast enable+save
  can't silently persist enabled:false. Hook 'refresh' now returns the fetched
  status and is exposed.
- Tests: bare-wt refusal, forward-slash Windows Terminal path, unrelated
  windowsterminal-folder is probed, and a rerender enabled false->true probe-once
  transition; update SettingsModal mocks for the new refresh().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 23:16:58 -07:00

62 lines
2.5 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import { renderHook, waitFor } from "@testing-library/react";
vi.mock("../../sse-bus", () => ({
subscribeSse: vi.fn(() => () => {}),
}));
import { useWorktrunkInstallStatus } from "../useWorktrunkInstallStatus";
/*
FNXC:WindowsTerminalStartup 2026-07-03-16:25:
The worktrunk status probe hits `GET /api/worktrunk/status`, which resolves +
probes the `wt` binary server-side; on Windows `wt` is Windows Terminal, so an
automatic probe on Settings mount pops its native version/Help dialog. The hook
must only auto-fetch when worktrunk integration is enabled (user opted in) —
never on a plain mount — so opening Settings can't trigger the dialog.
*/
describe("useWorktrunkInstallStatus", () => {
let fetchMock: ReturnType<typeof vi.fn>;
beforeEach(() => {
fetchMock = vi.fn(async () => ({
ok: true,
json: async () => ({ status: "installed", version: "0.4.2" }),
}));
vi.stubGlobal("fetch", fetchMock);
});
it("does not probe worktrunk status on mount when disabled", async () => {
renderHook(() => useWorktrunkInstallStatus("p1", { enabled: false }));
// Give any (incorrect) effect a chance to fire.
await new Promise((resolve) => setTimeout(resolve, 0));
expect(fetchMock).not.toHaveBeenCalled();
});
it("does not probe worktrunk status on mount when options are omitted", async () => {
renderHook(() => useWorktrunkInstallStatus("p1"));
await new Promise((resolve) => setTimeout(resolve, 0));
expect(fetchMock).not.toHaveBeenCalled();
});
it("probes worktrunk status on mount when enabled (user opted in)", async () => {
renderHook(() => useWorktrunkInstallStatus("p1", { enabled: true }));
await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1));
expect(String(fetchMock.mock.calls[0]?.[0])).toContain("/api/worktrunk/status");
});
it("probes exactly once when enabled flips false -> true live (the SettingsModal toggle path)", async () => {
const { rerender } = renderHook(
({ enabled }: { enabled: boolean }) => useWorktrunkInstallStatus("p1", { enabled }),
{ initialProps: { enabled: false } },
);
// No probe while disabled.
await new Promise((resolve) => setTimeout(resolve, 0));
expect(fetchMock).not.toHaveBeenCalled();
// Toggling on triggers exactly one probe.
rerender({ enabled: true });
await waitFor(() => expect(fetchMock).toHaveBeenCalledTimes(1));
expect(String(fetchMock.mock.calls[0]?.[0])).toContain("/api/worktrunk/status");
});
});