@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.
Files changed (98) hide show
  1. package/README.md +6 -0
  2. package/dist/cli/ui/components/App.d.ts.map +1 -1
  3. package/dist/cli/ui/components/App.js +4 -37
  4. package/dist/cli/ui/components/App.js.map +1 -1
  5. package/dist/cli/ui/components/common/Input.d.ts +1 -1
  6. package/dist/cli/ui/components/screens/BranchListScreen.d.ts +1 -2
  7. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  8. package/dist/cli/ui/components/screens/BranchListScreen.js +19 -14
  9. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  10. package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +1 -1
  11. package/dist/cli/ui/components/screens/ModelSelectorScreen.js +6 -6
  12. package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +1 -1
  13. package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts.map +1 -1
  14. package/dist/cli/ui/components/screens/PRCleanupScreen.js +0 -3
  15. package/dist/cli/ui/components/screens/PRCleanupScreen.js.map +1 -1
  16. package/dist/cli/ui/hooks/useGitData.d.ts.map +1 -1
  17. package/dist/cli/ui/hooks/useGitData.js +43 -2
  18. package/dist/cli/ui/hooks/useGitData.js.map +1 -1
  19. package/dist/cli/ui/types.d.ts +16 -4
  20. package/dist/cli/ui/types.d.ts.map +1 -1
  21. package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
  22. package/dist/cli/ui/utils/branchFormatter.js +124 -15
  23. package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
  24. package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
  25. package/dist/cli/ui/utils/modelOptions.js.map +1 -1
  26. package/dist/client/assets/{index-CNWntAlF.js → index-Dl798X5w.js} +1 -1
  27. package/dist/client/index.html +1 -1
  28. package/dist/config/index.d.ts.map +1 -1
  29. package/dist/config/index.js.map +1 -1
  30. package/dist/git.d.ts +6 -0
  31. package/dist/git.d.ts.map +1 -1
  32. package/dist/git.js +40 -5
  33. package/dist/git.js.map +1 -1
  34. package/dist/web/client/src/components/BranchGraph.js +1 -1
  35. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  36. package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
  37. package/dist/web/client/src/pages/BranchDetailPage.js +8 -3
  38. package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
  39. package/dist/web/server/routes/sessions.d.ts.map +1 -1
  40. package/dist/web/server/routes/sessions.js +4 -2
  41. package/dist/web/server/routes/sessions.js.map +1 -1
  42. package/dist/worktree.d.ts.map +1 -1
  43. package/dist/worktree.js +69 -62
  44. package/dist/worktree.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +9 -17
  47. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +77 -83
  48. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +107 -160
  49. package/src/cli/ui/__tests__/components/App.test.tsx +108 -84
  50. package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +12 -5
  51. package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +3 -2
  52. package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +3 -2
  53. package/src/cli/ui/__tests__/components/common/Input.test.tsx +3 -2
  54. package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +15 -14
  55. package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +3 -3
  56. package/src/cli/ui/__tests__/components/common/Select.test.tsx +1 -4
  57. package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +3 -2
  58. package/src/cli/ui/__tests__/components/parts/Header.test.tsx +3 -2
  59. package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +3 -2
  60. package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +3 -2
  61. package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +3 -2
  62. package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +3 -2
  63. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +31 -41
  64. package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +3 -2
  65. package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +3 -2
  66. package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +3 -2
  67. package/src/cli/ui/__tests__/hooks/useScreenState.test.ts +18 -17
  68. package/src/cli/ui/__tests__/hooks/useTerminalSize.test.ts +3 -2
  69. package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +61 -41
  70. package/src/cli/ui/__tests__/integration/navigation.test.tsx +15 -10
  71. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +3 -2
  72. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +0 -4
  73. package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +3 -5
  74. package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +24 -22
  75. package/src/cli/ui/components/App.tsx +5 -63
  76. package/src/cli/ui/components/common/Input.tsx +1 -1
  77. package/src/cli/ui/components/screens/BranchListScreen.tsx +32 -22
  78. package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +46 -49
  79. package/src/cli/ui/components/screens/PRCleanupScreen.tsx +0 -3
  80. package/src/cli/ui/hooks/useGitData.ts +59 -1
  81. package/src/cli/ui/screens/__tests__/BranchActionSelectorScreen.test.tsx +3 -2
  82. package/src/cli/ui/types.ts +24 -5
  83. package/src/cli/ui/utils/branchFormatter.ts +123 -15
  84. package/src/cli/ui/utils/modelOptions.test.ts +4 -6
  85. package/src/cli/ui/utils/modelOptions.ts +1 -2
  86. package/src/config/index.ts +2 -1
  87. package/src/git.ts +56 -16
  88. package/src/index.test.ts +1 -1
  89. package/src/web/client/src/components/BranchGraph.tsx +1 -1
  90. package/src/web/client/src/pages/BranchDetailPage.tsx +8 -3
  91. package/src/web/server/routes/sessions.ts +12 -5
  92. package/src/worktree.ts +80 -91
  93. package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts +0 -20
  94. package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts.map +0 -1
  95. package/dist/cli/ui/components/screens/WorktreeManagerScreen.js +0 -65
  96. package/dist/cli/ui/components/screens/WorktreeManagerScreen.js.map +0 -1
  97. package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +0 -151
  98. 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
