@akiojin/gwt 2.2.0 → 2.4.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 (172) hide show
  1. package/README.ja.md +6 -4
  2. package/README.md +6 -4
  3. package/dist/claude.d.ts +1 -0
  4. package/dist/claude.d.ts.map +1 -1
  5. package/dist/claude.js +6 -3
  6. package/dist/claude.js.map +1 -1
  7. package/dist/cli/ui/components/App.d.ts +6 -4
  8. package/dist/cli/ui/components/App.d.ts.map +1 -1
  9. package/dist/cli/ui/components/App.js +184 -107
  10. package/dist/cli/ui/components/App.js.map +1 -1
  11. package/dist/cli/ui/components/common/Confirm.d.ts +1 -1
  12. package/dist/cli/ui/components/common/Confirm.d.ts.map +1 -1
  13. package/dist/cli/ui/components/common/Confirm.js +7 -7
  14. package/dist/cli/ui/components/common/Confirm.js.map +1 -1
  15. package/dist/cli/ui/components/common/ErrorBoundary.d.ts +1 -1
  16. package/dist/cli/ui/components/common/ErrorBoundary.d.ts.map +1 -1
  17. package/dist/cli/ui/components/common/ErrorBoundary.js +4 -4
  18. package/dist/cli/ui/components/common/ErrorBoundary.js.map +1 -1
  19. package/dist/cli/ui/components/common/Input.d.ts +2 -2
  20. package/dist/cli/ui/components/common/Input.d.ts.map +1 -1
  21. package/dist/cli/ui/components/common/Input.js +4 -4
  22. package/dist/cli/ui/components/common/Input.js.map +1 -1
  23. package/dist/cli/ui/components/common/LoadingIndicator.d.ts +1 -1
  24. package/dist/cli/ui/components/common/LoadingIndicator.d.ts.map +1 -1
  25. package/dist/cli/ui/components/common/LoadingIndicator.js +4 -4
  26. package/dist/cli/ui/components/common/LoadingIndicator.js.map +1 -1
  27. package/dist/cli/ui/components/common/Select.d.ts +1 -1
  28. package/dist/cli/ui/components/common/Select.d.ts.map +1 -1
  29. package/dist/cli/ui/components/common/Select.js +11 -12
  30. package/dist/cli/ui/components/common/Select.js.map +1 -1
  31. package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts +3 -3
  32. package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts.map +1 -1
  33. package/dist/cli/ui/components/screens/AIToolSelectorScreen.js +11 -11
  34. package/dist/cli/ui/components/screens/AIToolSelectorScreen.js.map +1 -1
  35. package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts +1 -1
  36. package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts.map +1 -1
  37. package/dist/cli/ui/components/screens/BranchCreatorScreen.js +39 -36
  38. package/dist/cli/ui/components/screens/BranchCreatorScreen.js.map +1 -1
  39. package/dist/cli/ui/components/screens/BranchListScreen.d.ts +3 -3
  40. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  41. package/dist/cli/ui/components/screens/BranchListScreen.js +55 -50
  42. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  43. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts +2 -2
  44. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts.map +1 -1
  45. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js +25 -25
  46. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js.map +1 -1
  47. package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts +18 -0
  48. package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +1 -0
  49. package/dist/cli/ui/components/screens/ModelSelectorScreen.js +201 -0
  50. package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +1 -0
  51. package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts +2 -2
  52. package/dist/cli/ui/components/screens/PRCleanupScreen.js +21 -21
  53. package/dist/cli/ui/components/screens/SessionSelectorScreen.d.ts +1 -1
  54. package/dist/cli/ui/components/screens/SessionSelectorScreen.js +8 -8
  55. package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts +1 -1
  56. package/dist/cli/ui/components/screens/WorktreeManagerScreen.js +8 -8
  57. package/dist/cli/ui/screens/BranchActionSelectorScreen.d.ts.map +1 -1
  58. package/dist/cli/ui/screens/BranchActionSelectorScreen.js +7 -4
  59. package/dist/cli/ui/screens/BranchActionSelectorScreen.js.map +1 -1
  60. package/dist/cli/ui/types.d.ts +11 -1
  61. package/dist/cli/ui/types.d.ts.map +1 -1
  62. package/dist/cli/ui/utils/modelOptions.d.ts +6 -0
  63. package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -0
  64. package/dist/cli/ui/utils/modelOptions.js +111 -0
  65. package/dist/cli/ui/utils/modelOptions.js.map +1 -0
  66. package/dist/client/assets/{index-V6hDu9KS.js → index-Difv1Hwu.js} +2 -2
  67. package/dist/client/index.html +1 -1
  68. package/dist/codex.d.ts +6 -0
  69. package/dist/codex.d.ts.map +1 -1
  70. package/dist/codex.js +11 -4
  71. package/dist/codex.js.map +1 -1
  72. package/dist/config/builtin-tools.d.ts +10 -2
  73. package/dist/config/builtin-tools.d.ts.map +1 -1
  74. package/dist/config/builtin-tools.js +40 -4
  75. package/dist/config/builtin-tools.js.map +1 -1
  76. package/dist/config/index.d.ts.map +1 -1
  77. package/dist/config/index.js.map +1 -1
  78. package/dist/config/tools.d.ts.map +1 -1
  79. package/dist/config/tools.js +4 -3
  80. package/dist/config/tools.js.map +1 -1
  81. package/dist/gemini.d.ts +13 -0
  82. package/dist/gemini.d.ts.map +1 -0
  83. package/dist/gemini.js +157 -0
  84. package/dist/gemini.js.map +1 -0
  85. package/dist/git.d.ts.map +1 -1
  86. package/dist/git.js.map +1 -1
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +59 -7
  89. package/dist/index.js.map +1 -1
  90. package/dist/qwen.d.ts +13 -0
  91. package/dist/qwen.d.ts.map +1 -0
  92. package/dist/qwen.js +157 -0
  93. package/dist/qwen.js.map +1 -0
  94. package/dist/services/git.service.d.ts.map +1 -1
  95. package/dist/services/git.service.js.map +1 -1
  96. package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
  97. package/dist/web/client/src/components/BranchGraph.js +1 -1
  98. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  99. package/dist/web/client/src/components/EnvEditor.d.ts.map +1 -1
  100. package/dist/web/client/src/components/EnvEditor.js +7 -4
  101. package/dist/web/client/src/components/EnvEditor.js.map +1 -1
  102. package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
  103. package/dist/web/client/src/pages/BranchDetailPage.js +55 -18
  104. package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
  105. package/dist/web/client/src/pages/BranchListPage.d.ts.map +1 -1
  106. package/dist/web/client/src/pages/BranchListPage.js +10 -4
  107. package/dist/web/client/src/pages/BranchListPage.js.map +1 -1
  108. package/dist/web/client/src/pages/ConfigManagementPage.d.ts.map +1 -1
  109. package/dist/web/client/src/pages/ConfigManagementPage.js +4 -2
  110. package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
  111. package/package.json +2 -1
  112. package/src/claude.ts +8 -3
  113. package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +69 -50
  114. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +67 -45
  115. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +117 -75
  116. package/src/cli/ui/__tests__/components/App.test.tsx +45 -37
  117. package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +81 -0
  118. package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +35 -22
  119. package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +22 -22
  120. package/src/cli/ui/__tests__/components/common/Input.test.tsx +29 -22
  121. package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +63 -43
  122. package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +57 -66
  123. package/src/cli/ui/__tests__/components/common/Select.test.tsx +121 -91
  124. package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +18 -16
  125. package/src/cli/ui/__tests__/components/parts/Header.test.tsx +13 -13
  126. package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +20 -20
  127. package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +38 -26
  128. package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +31 -31
  129. package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +73 -37
  130. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +261 -153
  131. package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +38 -32
  132. package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +39 -39
  133. package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +49 -21
  134. package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +52 -28
  135. package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +84 -48
  136. package/src/cli/ui/__tests__/integration/navigation.test.tsx +111 -83
  137. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +111 -108
  138. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +50 -37
  139. package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +75 -76
  140. package/src/cli/ui/components/App.tsx +317 -150
  141. package/src/cli/ui/components/common/Confirm.tsx +13 -9
  142. package/src/cli/ui/components/common/ErrorBoundary.tsx +8 -5
  143. package/src/cli/ui/components/common/Input.tsx +12 -4
  144. package/src/cli/ui/components/common/LoadingIndicator.tsx +8 -5
  145. package/src/cli/ui/components/common/Select.tsx +28 -17
  146. package/src/cli/ui/components/parts/Header.test.tsx +5 -15
  147. package/src/cli/ui/components/screens/AIToolSelectorScreen.tsx +20 -15
  148. package/src/cli/ui/components/screens/BranchCreatorScreen.tsx +74 -54
  149. package/src/cli/ui/components/screens/BranchListScreen.tsx +92 -75
  150. package/src/cli/ui/components/screens/ExecutionModeSelectorScreen.tsx +35 -28
  151. package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +320 -0
  152. package/src/cli/ui/components/screens/PRCleanupScreen.tsx +22 -22
  153. package/src/cli/ui/components/screens/SessionSelectorScreen.tsx +8 -8
  154. package/src/cli/ui/components/screens/WorktreeManagerScreen.tsx +8 -8
  155. package/src/cli/ui/screens/BranchActionSelectorScreen.tsx +9 -4
  156. package/src/cli/ui/types.ts +21 -1
  157. package/src/cli/ui/utils/modelOptions.test.ts +36 -0
  158. package/src/cli/ui/utils/modelOptions.ts +122 -0
  159. package/src/codex.ts +23 -4
  160. package/src/config/builtin-tools.ts +42 -4
  161. package/src/config/index.ts +2 -12
  162. package/src/config/tools.ts +16 -6
  163. package/src/gemini.ts +207 -0
  164. package/src/git.ts +2 -1
  165. package/src/index.ts +86 -6
  166. package/src/qwen.ts +213 -0
  167. package/src/services/git.service.ts +2 -1
  168. package/src/web/client/src/components/BranchGraph.tsx +3 -2
  169. package/src/web/client/src/components/EnvEditor.tsx +44 -11
  170. package/src/web/client/src/pages/BranchDetailPage.tsx +165 -54
  171. package/src/web/client/src/pages/BranchListPage.tsx +37 -13
  172. package/src/web/client/src/pages/ConfigManagementPage.tsx +28 -9
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * @vitest-environment happy-dom
3
3
  */
