@akiojin/gwt 2.9.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +4 -37
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/common/Input.d.ts +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts +1 -2
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js +19 -14
- package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/ModelSelectorScreen.js +6 -6
- package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/PRCleanupScreen.js +0 -3
- package/dist/cli/ui/components/screens/PRCleanupScreen.js.map +1 -1
- package/dist/cli/ui/hooks/useGitData.d.ts.map +1 -1
- package/dist/cli/ui/hooks/useGitData.js +43 -2
- package/dist/cli/ui/hooks/useGitData.js.map +1 -1
- package/dist/cli/ui/types.d.ts +16 -4
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.js +124 -15
- package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
- package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
- package/dist/cli/ui/utils/modelOptions.js.map +1 -1
- package/dist/client/assets/{index-CNWntAlF.js → index-Dl798X5w.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/git.d.ts +6 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +40 -5
- package/dist/git.js.map +1 -1
- package/dist/web/client/src/components/BranchGraph.js +1 -1
- package/dist/web/client/src/components/BranchGraph.js.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.js +8 -3
- package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
- package/dist/web/server/routes/sessions.d.ts.map +1 -1
- package/dist/web/server/routes/sessions.js +4 -2
- package/dist/web/server/routes/sessions.js.map +1 -1
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +69 -62
- package/dist/worktree.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +9 -17
- package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +77 -83
- package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +107 -160
- package/src/cli/ui/__tests__/components/App.test.tsx +108 -84
- package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +12 -5
- package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/common/Input.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +15 -14
- package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +3 -3
- package/src/cli/ui/__tests__/components/common/Select.test.tsx +1 -4
- package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/parts/Header.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +31 -41
- package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +3 -2
- package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +3 -2
- package/src/cli/ui/__tests__/hooks/useScreenState.test.ts +18 -17
- package/src/cli/ui/__tests__/hooks/useTerminalSize.test.ts +3 -2
- package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +61 -41
- package/src/cli/ui/__tests__/integration/navigation.test.tsx +15 -10
- package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +3 -2
- package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +0 -4
- package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +3 -5
- package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +24 -22
- package/src/cli/ui/components/App.tsx +5 -63
- package/src/cli/ui/components/common/Input.tsx +1 -1
- package/src/cli/ui/components/screens/BranchListScreen.tsx +32 -22
- package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +46 -49
- package/src/cli/ui/components/screens/PRCleanupScreen.tsx +0 -3
- package/src/cli/ui/hooks/useGitData.ts +59 -1
- package/src/cli/ui/screens/__tests__/BranchActionSelectorScreen.test.tsx +3 -2
- package/src/cli/ui/types.ts +24 -5
- package/src/cli/ui/utils/branchFormatter.ts +123 -15
- package/src/cli/ui/utils/modelOptions.test.ts +4 -6
- package/src/cli/ui/utils/modelOptions.ts +1 -2
- package/src/config/index.ts +2 -1
- package/src/git.ts +56 -16
- package/src/index.test.ts +1 -1
- package/src/web/client/src/components/BranchGraph.tsx +1 -1
- package/src/web/client/src/pages/BranchDetailPage.tsx +8 -3
- package/src/web/server/routes/sessions.ts +12 -5
- package/src/worktree.ts +80 -91
- package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts +0 -20
- package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts.map +0 -1
- package/dist/cli/ui/components/screens/WorktreeManagerScreen.js +0 -65
- package/dist/cli/ui/components/screens/WorktreeManagerScreen.js.map +0 -1
- package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +0 -151
- package/src/cli/ui/components/screens/WorktreeManagerScreen.tsx +0 -117
|
@@ -1,36 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @vitest-environment happy-dom
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
it,
|
|
7
|
-
expect,
|
|
8
|
-
beforeEach,
|
|
9
|
-
afterEach,
|
|
10
|
-
afterAll,
|
|
11
|
-
vi,
|
|
12
|
-
} from "vitest";
|
|
13
|
-
import { act, render } from "@testing-library/react";
|
|
4
|
+
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
5
|
+
import { render } from "@testing-library/react";
|
|
14
6
|
import React from "react";
|
|
15
|
-
import { App } from "../../components/App.js";
|
|
16
7
|
import { Window } from "happy-dom";
|
|
17
|
-
import type { BranchInfo } from "../../types.js";
|
|
18
|
-
import
|
|
8
|
+
import type { BranchInfo, BranchItem } from "../../types.js";
|
|
9
|
+
import type { BranchListScreenProps } from "../../components/screens/BranchListScreen.js";
|
|
19
10
|
|
|
20
11
|
const mockRefresh = vi.fn();
|
|
21
|
-
|
|
22
|
-
const
|
|
12
|
+
let App: typeof import("../../components/App.js").App;
|
|
13
|
+
const branchListProps: BranchListScreenProps[] = [];
|
|
14
|
+
const useGitDataMock = vi.fn();
|
|
15
|
+
|
|
16
|
+
vi.mock("../../hooks/useGitData.js", () => ({
|
|
17
|
+
useGitData: (...args: unknown[]) => useGitDataMock(...args),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
vi.mock("../../components/screens/BranchListScreen.js", () => {
|
|
21
|
+
return {
|
|
22
|
+
BranchListScreen: (props: BranchListScreenProps) => {
|
|
23
|
+
branchListProps.push(props);
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<div>gwt - Branch Selection</div>
|
|
27
|
+
<div>Local: {props.stats?.localCount ?? 0}</div>
|
|
28
|
+
<div>Remote: {props.stats?.remoteCount ?? 0}</div>
|
|
29
|
+
<div>Worktrees: {props.stats?.worktreeCount ?? 0}</div>
|
|
30
|
+
<div>Changes: {props.stats?.changesCount ?? 0}</div>
|
|
31
|
+
{props.loading && <div>Loading Git information</div>}
|
|
32
|
+
{props.error && <div>Error: {props.error.message}</div>}
|
|
33
|
+
{!props.loading && !props.error && props.branches.length === 0 && (
|
|
34
|
+
<div>No branches found</div>
|
|
35
|
+
)}
|
|
36
|
+
<ul>
|
|
37
|
+
{props.branches.map((branch) => (
|
|
38
|
+
<li
|
|
39
|
+
key={branch.name}
|
|
40
|
+
>{`${branch.icons?.join("") ?? ""} ${branch.name}`}</li>
|
|
41
|
+
))}
|
|
42
|
+
</ul>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
});
|
|
23
48
|
|
|
24
49
|
describe("App", () => {
|
|
25
|
-
beforeEach(() => {
|
|
50
|
+
beforeEach(async () => {
|
|
26
51
|
// Setup happy-dom
|
|
27
52
|
const window = new Window();
|
|
28
|
-
globalThis.window = window as
|
|
29
|
-
globalThis.document =
|
|
53
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
54
|
+
globalThis.document =
|
|
55
|
+
window.document as unknown as typeof globalThis.document;
|
|
30
56
|
|
|
31
57
|
vi.clearAllMocks();
|
|
32
|
-
|
|
33
|
-
|
|
58
|
+
useGitDataMock.mockReset();
|
|
59
|
+
branchListProps.length = 0;
|
|
60
|
+
App = (await import("../../components/App.js")).App;
|
|
34
61
|
});
|
|
35
62
|
|
|
36
63
|
const mockBranches: BranchInfo[] = [
|
|
@@ -49,61 +76,61 @@ describe("App", () => {
|
|
|
49
76
|
];
|
|
50
77
|
|
|
51
78
|
it("should render BranchListScreen when data is loaded", () => {
|
|
52
|
-
|
|
79
|
+
useGitDataMock.mockImplementation(() => ({
|
|
53
80
|
branches: mockBranches,
|
|
54
81
|
loading: false,
|
|
55
82
|
error: null,
|
|
56
83
|
worktrees: [],
|
|
57
84
|
refresh: mockRefresh,
|
|
58
|
-
});
|
|
85
|
+
}));
|
|
59
86
|
|
|
60
87
|
const onExit = vi.fn();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
expect(
|
|
66
|
-
expect(
|
|
88
|
+
render(<App onExit={onExit} />);
|
|
89
|
+
|
|
90
|
+
expect(branchListProps).not.toHaveLength(0);
|
|
91
|
+
const props = branchListProps.at(-1);
|
|
92
|
+
expect(props?.loading).toBe(false);
|
|
93
|
+
expect(props?.error).toBeNull();
|
|
94
|
+
const branchNames = props?.branches.map((b) => b.name);
|
|
95
|
+
expect(branchNames).toContain("main");
|
|
96
|
+
expect(branchNames).toContain("feature/test");
|
|
67
97
|
});
|
|
68
98
|
|
|
69
99
|
it("should show loading state initially", async () => {
|
|
70
|
-
|
|
100
|
+
useGitDataMock.mockImplementation(() => ({
|
|
71
101
|
branches: [],
|
|
72
102
|
loading: true,
|
|
73
103
|
error: null,
|
|
74
104
|
worktrees: [],
|
|
75
105
|
refresh: mockRefresh,
|
|
76
|
-
});
|
|
106
|
+
}));
|
|
77
107
|
|
|
78
108
|
const onExit = vi.fn();
|
|
79
|
-
|
|
80
|
-
<App onExit={onExit} loadingIndicatorDelay={10} />,
|
|
81
|
-
);
|
|
109
|
+
render(<App onExit={onExit} loadingIndicatorDelay={10} />);
|
|
82
110
|
|
|
83
|
-
expect(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
expect(getByText(/Loading Git information/i)).toBeDefined();
|
|
111
|
+
expect(branchListProps).not.toHaveLength(0);
|
|
112
|
+
const props = branchListProps.at(-1);
|
|
113
|
+
expect(props?.loading).toBe(true);
|
|
114
|
+
expect(props?.loadingIndicatorDelay).toBe(10);
|
|
90
115
|
});
|
|
91
116
|
|
|
92
117
|
it("should show error state when Git data fails to load", () => {
|
|
93
118
|
const error = new Error("Failed to fetch branches");
|
|
94
|
-
|
|
119
|
+
useGitDataMock.mockImplementation(() => ({
|
|
95
120
|
branches: [],
|
|
96
121
|
loading: false,
|
|
97
122
|
error,
|
|
98
123
|
worktrees: [],
|
|
99
124
|
refresh: mockRefresh,
|
|
100
|
-
});
|
|
125
|
+
}));
|
|
101
126
|
|
|
102
127
|
const onExit = vi.fn();
|
|
103
|
-
|
|
128
|
+
render(<App onExit={onExit} />);
|
|
104
129
|
|
|
105
|
-
expect(
|
|
106
|
-
|
|
130
|
+
expect(branchListProps).not.toHaveLength(0);
|
|
131
|
+
const props = branchListProps.at(-1);
|
|
132
|
+
expect(props?.error?.message).toBe("Failed to fetch branches");
|
|
133
|
+
expect(props?.loading).toBe(false);
|
|
107
134
|
});
|
|
108
135
|
|
|
109
136
|
it("should calculate statistics from branches", () => {
|
|
@@ -133,67 +160,71 @@ describe("App", () => {
|
|
|
133
160
|
},
|
|
134
161
|
];
|
|
135
162
|
|
|
136
|
-
|
|
163
|
+
useGitDataMock.mockImplementation(() => ({
|
|
137
164
|
branches: branchesWithWorktree,
|
|
138
165
|
loading: false,
|
|
139
166
|
error: null,
|
|
140
167
|
worktrees: [],
|
|
141
168
|
refresh: mockRefresh,
|
|
142
|
-
});
|
|
169
|
+
}));
|
|
143
170
|
|
|
144
171
|
const onExit = vi.fn();
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
expect(
|
|
150
|
-
expect(
|
|
151
|
-
expect(
|
|
152
|
-
expect(getByText(/Worktrees:/)).toBeDefined();
|
|
172
|
+
render(<App onExit={onExit} />);
|
|
173
|
+
|
|
174
|
+
expect(branchListProps).not.toHaveLength(0);
|
|
175
|
+
const props = branchListProps.at(-1);
|
|
176
|
+
expect(props?.stats.localCount).toBe(2);
|
|
177
|
+
expect(props?.stats.remoteCount).toBe(1);
|
|
178
|
+
expect(props?.stats.worktreeCount).toBe(1);
|
|
153
179
|
});
|
|
154
180
|
|
|
155
|
-
it("should
|
|
156
|
-
|
|
181
|
+
it("should render branch selection without triggering exit", () => {
|
|
182
|
+
useGitDataMock.mockImplementation(() => ({
|
|
157
183
|
branches: mockBranches,
|
|
158
184
|
loading: false,
|
|
159
185
|
error: null,
|
|
160
186
|
worktrees: [],
|
|
161
187
|
refresh: mockRefresh,
|
|
162
|
-
});
|
|
188
|
+
}));
|
|
163
189
|
|
|
164
190
|
const onExit = vi.fn();
|
|
165
191
|
const { container } = render(<App onExit={onExit} />);
|
|
166
192
|
|
|
167
193
|
expect(container).toBeDefined();
|
|
194
|
+
expect(onExit).not.toHaveBeenCalled();
|
|
168
195
|
// Note: Testing actual selection requires simulating user input,
|
|
169
196
|
// which is covered in integration tests
|
|
170
197
|
});
|
|
171
198
|
|
|
172
199
|
it("should handle empty branch list", () => {
|
|
173
|
-
|
|
200
|
+
useGitDataMock.mockImplementation(() => ({
|
|
174
201
|
branches: [],
|
|
175
202
|
loading: false,
|
|
176
203
|
error: null,
|
|
177
204
|
worktrees: [],
|
|
178
205
|
refresh: mockRefresh,
|
|
179
|
-
});
|
|
206
|
+
}));
|
|
180
207
|
|
|
181
208
|
const onExit = vi.fn();
|
|
182
|
-
|
|
209
|
+
render(<App onExit={onExit} />);
|
|
183
210
|
|
|
184
|
-
expect(
|
|
211
|
+
expect(branchListProps).not.toHaveLength(0);
|
|
212
|
+
const props = branchListProps.at(-1);
|
|
213
|
+
expect(props?.branches).toHaveLength(0);
|
|
214
|
+
expect(props?.loading).toBe(false);
|
|
215
|
+
expect(props?.error).toBeNull();
|
|
185
216
|
});
|
|
186
217
|
|
|
187
218
|
it("should wrap with ErrorBoundary", () => {
|
|
188
219
|
// This test verifies ErrorBoundary is present
|
|
189
220
|
// Actual error catching is tested separately
|
|
190
|
-
|
|
221
|
+
useGitDataMock.mockImplementation(() => ({
|
|
191
222
|
branches: mockBranches,
|
|
192
223
|
loading: false,
|
|
193
224
|
error: null,
|
|
194
225
|
worktrees: [],
|
|
195
226
|
refresh: mockRefresh,
|
|
196
|
-
});
|
|
227
|
+
}));
|
|
197
228
|
|
|
198
229
|
const onExit = vi.fn();
|
|
199
230
|
const { container } = render(<App onExit={onExit} />);
|
|
@@ -202,30 +233,32 @@ describe("App", () => {
|
|
|
202
233
|
});
|
|
203
234
|
|
|
204
235
|
it("should format branch items with icons", () => {
|
|
205
|
-
|
|
236
|
+
useGitDataMock.mockImplementation(() => ({
|
|
206
237
|
branches: mockBranches,
|
|
207
238
|
loading: false,
|
|
208
239
|
error: null,
|
|
209
240
|
worktrees: [],
|
|
210
241
|
refresh: mockRefresh,
|
|
211
|
-
});
|
|
242
|
+
}));
|
|
212
243
|
|
|
213
244
|
const onExit = vi.fn();
|
|
214
|
-
|
|
245
|
+
render(<App onExit={onExit} />);
|
|
215
246
|
|
|
216
|
-
|
|
217
|
-
|
|
247
|
+
expect(branchListProps).not.toHaveLength(0);
|
|
248
|
+
const props = branchListProps.at(-1);
|
|
249
|
+
const main = props?.branches.find((b: BranchItem) => b.name === "main");
|
|
250
|
+
expect(main?.icons).toContain("⚡");
|
|
218
251
|
});
|
|
219
252
|
|
|
220
253
|
describe("BranchActionSelectorScreen integration", () => {
|
|
221
254
|
it("should show BranchActionSelectorScreen after branch selection", () => {
|
|
222
|
-
|
|
255
|
+
useGitDataMock.mockImplementation(() => ({
|
|
223
256
|
branches: mockBranches,
|
|
224
257
|
loading: false,
|
|
225
258
|
error: null,
|
|
226
259
|
worktrees: [],
|
|
227
260
|
refresh: mockRefresh,
|
|
228
|
-
});
|
|
261
|
+
}));
|
|
229
262
|
|
|
230
263
|
const onExit = vi.fn();
|
|
231
264
|
const { container } = render(<App onExit={onExit} />);
|
|
@@ -235,13 +268,13 @@ describe("App", () => {
|
|
|
235
268
|
});
|
|
236
269
|
|
|
237
270
|
it('should navigate to AI tool selector when "use existing" is selected', () => {
|
|
238
|
-
|
|
271
|
+
useGitDataMock.mockImplementation(() => ({
|
|
239
272
|
branches: mockBranches,
|
|
240
273
|
loading: false,
|
|
241
274
|
error: null,
|
|
242
275
|
worktrees: [],
|
|
243
276
|
refresh: mockRefresh,
|
|
244
|
-
});
|
|
277
|
+
}));
|
|
245
278
|
|
|
246
279
|
const onExit = vi.fn();
|
|
247
280
|
const { container } = render(<App onExit={onExit} />);
|
|
@@ -251,13 +284,13 @@ describe("App", () => {
|
|
|
251
284
|
});
|
|
252
285
|
|
|
253
286
|
it('should navigate to branch creator when "create new" is selected', () => {
|
|
254
|
-
|
|
287
|
+
useGitDataMock.mockImplementation(() => ({
|
|
255
288
|
branches: mockBranches,
|
|
256
289
|
loading: false,
|
|
257
290
|
error: null,
|
|
258
291
|
worktrees: [],
|
|
259
292
|
refresh: mockRefresh,
|
|
260
|
-
});
|
|
293
|
+
}));
|
|
261
294
|
|
|
262
295
|
const onExit = vi.fn();
|
|
263
296
|
const { container } = render(<App onExit={onExit} />);
|
|
@@ -266,13 +299,4 @@ describe("App", () => {
|
|
|
266
299
|
expect(container).toBeDefined();
|
|
267
300
|
});
|
|
268
301
|
});
|
|
269
|
-
|
|
270
|
-
afterEach(() => {
|
|
271
|
-
useGitDataSpy.mockReset();
|
|
272
|
-
useGitDataSpy.mockImplementation(originalUseGitData);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
afterAll(() => {
|
|
277
|
-
useGitDataSpy.mockRestore();
|
|
278
302
|
});
|
|
@@ -7,16 +7,22 @@ import { render, waitFor } from "@testing-library/react";
|
|
|
7
7
|
import { ModelSelectorScreen } from "../../components/screens/ModelSelectorScreen.js";
|
|
8
8
|
import type { ModelSelectionResult } from "../../components/screens/ModelSelectorScreen.js";
|
|
9
9
|
import { Window } from "happy-dom";
|
|
10
|
+
import type {
|
|
11
|
+
SelectProps,
|
|
12
|
+
SelectItem,
|
|
13
|
+
} from "../../components/common/Select.js";
|
|
10
14
|
|
|
11
|
-
const selectMocks:
|
|
15
|
+
const selectMocks: SelectProps<SelectItem>[] = [];
|
|
12
16
|
|
|
13
17
|
vi.mock("../../components/common/Select.js", () => {
|
|
14
18
|
return {
|
|
15
|
-
Select: (props:
|
|
19
|
+
Select: (props: SelectProps<SelectItem>) => {
|
|
16
20
|
selectMocks.push(props);
|
|
17
21
|
return React.createElement("div", {
|
|
18
22
|
"data-testid": "select-mock",
|
|
19
|
-
onClick: () =>
|
|
23
|
+
onClick: () =>
|
|
24
|
+
props.onSelect &&
|
|
25
|
+
props.onSelect(props.items[props.initialIndex ?? 0]),
|
|
20
26
|
});
|
|
21
27
|
},
|
|
22
28
|
};
|
|
@@ -26,8 +32,9 @@ describe("ModelSelectorScreen initial selection", () => {
|
|
|
26
32
|
beforeEach(() => {
|
|
27
33
|
selectMocks.length = 0;
|
|
28
34
|
const window = new Window();
|
|
29
|
-
globalThis.window = window as
|
|
30
|
-
globalThis.document =
|
|
35
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
36
|
+
globalThis.document =
|
|
37
|
+
window.document as unknown as typeof globalThis.document;
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
it("sets model list initialIndex based on previous selection", async () => {
|
|
@@ -11,8 +11,9 @@ describe("Confirm", () => {
|
|
|
11
11
|
beforeEach(() => {
|
|
12
12
|
// Setup happy-dom
|
|
13
13
|
const window = new Window();
|
|
14
|
-
globalThis.window = window as
|
|
15
|
-
globalThis.document =
|
|
14
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
15
|
+
globalThis.document =
|
|
16
|
+
window.document as unknown as typeof globalThis.document;
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
it("should render the message", () => {
|
|
@@ -20,8 +20,9 @@ describe("ErrorBoundary", () => {
|
|
|
20
20
|
beforeEach(() => {
|
|
21
21
|
// Setup happy-dom
|
|
22
22
|
const window = new Window();
|
|
23
|
-
globalThis.window = window as
|
|
24
|
-
globalThis.document =
|
|
23
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
24
|
+
globalThis.document =
|
|
25
|
+
window.document as unknown as typeof globalThis.document;
|
|
25
26
|
|
|
26
27
|
// Suppress console.error for expected errors in tests
|
|
27
28
|
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
@@ -11,8 +11,9 @@ describe("Input", () => {
|
|
|
11
11
|
beforeEach(() => {
|
|
12
12
|
// Setup happy-dom
|
|
13
13
|
const window = new Window();
|
|
14
|
-
globalThis.window = window as
|
|
15
|
-
globalThis.document =
|
|
14
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
15
|
+
globalThis.document =
|
|
16
|
+
window.document as unknown as typeof globalThis.document;
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
it("should render with value", () => {
|
|
@@ -24,8 +24,9 @@ beforeEach(() => {
|
|
|
24
24
|
vi.useFakeTimers();
|
|
25
25
|
}
|
|
26
26
|
const window = new Window();
|
|
27
|
-
globalThis.window = window as
|
|
28
|
-
globalThis.document =
|
|
27
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
28
|
+
globalThis.document =
|
|
29
|
+
window.document as unknown as typeof globalThis.document;
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
afterEach(() => {
|
|
@@ -78,18 +79,18 @@ describe("LoadingIndicator", () => {
|
|
|
78
79
|
|
|
79
80
|
expect(getMessageText(container)).toContain("Loading data");
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
await act(async () => {
|
|
83
|
+
rerender(
|
|
84
|
+
<LoadingIndicator
|
|
85
|
+
isLoading={false}
|
|
86
|
+
message="Loading data"
|
|
87
|
+
delay={10}
|
|
88
|
+
/>,
|
|
89
|
+
);
|
|
90
|
+
if (typeof vi.advanceTimersByTimeAsync === "function") {
|
|
91
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
93
94
|
|
|
94
95
|
expect(container.textContent).toBe("");
|
|
95
96
|
});
|
|
@@ -19,14 +19,14 @@ import { Select, type SelectItem } from "../../../components/common/Select.js";
|
|
|
19
19
|
describe.skip("Select Component React.memo (T082-2)", () => {
|
|
20
20
|
beforeEach(() => {
|
|
21
21
|
const window = new Window();
|
|
22
|
-
globalThis.window = window as
|
|
23
|
-
globalThis.document =
|
|
22
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
23
|
+
globalThis.document =
|
|
24
|
+
window.document as unknown as typeof globalThis.document;
|
|
24
25
|
vi.clearAllMocks();
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
it("should not re-render when items array reference changes but content is the same", () => {
|
|
28
29
|
const onSelect = vi.fn();
|
|
29
|
-
const renderCount = 0;
|
|
30
30
|
|
|
31
31
|
// Wrapper component to track renders
|
|
32
32
|
function TestWrapper() {
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @vitest-environment happy-dom
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import { describe, it, expect, vi } from "vitest";
|
|
6
6
|
import { render } from "ink-testing-library";
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { Select } from "../../../components/common/Select.js";
|
|
9
9
|
|
|
10
|
-
// Helper to wait for async updates
|
|
11
|
-
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
12
|
-
|
|
13
10
|
interface TestItem {
|
|
14
11
|
label: string;
|
|
15
12
|
value: string;
|
|
@@ -11,8 +11,9 @@ describe("Footer", () => {
|
|
|
11
11
|
beforeEach(() => {
|
|
12
12
|
// Setup happy-dom
|
|
13
13
|
const window = new Window();
|
|
14
|
-
globalThis.window = window as
|
|
15
|
-
globalThis.document =
|
|
14
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
15
|
+
globalThis.document =
|
|
16
|
+
window.document as unknown as typeof globalThis.document;
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
const mockActions = [
|
|
@@ -11,8 +11,9 @@ describe("Header", () => {
|
|
|
11
11
|
beforeEach(() => {
|
|
12
12
|
// Setup happy-dom
|
|
13
13
|
const window = new Window();
|
|
14
|
-
globalThis.window = window as
|
|
15
|
-
globalThis.document =
|
|
14
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
15
|
+
globalThis.document =
|
|
16
|
+
window.document as unknown as typeof globalThis.document;
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
it("should render title", () => {
|
|
@@ -12,8 +12,9 @@ describe("ScrollableList", () => {
|
|
|
12
12
|
beforeEach(() => {
|
|
13
13
|
// Setup happy-dom
|
|
14
14
|
const window = new Window();
|
|
15
|
-
globalThis.window = window as
|
|
16
|
-
globalThis.document =
|
|
15
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
16
|
+
globalThis.document =
|
|
17
|
+
window.document as unknown as typeof globalThis.document;
|
|
17
18
|
});
|
|
18
19
|
|
|
19
20
|
it("should render children", () => {
|
|
@@ -12,8 +12,9 @@ describe("Stats", () => {
|
|
|
12
12
|
beforeEach(() => {
|
|
13
13
|
// Setup happy-dom
|
|
14
14
|
const window = new Window();
|
|
15
|
-
globalThis.window = window as
|
|
16
|
-
globalThis.document =
|
|
15
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
16
|
+
globalThis.document =
|
|
17
|
+
window.document as unknown as typeof globalThis.document;
|
|
17
18
|
});
|
|
18
19
|
|
|
19
20
|
const mockStats: Statistics = {
|
|
@@ -27,8 +27,9 @@ describe("AIToolSelectorScreen", () => {
|
|
|
27
27
|
beforeEach(() => {
|
|
28
28
|
// Setup happy-dom
|
|
29
29
|
const window = new Window();
|
|
30
|
-
globalThis.window = window as
|
|
31
|
-
globalThis.document =
|
|
30
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
31
|
+
globalThis.document =
|
|
32
|
+
window.document as unknown as typeof globalThis.document;
|
|
32
33
|
});
|
|
33
34
|
|
|
34
35
|
it("should render header with title", () => {
|
|
@@ -13,8 +13,9 @@ describe("BranchCreatorScreen", () => {
|
|
|
13
13
|
vi.useFakeTimers();
|
|
14
14
|
// Setup happy-dom
|
|
15
15
|
const window = new Window();
|
|
16
|
-
globalThis.window = window as
|
|
17
|
-
globalThis.document =
|
|
16
|
+
globalThis.window = window as unknown as typeof globalThis.window;
|
|
17
|
+
globalThis.document =
|
|
18
|
+
window.document as unknown as typeof globalThis.document;
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
afterEach(() => {
|