- describe,
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 * as useGitDataModule from "../../hooks/useGitData.js";
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
- const originalUseGitData = useGitDataModule.useGitData;
22
- const useGitDataSpy = vi.spyOn(useGitDataModule, "useGitData");
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 any;
29
- globalThis.document = window.document as any;
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
- useGitDataSpy.mockReset();
33
- useGitDataSpy.mockImplementation(originalUseGitData);
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
- useGitDataSpy.mockReturnValue({
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
- const { getByText } = render(<App onExit={onExit} />);
62
-
63
- // Check for BranchListScreen elements
64
- expect(getByText(/gwt - Branch Selection/i)).toBeDefined();
65
- expect(getByText(/main/)).toBeDefined();
66
- expect(getByText(/feature\/test/)).toBeDefined();
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
- useGitDataSpy.mockReturnValue({
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
- const { queryByText, getByText } = render(
80
- <App onExit={onExit} loadingIndicatorDelay={10} />,
81
- );
109
+ render(<App onExit={onExit} loadingIndicatorDelay={10} />);
82
110
 
83
- expect(queryByText(/Loading Git information/i)).toBeNull();
84
-
85
- await act(async () => {
86
- await new Promise((resolve) => setTimeout(resolve, 15));
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
- useGitDataSpy.mockReturnValue({
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
- const { getByText } = render(<App onExit={onExit} />);
128
+ render(<App onExit={onExit} />);
104
129
 
105
- expect(getByText(/Error:/i)).toBeDefined();
106
- expect(getByText(/Failed to fetch branches/i)).toBeDefined();
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
- useGitDataSpy.mockReturnValue({
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
- const { getByText, getAllByText } = render(<App onExit={onExit} />);
146
-
147
- // Check for statistics
148
- expect(getByText(/Local:/)).toBeDefined();
149
- expect(getAllByText(/2/).length).toBeGreaterThan(0); // 2 local branches
150
- expect(getByText(/Remote:/)).toBeDefined();
151
- expect(getAllByText(/1/).length).toBeGreaterThan(0); // 1 remote branch + 1 worktree
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 call onExit when branch is selected", () => {
156
- useGitDataSpy.mockReturnValue({
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
- useGitDataSpy.mockReturnValue({
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
- const { getByText } = render(<App onExit={onExit} />);
209
+ render(<App onExit={onExit} />);
183
210
 
184
- expect(getByText(/No branches found/i)).toBeDefined();
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
- useGitDataSpy.mockReturnValue({
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
- useGitDataSpy.mockReturnValue({
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
- const { getByText } = render(<App onExit={onExit} />);
245
+ render(<App onExit={onExit} />);
215
246
 
216
- // Check for branch type icon (main = ⚡)
217
- expect(getByText(/⚡/)).toBeDefined();
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
- useGitDataSpy.mockReturnValue({
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
- useGitDataSpy.mockReturnValue({
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
- useGitDataSpy.mockReturnValue({
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: any[] = [];
15
+ const selectMocks: SelectProps<SelectItem>[] = [];
12
16
 
13
17
  vi.mock("../../components/common/Select.js", () => {
14
18
  return {
15
- Select: (props: any) => {
19
+ Select: (props: SelectProps<SelectItem>) => {
16
20
  selectMocks.push(props);
17
21
  return React.createElement("div", {
18
22
  "data-testid": "select-mock",
19
- onClick: () => props.onSelect && props.onSelect(props.items[props.initialIndex ?? 0]),
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 any;
30
- globalThis.document = window.document as any;
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 any;
15
- globalThis.document = window.document as any;
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 any;
24
- globalThis.document = window.document as any;
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 any;
15
- globalThis.document = window.document as any;
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 any;
28
- globalThis.document = window.document as any;
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
- await act(async () => {
82
- rerender(
83
- <LoadingIndicator
84
- isLoading={false}
85
- message="Loading data"
86
- delay={10}
87
- />,
88
- );
89
- if (typeof vi.advanceTimersByTimeAsync === "function") {
90
- await vi.advanceTimersByTimeAsync(0);
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 any;
23
- globalThis.document = window.document as any;
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 any;
15
- globalThis.document = window.document as any;
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 any;
15
- globalThis.document = window.document as any;
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 any;
16
- globalThis.document = window.document as any;
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 any;
16
- globalThis.document = window.document as any;
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 any;
31
- globalThis.document = window.document as any;
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 any;
17
- globalThis.document = window.document as any;
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(() => {