4
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5
- import { render } from '@testing-library/react';
6
- import React from 'react';
7
- import { App } from '../../components/App.js';
8
- import { Window } from 'happy-dom';
9
- import type { BranchInfo } from '../../types.js';
4
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
5
+ import { render } from "@testing-library/react";
6
+ import React from "react";
7
+ import { App } from "../../components/App.js";
8
+ import { Window } from "happy-dom";
9
+ import type { BranchInfo } from "../../types.js";
10
10
 
11
11
  /**
12
12
  * Real-time update integration tests
@@ -15,14 +15,14 @@ import type { BranchInfo } from '../../types.js';
15
15
 
16
16
  // Mock useGitData hook
17
17
  const mockRefresh = vi.fn();
18
- vi.mock('../../hooks/useGitData.js', () => ({
18
+ vi.mock("../../hooks/useGitData.js", () => ({
19
19
  useGitData: vi.fn(),
20
20
  }));
21
21
 
22
- import { useGitData } from '../../hooks/useGitData.js';
22
+ import { useGitData } from "../../hooks/useGitData.js";
23
23
  const mockUseGitData = useGitData as ReturnType<typeof vi.fn>;
24
24
 
25
- describe('Real-time Update Integration', () => {
25
+ describe("Real-time Update Integration", () => {
26
26
  beforeEach(() => {
27
27
  // Setup happy-dom
28
28
  const window = new Window();
@@ -37,18 +37,18 @@ describe('Real-time Update Integration', () => {
37
37
  vi.restoreAllMocks();
38
38
  });
39
39
 
40
- it('T084: should disable auto-refresh (manual refresh with r key)', () => {
40
+ it("T084: should disable auto-refresh (manual refresh with r key)", () => {
41
41
  const mockBranches: BranchInfo[] = [
42
42
  {
43
- name: 'main',
44
- branchType: 'main',
45
- type: 'local',
43
+ name: "main",
44
+ branchType: "main",
45
+ type: "local",
46
46
  isCurrent: true,
47
47
  },
48
48
  {
49
- name: 'feature/test-1',
50
- branchType: 'feature',
51
- type: 'local',
49
+ name: "feature/test-1",
50
+ branchType: "feature",
51
+ type: "local",
52
52
  isCurrent: false,
53
53
  },
54
54
  ];
@@ -71,18 +71,18 @@ describe('Real-time Update Integration', () => {
71
71
  });
72
72
  });
73
73
 
74
- it('T085: should display updated statistics', () => {
74
+ it("T085: should display updated statistics", () => {
75
75
  const mockBranches: BranchInfo[] = [
76
76
  {
77
- name: 'main',
78
- branchType: 'main',
79
- type: 'local',
77
+ name: "main",
78
+ branchType: "main",
79
+ type: "local",
80
80
  isCurrent: true,
81
81
  },
82
82
  {
83
- name: 'feature/test-1',
84
- branchType: 'feature',
85
- type: 'local',
83
+ name: "feature/test-1",
84
+ branchType: "feature",
85
+ type: "local",
86
86
  isCurrent: false,
87
87
  },
88
88
  ];
@@ -101,15 +101,15 @@ describe('Real-time Update Integration', () => {
101
101
 
102
102
  // Initial state should show "Local: 2"
103
103
  expect(getByText(/Local:/i)).toBeDefined();
104
- expect(getByText('2')).toBeDefined();
104
+ expect(getByText("2")).toBeDefined();
105
105
 
106
106
  // Simulate Git operation: add a new branch
107
107
  const updatedBranches: BranchInfo[] = [
108
108
  ...mockBranches,
109
109
  {
110
- name: 'feature/test-2',
111
- branchType: 'feature',
112
- type: 'local',
110
+ name: "feature/test-2",
111
+ branchType: "feature",
112
+ type: "local",
113
113
  isCurrent: false,
114
114
  },
115
115
  ];
@@ -127,21 +127,21 @@ describe('Real-time Update Integration', () => {
127
127
  rerender(<App onExit={onExit} />);
128
128
 
129
129
  // Should now show "Local: 3"
130
- expect(getByText('3')).toBeDefined();
130
+ expect(getByText("3")).toBeDefined();
131
131
  });
132
132
 
133
- it('T086: should update statistics after Worktree creation', () => {
133
+ it("T086: should update statistics after Worktree creation", () => {
134
134
  const mockBranches: BranchInfo[] = [
135
135
  {
136
- name: 'main',
137
- branchType: 'main',
138
- type: 'local',
136
+ name: "main",
137
+ branchType: "main",
138
+ type: "local",
139
139
  isCurrent: true,
140
140
  },
141
141
  {
142
- name: 'feature/test-1',
143
- branchType: 'feature',
144
- type: 'local',
142
+ name: "feature/test-1",
143
+ branchType: "feature",
144
+ type: "local",
145
145
  isCurrent: false,
146
146
  },
147
147
  ];
@@ -161,24 +161,24 @@ describe('Real-time Update Integration', () => {
161
161
  // Initial state should show "Worktrees: 0"
162
162
  expect(getByText(/Worktrees:/i)).toBeDefined();
163
163
  // Verify the content contains Worktrees: 0
164
- expect(container.textContent).toContain('Worktrees');
164
+ expect(container.textContent).toContain("Worktrees");
165
165
 
166
166
  // Simulate Worktree creation
167
167
  const branchesWithWorktree: BranchInfo[] = [
168
168
  {
169
- name: 'main',
170
- branchType: 'main',
171
- type: 'local',
169
+ name: "main",
170
+ branchType: "main",
171
+ type: "local",
172
172
  isCurrent: true,
173
173
  },
174
174
  {
175
- name: 'feature/test-1',
176
- branchType: 'feature',
177
- type: 'local',
175
+ name: "feature/test-1",
176
+ branchType: "feature",
177
+ type: "local",
178
178
  isCurrent: false,
179
179
  worktree: {
180
- path: '/mock/worktree/feature-test-1',
181
- branch: 'feature/test-1',
180
+ path: "/mock/worktree/feature-test-1",
181
+ branch: "feature/test-1",
182
182
  isAccessible: true,
183
183
  },
184
184
  },
@@ -188,8 +188,8 @@ describe('Real-time Update Integration', () => {
188
188
  branches: branchesWithWorktree,
189
189
  worktrees: [
190
190
  {
191
- path: '/mock/worktree/feature-test-1',
192
- branch: 'feature/test-1',
191
+ path: "/mock/worktree/feature-test-1",
192
+ branch: "feature/test-1",
193
193
  isAccessible: true,
194
194
  },
195
195
  ],
@@ -205,15 +205,15 @@ describe('Real-time Update Integration', () => {
205
205
  // Should now show "Worktrees: 1"
206
206
  expect(getByText(/Worktrees:/i)).toBeDefined();
207
207
  // Verify worktree count increased by checking container content
208
- expect(container.textContent).toContain('Worktrees');
208
+ expect(container.textContent).toContain("Worktrees");
209
209
  });
210
210
 
211
- it('should display lastUpdated timestamp', () => {
211
+ it("should display lastUpdated timestamp", () => {
212
212
  const mockBranches: BranchInfo[] = [
213
213
  {
214
- name: 'main',
215
- branchType: 'main',
216
- type: 'local',
214
+ name: "main",
215
+ branchType: "main",
216
+ type: "local",
217
217
  isCurrent: true,
218
218
  },
219
219
  ];
@@ -235,8 +235,8 @@ describe('Real-time Update Integration', () => {
235
235
  expect(getByText(/Updated:/i)).toBeDefined();
236
236
  });
237
237
 
238
- it('should handle refresh errors gracefully', () => {
239
- const error = new Error('Git command failed');
238
+ it("should handle refresh errors gracefully", () => {
239
+ const error = new Error("Git command failed");
240
240
  mockUseGitData.mockReturnValue({
241
241
  branches: [],
242
242
  worktrees: [],
@@ -258,25 +258,25 @@ describe('Real-time Update Integration', () => {
258
258
  * T082-3: Cursor position retention during auto-refresh
259
259
  * Tests that cursor position is maintained when data is auto-refreshed
260
260
  */
