1import type { EnvironmentId, T3ProjectFileScript, ThreadId } from "@t3tools/contracts";
2import { renderToStaticMarkup } from "react-dom/server";
3import { PopoverCreateHandle } from "../ui/popover";
4import { beforeEach, describe, expect, it, vi } from "vite-plus/test";
5
6const testState = vi.hoisted(() => ({
7 useT3ProjectFileScripts: vi.fn(),
8 projectScriptsControl: vi.fn(),
9}));
10
11vi.mock("../../hooks/useT3ProjectFileScripts", () => ({
12 useT3ProjectFileScripts: (...args: ReadonlyArray<unknown>) =>
13 testState.useT3ProjectFileScripts(...args),
14}));
15vi.mock("../BranchToolbar", () => ({
16 BranchToolbar: () => null,
17}));
18vi.mock("../ProjectScriptsControl", () => ({
19 default: (props: unknown) => {
20 testState.projectScriptsControl(props);
21 return null;
22 },
23}));
24vi.mock("./ThreadAutomationsPanel", () => ({
25 ThreadAutomationsPanel: () => null,
26}));
27vi.mock("./ThreadRelationshipsControl", () => ({
28 ThreadRelationshipsPanel: () => null,
29}));
30vi.mock("./ThreadDetailsCard", () => ({
31 ThreadDetailsCard: ({ children }: { children: (density: "full") => React.ReactNode }) =>
32 children("full"),
33}));
34
35import { ThreadDetailsPanel, type ThreadDetailsPanelProps } from "./ThreadDetailsPanel";
36
37describe("ThreadDetailsPanel", () => {
38 beforeEach(() => {
39 testState.useT3ProjectFileScripts.mockReset();
40 testState.projectScriptsControl.mockReset();
41 });
42
43 it("passes checked-in t3.json scripts to the project scripts control", () => {
44 const environmentId = "environment:thread-details" as EnvironmentId;
45 const gitCwd = "/tmp/thread-details-project";
46 const fileScripts = [
47 {
48 name: "Check project",
49 command: "vp check",
50 icon: "test",
51 },
52 ] satisfies ReadonlyArray<T3ProjectFileScript>;
53 testState.useT3ProjectFileScripts.mockReturnValue(fileScripts);
54
55 const props: ThreadDetailsPanelProps = {
56 anchor: { current: null },
57 handle: PopoverCreateHandle(),
58 onPresentationChange: vi.fn(),
59 environmentId,
60 threadId: "thread:thread-details" as ThreadId,
61 activeProjectName: undefined,
62 activeProjectScripts: [],
63 preferredScriptId: null,
64 keybindings: [],
65 availableEditors: [],
66 showOpenInPicker: false,
67 gitCwd,
68 isGitRepo: false,
69 envLocked: false,
70 availableEnvironments: [],
71 onEnvironmentChange: vi.fn(),
72 onEnvModeChange: vi.fn(),
73 envMode: "local",
74 startFromOrigin: false,
75 onStartFromOriginChange: vi.fn(),
76 onComposerFocusRequest: vi.fn(),
77 onRunProjectScript: vi.fn(),
78 onAddProjectScript: vi.fn() as ThreadDetailsPanelProps["onAddProjectScript"],
79 onUpdateProjectScript: vi.fn() as ThreadDetailsPanelProps["onUpdateProjectScript"],
80 onDeleteProjectScript: vi.fn() as ThreadDetailsPanelProps["onDeleteProjectScript"],
81 };
82
83 renderToStaticMarkup(<ThreadDetailsPanel {...props} />);
84
85 expect(testState.useT3ProjectFileScripts).toHaveBeenCalledWith(environmentId, gitCwd);
86 expect(testState.projectScriptsControl).toHaveBeenCalledWith(
87 expect.objectContaining({
88 displayMode: "panel",
89 scripts: [],
90 fileScripts,
91 }),
92 );
93 });
94});