261
- describe('Cursor Position Retention (T082-3)', () => {
262
- it('should maintain cursor position when branches data is refreshed with same content', () => {
261
+ describe("Cursor Position Retention (T082-3)", () => {
262
+ it("should maintain cursor position when branches data is refreshed with same content", () => {
263
263
  const mockBranches: BranchInfo[] = [
264
264
  {
265
- name: 'main',
266
- branchType: 'main',
267
- type: 'local',
265
+ name: "main",
266
+ branchType: "main",
267
+ type: "local",
268
268
  isCurrent: true,
269
269
  },
270
270
  {
271
- name: 'feature/test-1',
272
- branchType: 'feature',
273
- type: 'local',
271
+ name: "feature/test-1",
272
+ branchType: "feature",
273
+ type: "local",
274
274
  isCurrent: false,
275
275
  },
276
276
  {
277
- name: 'feature/test-2',
278
- branchType: 'feature',
279
- type: 'local',
277
+ name: "feature/test-2",
278
+ branchType: "feature",
279
+ type: "local",
280
280
  isCurrent: false,
281
281
  },
282
282
  ];
@@ -299,21 +299,21 @@ describe('Real-time Update Integration', () => {
299
299
  // Create new array with same content (simulating auto-refresh)
300
300
  const refreshedBranches: BranchInfo[] = [
301
301
  {
302
- name: 'main',
303
- branchType: 'main',
304
- type: 'local',
302
+ name: "main",
303
+ branchType: "main",
304
+ type: "local",
305
305
  isCurrent: true,
306
306
  },
307
307
  {
308
- name: 'feature/test-1',
309
- branchType: 'feature',
310
- type: 'local',
308
+ name: "feature/test-1",
309
+ branchType: "feature",
310
+ type: "local",
311
311
  isCurrent: false,
312
312
  },
313
313
  {
314
- name: 'feature/test-2',
315
- branchType: 'feature',
316
- type: 'local',
314
+ name: "feature/test-2",
315
+ branchType: "feature",
316
+ type: "local",
317
317
  isCurrent: false,
318
318
  },
319
319
  ];
@@ -341,18 +341,18 @@ describe('Real-time Update Integration', () => {
341
341
  // - Cursor position might be reset
342
342
  });
343
343
 
344
- it('should maintain cursor position when a branch is added at the end', () => {
344
+ it("should maintain cursor position when a branch is added at the end", () => {
345
345
  const initialBranches: BranchInfo[] = [
346
346
  {
347
- name: 'main',
348
- branchType: 'main',
349
- type: 'local',
347
+ name: "main",
348
+ branchType: "main",
349
+ type: "local",
350
350
  isCurrent: true,
351
351
  },
352
352
  {
353
- name: 'feature/test-1',
354
- branchType: 'feature',
355
- type: 'local',
353
+ name: "feature/test-1",
354
+ branchType: "feature",
355
+ type: "local",
356
356
  isCurrent: false,
357
357
  },
358
358
  ];
@@ -373,9 +373,9 @@ describe('Real-time Update Integration', () => {
373
373
  const updatedBranches: BranchInfo[] = [
374
374
  ...initialBranches,
375
375
  {
376
- name: 'feature/test-2',
377
- branchType: 'feature',
378
- type: 'local',
376
+ name: "feature/test-2",
377
+ branchType: "feature",
378
+ type: "local",
379
379
  isCurrent: false,
380
380
  },
381
381
  ];
@@ -394,24 +394,24 @@ describe('Real-time Update Integration', () => {
394
394
  // Cursor should remain on the same item (e.g., index 1 should still point to 'feature/test-1')
395
395
  });
396
396
 
397
- it('should adjust cursor position when current selected branch is deleted', () => {
397
+ it("should adjust cursor position when current selected branch is deleted", () => {
398
398
  const initialBranches: BranchInfo[] = [
399
399
  {
400
- name: 'main',
401
- branchType: 'main',
402
- type: 'local',
400
+ name: "main",
401
+ branchType: "main",
402
+ type: "local",
403
403
  isCurrent: true,
404
404
  },
405
405
  {
406
- name: 'feature/test-1',
407
- branchType: 'feature',
408
- type: 'local',
406
+ name: "feature/test-1",
407
+ branchType: "feature",
408
+ type: "local",
409
409
  isCurrent: false,
410
410
  },
411
411
  {
412
- name: 'feature/test-2',
413
- branchType: 'feature',
414
- type: 'local',
412
+ name: "feature/test-2",
413
+ branchType: "feature",
414
+ type: "local",
415
415
  isCurrent: false,
416
416
  },
417
417
  ];
@@ -431,15 +431,15 @@ describe('Real-time Update Integration', () => {
431
431
  // Remove middle branch (cursor was on index 1, which is now deleted)
432
432
  const updatedBranches: BranchInfo[] = [
433
433
  {
434
- name: 'main',
435
- branchType: 'main',
436
- type: 'local',
434
+ name: "main",
435
+ branchType: "main",
436
+ type: "local",
437
437
  isCurrent: true,
438
438
  },
439
439
  {
440
- name: 'feature/test-2',
441
- branchType: 'feature',
442
- type: 'local',
440
+ name: "feature/test-2",
441
+ branchType: "feature",
442
+ type: "local",
443
443
  isCurrent: false,
444
444
  },
445
445
  ];
@@ -458,12 +458,12 @@ describe('Real-time Update Integration', () => {
458
458
  // Cursor should be clamped to valid index (e.g., moved to index 1, which is now 'feature/test-2')
459
459
  });
460
460
 
461
- it('should maintain scroll offset during auto-refresh', () => {
461
+ it("should maintain scroll offset during auto-refresh", () => {
462
462
  // Create many branches to test scrolling
463
463
  const manyBranches: BranchInfo[] = Array.from({ length: 20 }, (_, i) => ({
464
464
  name: `feature/test-${i + 1}`,
465
- branchType: 'feature' as const,
466
- type: 'local' as const,
465
+ branchType: "feature" as const,
466
+ type: "local" as const,
467
467
  isCurrent: false,
468
468
  }));
469
469
 
@@ -480,12 +480,15 @@ describe('Real-time Update Integration', () => {
480
480
  const { rerender } = render(<App onExit={onExit} />);
481
481
 
482
482
  // Simulate auto-refresh with same content
483
- const refreshedBranches: BranchInfo[] = Array.from({ length: 20 }, (_, i) => ({
484
- name: `feature/test-${i + 1}`,
485
- branchType: 'feature' as const,
486
- type: 'local' as const,
487
- isCurrent: false,
488
- }));
483
+ const refreshedBranches: BranchInfo[] = Array.from(
484
+ { length: 20 },
485
+ (_, i) => ({
486
+ name: `feature/test-${i + 1}`,
487
+ branchType: "feature" as const,
488
+ type: "local" as const,
489
+ isCurrent: false,
490
+ }),
491
+ );
489
492
 
490
493
  mockUseGitData.mockReturnValue({
491
494
  branches: refreshedBranches,
@@ -1,16 +1,23 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { render } from 'ink-testing-library';
3
- import React from 'react';
4
- import { BranchListScreen } from '../../components/screens/BranchListScreen.js';
5
- import type { BranchItem, Statistics } from '../../types.js';
1
+ import { describe, it, expect } from "vitest";
2
+ import { render } from "ink-testing-library";
3
+ import React from "react";
4
+ import { BranchListScreen } from "../../components/screens/BranchListScreen.js";
5
+ import type { BranchItem, Statistics } from "../../types.js";
6
6
 
7
7
  /**
8
8
  * Generate mock branch items for performance testing
9
9
  */
10
10
  function generateMockBranches(count: number): BranchItem[] {
11
11
  const branches: BranchItem[] = [];
12
- const types = ['feature', 'hotfix', 'release', 'other'] as const;
13
- const branchTypes = ['main', 'develop', 'feature', 'hotfix', 'release', 'other'] as const;
12
+ const types = ["feature", "hotfix", "release", "other"] as const;
13
+ const branchTypes = [
14
+ "main",
15
+ "develop",
16
+ "feature",
17
+ "hotfix",
18
+ "release",
19
+ "other",
20
+ ] as const;
14
21
 
15
22
  for (let i = 0; i < count; i++) {
16
23
  const type = types[i % types.length];
@@ -18,22 +25,26 @@ function generateMockBranches(count: number): BranchItem[] {
18
25
  const hasWorktree = i % 3 === 0;
19
26
 
20
27
  branches.push({
21
- name: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
28
+ name: `${type}/test-branch-${i.toString().padStart(4, "0")}`,
22
29
  branchType,
23
- type: i % 10 === 0 ? 'remote' : 'local',
30
+ type: i % 10 === 0 ? "remote" : "local",
24
31
  isCurrent: i === 0,
25
32
  worktree: hasWorktree
26
33
  ? {
27
34
  path: `/mock/worktree/${type}-${i}`,
28
- branch: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
35
+ branch: `${type}/test-branch-${i.toString().padStart(4, "0")}`,
29
36
  isAccessible: i % 5 !== 0, // Some inaccessible
30
37
  }
31
38
  : undefined,
32
- worktreeStatus: hasWorktree ? (i % 5 !== 0 ? 'active' : 'inaccessible') : undefined,
39
+ worktreeStatus: hasWorktree
40
+ ? i % 5 !== 0
41
+ ? "active"
42
+ : "inaccessible"
43
+ : undefined,
33
44
  hasChanges: i % 4 === 0,
34
45
  icons: [],
35
- label: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
36
- value: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
46
+ label: `${type}/test-branch-${i.toString().padStart(4, "0")}`,
47
+ value: `${type}/test-branch-${i.toString().padStart(4, "0")}`,
37
48
  });
38
49
  }
39
50
 
@@ -52,17 +63,17 @@ function generateMockBranches(count: number): BranchItem[] {
52
63
  // worktree: 0,
53
64
  // };
54
65
 
55
- describe('BranchListScreen Performance', () => {
56
- it('should render 100+ branches within acceptable time', () => {
66
+ describe("BranchListScreen Performance", () => {
67
+ it("should render 100+ branches within acceptable time", () => {
57
68
  const branches = generateMockBranches(150);
58
69
  const stats: Statistics = {
59
70
  total: branches.length,
60
- local: branches.filter((b) => b.type === 'local').length,
61
- remote: branches.filter((b) => b.type === 'remote').length,
71
+ local: branches.filter((b) => b.type === "local").length,
72
+ remote: branches.filter((b) => b.type === "remote").length,
62
73
  current: 1,
63
- feature: branches.filter((b) => b.branchType === 'feature').length,
64
- hotfix: branches.filter((b) => b.branchType === 'hotfix').length,
65
- release: branches.filter((b) => b.branchType === 'release').length,
74
+ feature: branches.filter((b) => b.branchType === "feature").length,
75
+ hotfix: branches.filter((b) => b.branchType === "hotfix").length,
76
+ release: branches.filter((b) => b.branchType === "release").length,
66
77
  worktree: branches.filter((b) => b.worktree).length,
67
78
  };
68
79
 
@@ -75,7 +86,7 @@ describe('BranchListScreen Performance', () => {
75
86
  onSelect={() => {}}
76
87
  onNavigate={() => {}}
77
88
  onQuit={() => {}}
78
- />
89
+ />,
79
90
  );
80
91
 
81
92
  const renderTime = performance.now() - startTime;
@@ -89,19 +100,21 @@ describe('BranchListScreen Performance', () => {
89
100
  console.log(`\nšŸ“Š Performance Test Results:`);
90
101
  console.log(` Branches: ${branches.length}`);
91
102
  console.log(` Render time: ${renderTime.toFixed(2)}ms`);
92
- console.log(` Average per branch: ${(renderTime / branches.length).toFixed(3)}ms`);
103
+ console.log(
104
+ ` Average per branch: ${(renderTime / branches.length).toFixed(3)}ms`,
105
+ );
93
106
  });
94
107
 
95
- it('should handle re-render efficiently when stats update', () => {
108
+ it("should handle re-render efficiently when stats update", () => {
96
109
  const branches = generateMockBranches(100);
97
110
  const stats: Statistics = {
98
111
  total: branches.length,
99
- local: branches.filter((b) => b.type === 'local').length,
100
- remote: branches.filter((b) => b.type === 'remote').length,
112
+ local: branches.filter((b) => b.type === "local").length,
113
+ remote: branches.filter((b) => b.type === "remote").length,
101
114
  current: 1,
102
- feature: branches.filter((b) => b.branchType === 'feature').length,
103
- hotfix: branches.filter((b) => b.branchType === 'hotfix').length,
104
- release: branches.filter((b) => b.branchType === 'release').length,
115
+ feature: branches.filter((b) => b.branchType === "feature").length,
116
+ hotfix: branches.filter((b) => b.branchType === "hotfix").length,
117
+ release: branches.filter((b) => b.branchType === "release").length,
105
118
  worktree: branches.filter((b) => b.worktree).length,
106
119
  };
107
120
 
@@ -113,7 +126,7 @@ describe('BranchListScreen Performance', () => {
113
126
  onNavigate={() => {}}
114
127
  onQuit={() => {}}
115
128
  lastUpdated={new Date()}
116
- />
129
+ />,
117
130
  );
118
131
 
119
132
  // Simulate stats update (real-time refresh)
@@ -127,7 +140,7 @@ describe('BranchListScreen Performance', () => {
127
140
  onNavigate={() => {}}
128
141
  onQuit={() => {}}
129
142
  lastUpdated={new Date()}
130
- />
143
+ />,
131
144
  );
132
145
 
133
146
  const rerenderTime = performance.now() - startTime;
@@ -141,16 +154,16 @@ describe('BranchListScreen Performance', () => {
141
154
  console.log(` Re-render time: ${rerenderTime.toFixed(2)}ms`);
142
155
  });
143
156
 
144
- it('should handle large branch list (200+ branches)', () => {
157
+ it("should handle large branch list (200+ branches)", () => {
145
158
  const branches = generateMockBranches(250);
146
159
  const stats: Statistics = {
147
160
  total: branches.length,
148
- local: branches.filter((b) => b.type === 'local').length,
149
- remote: branches.filter((b) => b.type === 'remote').length,
161
+ local: branches.filter((b) => b.type === "local").length,
162
+ remote: branches.filter((b) => b.type === "remote").length,
150
163
  current: 1,
151
- feature: branches.filter((b) => b.branchType === 'feature').length,
152
- hotfix: branches.filter((b) => b.branchType === 'hotfix').length,
153
- release: branches.filter((b) => b.branchType === 'release').length,
164
+ feature: branches.filter((b) => b.branchType === "feature").length,
165
+ hotfix: branches.filter((b) => b.branchType === "hotfix").length,
166
+ release: branches.filter((b) => b.branchType === "release").length,
154
167
  worktree: branches.filter((b) => b.worktree).length,
155
168
  };
156
169
 
@@ -163,7 +176,7 @@ describe('BranchListScreen Performance', () => {
163
176
  onSelect={() => {}}
164
177
  onNavigate={() => {}}
165
178
  onQuit={() => {}}
166
- />
179
+ />,
167
180
  );
168
181
 
169
182
  const renderTime = performance.now() - startTime;