@akiojin/gwt 2.0.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 (132) hide show
  1. package/README.ja.md +323 -0
  2. package/README.md +347 -0
  3. package/bin/gwt.js +5 -0
  4. package/package.json +125 -0
  5. package/src/claude-history.ts +717 -0
  6. package/src/claude.ts +292 -0
  7. package/src/cli/ui/__tests__/SKIPPED_TESTS.md +119 -0
  8. package/src/cli/ui/__tests__/acceptance/branchList.acceptance.test.tsx.skip +239 -0
  9. package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +214 -0
  10. package/src/cli/ui/__tests__/acceptance/realtimeUpdate.acceptance.test.tsx.skip +219 -0
  11. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +183 -0
  12. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +313 -0
  13. package/src/cli/ui/__tests__/components/App.test.tsx +270 -0
  14. package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +66 -0
  15. package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +103 -0
  16. package/src/cli/ui/__tests__/components/common/Input.test.tsx +92 -0
  17. package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +127 -0
  18. package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +264 -0
  19. package/src/cli/ui/__tests__/components/common/Select.test.tsx +246 -0
  20. package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +62 -0
  21. package/src/cli/ui/__tests__/components/parts/Header.test.tsx +54 -0
  22. package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +68 -0
  23. package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +135 -0
  24. package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +153 -0
  25. package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +215 -0
  26. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +293 -0
  27. package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +161 -0
  28. package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +215 -0
  29. package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +99 -0
  30. package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +127 -0
  31. package/src/cli/ui/__tests__/hooks/useGitData.test.ts.skip +228 -0
  32. package/src/cli/ui/__tests__/hooks/useScreenState.test.ts +146 -0
  33. package/src/cli/ui/__tests__/hooks/useTerminalSize.test.ts +98 -0
  34. package/src/cli/ui/__tests__/integration/branchList.test.tsx.skip +253 -0
  35. package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +306 -0
  36. package/src/cli/ui/__tests__/integration/navigation.test.tsx +405 -0
  37. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +505 -0
  38. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx.skip +216 -0
  39. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +180 -0
  40. package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +237 -0
  41. package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +775 -0
  42. package/src/cli/ui/__tests__/utils/statisticsCalculator.test.ts +243 -0
  43. package/src/cli/ui/components/App.tsx +793 -0
  44. package/src/cli/ui/components/common/Confirm.tsx +40 -0
  45. package/src/cli/ui/components/common/ErrorBoundary.tsx +57 -0
  46. package/src/cli/ui/components/common/Input.tsx +36 -0
  47. package/src/cli/ui/components/common/LoadingIndicator.tsx +95 -0
  48. package/src/cli/ui/components/common/Select.tsx +216 -0
  49. package/src/cli/ui/components/parts/Footer.tsx +41 -0
  50. package/src/cli/ui/components/parts/Header.test.tsx +85 -0
  51. package/src/cli/ui/components/parts/Header.tsx +63 -0
  52. package/src/cli/ui/components/parts/MergeStatusList.tsx +75 -0
  53. package/src/cli/ui/components/parts/ProgressBar.tsx +73 -0
  54. package/src/cli/ui/components/parts/ScrollableList.tsx +24 -0
  55. package/src/cli/ui/components/parts/Stats.tsx +67 -0
  56. package/src/cli/ui/components/screens/AIToolSelectorScreen.tsx +116 -0
  57. package/src/cli/ui/components/screens/BatchMergeProgressScreen.tsx +70 -0
  58. package/src/cli/ui/components/screens/BatchMergeResultScreen.tsx +104 -0
  59. package/src/cli/ui/components/screens/BranchCreatorScreen.tsx +213 -0
  60. package/src/cli/ui/components/screens/BranchListScreen.tsx +299 -0
  61. package/src/cli/ui/components/screens/ExecutionModeSelectorScreen.tsx +149 -0
  62. package/src/cli/ui/components/screens/PRCleanupScreen.tsx +167 -0
  63. package/src/cli/ui/components/screens/SessionSelectorScreen.tsx +100 -0
  64. package/src/cli/ui/components/screens/WorktreeManagerScreen.tsx +117 -0
  65. package/src/cli/ui/hooks/useBatchMerge.ts +96 -0
  66. package/src/cli/ui/hooks/useGitData.ts +157 -0
  67. package/src/cli/ui/hooks/useScreenState.ts +44 -0
  68. package/src/cli/ui/hooks/useTerminalSize.ts +33 -0
  69. package/src/cli/ui/screens/BranchActionSelectorScreen.tsx +102 -0
  70. package/src/cli/ui/screens/__tests__/BranchActionSelectorScreen.test.tsx +151 -0
  71. package/src/cli/ui/types.ts +295 -0
  72. package/src/cli/ui/utils/baseBranch.ts +34 -0
  73. package/src/cli/ui/utils/branchFormatter.ts +222 -0
  74. package/src/cli/ui/utils/statisticsCalculator.ts +44 -0
  75. package/src/codex.ts +139 -0
  76. package/src/config/builtin-tools.ts +44 -0
  77. package/src/config/constants.ts +100 -0
  78. package/src/config/env-history.ts +45 -0
  79. package/src/config/index.ts +204 -0
  80. package/src/config/tools.ts +293 -0
  81. package/src/git.ts +1102 -0
  82. package/src/github.ts +158 -0
  83. package/src/index.test.ts +87 -0
  84. package/src/index.ts +684 -0
  85. package/src/index.ts.backup +1543 -0
  86. package/src/launcher.ts +142 -0
  87. package/src/repositories/git.repository.ts +129 -0
  88. package/src/repositories/github.repository.ts +83 -0
  89. package/src/repositories/worktree.repository.ts +69 -0
  90. package/src/services/BatchMergeService.ts +251 -0
  91. package/src/services/WorktreeOrchestrator.ts +115 -0
  92. package/src/services/__tests__/BatchMergeService.test.ts +518 -0
  93. package/src/services/__tests__/WorktreeOrchestrator.test.ts +258 -0
  94. package/src/services/dependency-installer.ts +199 -0
  95. package/src/services/git.service.ts +113 -0
  96. package/src/services/github.service.ts +61 -0
  97. package/src/services/worktree.service.ts +66 -0
  98. package/src/types/api.ts +241 -0
  99. package/src/types/tools.ts +235 -0
  100. package/src/utils/spinner.ts +54 -0
  101. package/src/utils/terminal.ts +272 -0
  102. package/src/utils.test.ts +43 -0
  103. package/src/utils.ts +60 -0
  104. package/src/web/client/index.html +12 -0
  105. package/src/web/client/src/components/BranchGraph.tsx +231 -0
  106. package/src/web/client/src/components/EnvEditor.tsx +145 -0
  107. package/src/web/client/src/components/Terminal.tsx +137 -0
  108. package/src/web/client/src/hooks/useBranches.ts +41 -0
  109. package/src/web/client/src/hooks/useConfig.ts +31 -0
  110. package/src/web/client/src/hooks/useSessions.ts +59 -0
  111. package/src/web/client/src/hooks/useWorktrees.ts +47 -0
  112. package/src/web/client/src/index.css +834 -0
  113. package/src/web/client/src/lib/api.ts +184 -0
  114. package/src/web/client/src/lib/websocket.ts +174 -0
  115. package/src/web/client/src/main.tsx +29 -0
  116. package/src/web/client/src/pages/BranchDetailPage.tsx +847 -0
  117. package/src/web/client/src/pages/BranchListPage.tsx +264 -0
  118. package/src/web/client/src/pages/ConfigManagementPage.tsx +203 -0
  119. package/src/web/client/src/router.tsx +27 -0
  120. package/src/web/client/vite.config.ts +21 -0
  121. package/src/web/server/env/importer.ts +54 -0
  122. package/src/web/server/index.ts +74 -0
  123. package/src/web/server/pty/manager.ts +189 -0
  124. package/src/web/server/routes/branches.ts +126 -0
  125. package/src/web/server/routes/config.ts +220 -0
  126. package/src/web/server/routes/index.ts +37 -0
  127. package/src/web/server/routes/sessions.ts +130 -0
  128. package/src/web/server/routes/worktrees.ts +108 -0
  129. package/src/web/server/services/branches.ts +368 -0
  130. package/src/web/server/services/worktrees.ts +85 -0
  131. package/src/web/server/websocket/handler.ts +180 -0
  132. package/src/worktree.ts +703 -0
@@ -0,0 +1,180 @@
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
+
7
+ /**
8
+ * Generate mock branch items for performance testing
9
+ */
10
+ function generateMockBranches(count: number): BranchItem[] {
11
+ const branches: BranchItem[] = [];
12
+ const types = ['feature', 'hotfix', 'release', 'other'] as const;
13
+ const branchTypes = ['main', 'develop', 'feature', 'hotfix', 'release', 'other'] as const;
14
+
15
+ for (let i = 0; i < count; i++) {
16
+ const type = types[i % types.length];
17
+ const branchType = branchTypes[i % branchTypes.length];
18
+ const hasWorktree = i % 3 === 0;
19
+
20
+ branches.push({
21
+ name: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
22
+ branchType,
23
+ type: i % 10 === 0 ? 'remote' : 'local',
24
+ isCurrent: i === 0,
25
+ worktree: hasWorktree
26
+ ? {
27
+ path: `/mock/worktree/${type}-${i}`,
28
+ branch: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
29
+ isAccessible: i % 5 !== 0, // Some inaccessible
30
+ }
31
+ : undefined,
32
+ worktreeStatus: hasWorktree ? (i % 5 !== 0 ? 'active' : 'inaccessible') : undefined,
33
+ hasChanges: i % 4 === 0,
34
+ icons: [],
35
+ label: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
36
+ value: `${type}/test-branch-${i.toString().padStart(4, '0')}`,
37
+ });
38
+ }
39
+
40
+ return branches;
41
+ }
42
+
43
+ // Unused for now - keeping for potential future use
44
+ // const mockStats: Statistics = {
45
+ // total: 0,
46
+ // local: 0,
47
+ // remote: 0,
48
+ // current: 0,
49
+ // feature: 0,
50
+ // hotfix: 0,
51
+ // release: 0,
52
+ // worktree: 0,
53
+ // };
54
+
55
+ describe('BranchListScreen Performance', () => {
56
+ it('should render 100+ branches within acceptable time', () => {
57
+ const branches = generateMockBranches(150);
58
+ const stats: Statistics = {
59
+ total: branches.length,
60
+ local: branches.filter((b) => b.type === 'local').length,
61
+ remote: branches.filter((b) => b.type === 'remote').length,
62
+ 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,
66
+ worktree: branches.filter((b) => b.worktree).length,
67
+ };
68
+
69
+ const startTime = performance.now();
70
+
71
+ const { unmount } = render(
72
+ <BranchListScreen
73
+ branches={branches}
74
+ stats={stats}
75
+ onSelect={() => {}}
76
+ onNavigate={() => {}}
77
+ onQuit={() => {}}
78
+ />
79
+ );
80
+
81
+ const renderTime = performance.now() - startTime;
82
+
83
+ unmount();
84
+
85
+ // Rendering should complete within 500ms (generous threshold)
86
+ expect(renderTime).toBeLessThan(500);
87
+
88
+ // Log performance metrics
89
+ console.log(`\n📊 Performance Test Results:`);
90
+ console.log(` Branches: ${branches.length}`);
91
+ console.log(` Render time: ${renderTime.toFixed(2)}ms`);
92
+ console.log(` Average per branch: ${(renderTime / branches.length).toFixed(3)}ms`);
93
+ });
94
+
95
+ it('should handle re-render efficiently when stats update', () => {
96
+ const branches = generateMockBranches(100);
97
+ const stats: Statistics = {
98
+ total: branches.length,
99
+ local: branches.filter((b) => b.type === 'local').length,
100
+ remote: branches.filter((b) => b.type === 'remote').length,
101
+ 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,
105
+ worktree: branches.filter((b) => b.worktree).length,
106
+ };
107
+
108
+ const { rerender, unmount } = render(
109
+ <BranchListScreen
110
+ branches={branches}
111
+ stats={stats}
112
+ onSelect={() => {}}
113
+ onNavigate={() => {}}
114
+ onQuit={() => {}}
115
+ lastUpdated={new Date()}
116
+ />
117
+ );
118
+
119
+ // Simulate stats update (real-time refresh)
120
+ const startTime = performance.now();
121
+
122
+ rerender(
123
+ <BranchListScreen
124
+ branches={branches}
125
+ stats={{ ...stats, total: stats.total + 1 }}
126
+ onSelect={() => {}}
127
+ onNavigate={() => {}}
128
+ onQuit={() => {}}
129
+ lastUpdated={new Date()}
130
+ />
131
+ );
132
+
133
+ const rerenderTime = performance.now() - startTime;
134
+
135
+ unmount();
136
+
137
+ // Re-render should be very fast (< 100ms)
138
+ expect(rerenderTime).toBeLessThan(100);
139
+
140
+ console.log(`\n🔄 Re-render Performance:`);
141
+ console.log(` Re-render time: ${rerenderTime.toFixed(2)}ms`);
142
+ });
143
+
144
+ it('should handle large branch list (200+ branches)', () => {
145
+ const branches = generateMockBranches(250);
146
+ const stats: Statistics = {
147
+ total: branches.length,
148
+ local: branches.filter((b) => b.type === 'local').length,
149
+ remote: branches.filter((b) => b.type === 'remote').length,
150
+ 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,
154
+ worktree: branches.filter((b) => b.worktree).length,
155
+ };
156
+
157
+ const startTime = performance.now();
158
+
159
+ const { unmount } = render(
160
+ <BranchListScreen
161
+ branches={branches}
162
+ stats={stats}
163
+ onSelect={() => {}}
164
+ onNavigate={() => {}}
165
+ onQuit={() => {}}
166
+ />
167
+ );
168
+
169
+ const renderTime = performance.now() - startTime;
170
+
171
+ unmount();
172
+
173
+ // Even with 250+ branches, should render within 1 second
174
+ expect(renderTime).toBeLessThan(1000);
175
+
176
+ console.log(`\n🚀 Large Branch List Performance:`);
177
+ console.log(` Branches: ${branches.length}`);
178
+ console.log(` Render time: ${renderTime.toFixed(2)}ms`);
179
+ });
180
+ });
@@ -0,0 +1,237 @@
1
+ /**
2
+ * @vitest-environment happy-dom
3
+ */
4
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
5
+ import { render } from '@testing-library/react';
6
+ import React, { useMemo } from 'react';
7
+ import { Window } from 'happy-dom';
8
+ import type { BranchInfo, WorktreeInfo } from '../../types.js';
9
+ import { formatBranchItems } from '../../utils/branchFormatter.js';
10
+
11
+ /**
12
+ * T082-1: useMemo optimization tests
13
+ * Tests that branchItems are not unnecessarily regenerated when data content is the same
14
+ */
15
+
16
+ // Mock useGitData hook
17
+ vi.mock('../../hooks/useGitData.js', () => ({
18
+ useGitData: vi.fn(),
19
+ }));
20
+
21
+ import { useGitData } from '../../hooks/useGitData.js';
22
+ // const mockUseGitData = useGitData as ReturnType<typeof vi.fn>;
23
+
24
+ // Helper function to create a stable hash of branch data
25
+ function createBranchHash(branches: BranchInfo[]): string {
26
+ return branches
27
+ .map((b) => `${b.name}-${b.type}-${b.isCurrent}`)
28
+ .join(',');
29
+ }
30
+
31
+ // Helper function to create a stable hash of worktree data
32
+ function createWorktreeHash(worktrees: WorktreeInfo[]): string {
33
+ return worktrees
34
+ .map((w) => `${w.branch}-${w.path}`)
35
+ .join(',');
36
+ }
37
+
38
+ // Test component that uses optimized useMemo
39
+ function TestComponent({ branches, worktrees }: { branches: BranchInfo[]; worktrees: WorktreeInfo[] }) {
40
+ // Count how many times formatBranchItems is called
41
+ const formatCallCount = React.useRef(0);
42
+
43
+ // Optimized useMemo with content-based dependencies
44
+ const branchItems = useMemo(() => {
45
+ formatCallCount.current++;
46
+ const worktreeMap = new Map();
47
+ for (const wt of worktrees) {
48
+ worktreeMap.set(wt.branch, {
49
+ path: wt.path,
50
+ locked: false,
51
+ prunable: wt.isAccessible === false,
52
+ isAccessible: wt.isAccessible ?? true,
53
+ });
54
+ }
55
+ return formatBranchItems(branches, worktreeMap);
56
+ }, [
57
+ createBranchHash(branches),
58
+ createWorktreeHash(worktrees),
59
+ ]);
60
+
61
+ return (
62
+ <div data-testid="branch-count">{branchItems.length}</div>
63
+ );
64
+ }
65
+
66
+ describe('useMemo Optimization (T082-1)', () => {
67
+ beforeEach(() => {
68
+ const window = new Window();
69
+ globalThis.window = window as any;
70
+ globalThis.document = window.document as any;
71
+ vi.clearAllMocks();
72
+ });
73
+
74
+ it('should not regenerate branchItems when data content is the same', () => {
75
+ const mockBranches: BranchInfo[] = [
76
+ {
77
+ name: 'main',
78
+ branchType: 'main',
79
+ type: 'local',
80
+ isCurrent: true,
81
+ },
82
+ {
83
+ name: 'feature/test-1',
84
+ branchType: 'feature',
85
+ type: 'local',
86
+ isCurrent: false,
87
+ },
88
+ ];
89
+
90
+ const mockWorktrees: WorktreeInfo[] = [
91
+ {
92
+ path: '/mock/worktree/feature-test-1',
93
+ branch: 'feature/test-1',
94
+ isAccessible: true,
95
+ },
96
+ ];
97
+
98
+ const { rerender } = render(
99
+ <TestComponent branches={mockBranches} worktrees={mockWorktrees} />
100
+ );
101
+
102
+ // Create new arrays with the same content
103
+ const sameBranches: BranchInfo[] = [
104
+ {
105
+ name: 'main',
106
+ branchType: 'main',
107
+ type: 'local',
108
+ isCurrent: true,
109
+ },
110
+ {
111
+ name: 'feature/test-1',
112
+ branchType: 'feature',
113
+ type: 'local',
114
+ isCurrent: false,
115
+ },
116
+ ];
117
+
118
+ const sameWorktrees: WorktreeInfo[] = [
119
+ {
120
+ path: '/mock/worktree/feature-test-1',
121
+ branch: 'feature/test-1',
122
+ isAccessible: true,
123
+ },
124
+ ];
125
+
126
+ // Verify that arrays are different references
127
+ expect(sameBranches).not.toBe(mockBranches);
128
+ expect(sameWorktrees).not.toBe(mockWorktrees);
129
+
130
+ // Verify that content is the same
131
+ expect(createBranchHash(sameBranches)).toBe(createBranchHash(mockBranches));
132
+ expect(createWorktreeHash(sameWorktrees)).toBe(createWorktreeHash(mockWorktrees));
133
+
134
+ // Re-render with same content but different references
135
+ rerender(
136
+ <TestComponent branches={sameBranches} worktrees={sameWorktrees} />
137
+ );
138
+
139
+ // formatBranchItems should only be called once (not twice)
140
+ // This test would fail with the current implementation because useMemo
141
+ // depends on array references, not content
142
+ });
143
+
144
+ it('should regenerate branchItems when data content changes', () => {
145
+ const initialBranches: BranchInfo[] = [
146
+ {
147
+ name: 'main',
148
+ branchType: 'main',
149
+ type: 'local',
150
+ isCurrent: true,
151
+ },
152
+ ];
153
+
154
+ const { rerender } = render(
155
+ <TestComponent branches={initialBranches} worktrees={[]} />
156
+ );
157
+
158
+ // Add a new branch
159
+ const updatedBranches: BranchInfo[] = [
160
+ ...initialBranches,
161
+ {
162
+ name: 'feature/new',
163
+ branchType: 'feature',
164
+ type: 'local',
165
+ isCurrent: false,
166
+ },
167
+ ];
168
+
169
+ // Verify content changed
170
+ expect(createBranchHash(updatedBranches)).not.toBe(createBranchHash(initialBranches));
171
+
172
+ // Re-render with new content
173
+ rerender(
174
+ <TestComponent branches={updatedBranches} worktrees={[]} />
175
+ );
176
+
177
+ // formatBranchItems should be called twice (once for initial, once for update)
178
+ });
179
+
180
+ it('should handle branch order changes correctly', () => {
181
+ const branches1: BranchInfo[] = [
182
+ {
183
+ name: 'main',
184
+ branchType: 'main',
185
+ type: 'local',
186
+ isCurrent: true,
187
+ },
188
+ {
189
+ name: 'feature/test',
190
+ branchType: 'feature',
191
+ type: 'local',
192
+ isCurrent: false,
193
+ },
194
+ ];
195
+
196
+ const branches2: BranchInfo[] = [
197
+ {
198
+ name: 'feature/test',
199
+ branchType: 'feature',
200
+ type: 'local',
201
+ isCurrent: false,
202
+ },
203
+ {
204
+ name: 'main',
205
+ branchType: 'main',
206
+ type: 'local',
207
+ isCurrent: true,
208
+ },
209
+ ];
210
+
211
+ // Different order should produce different hashes
212
+ expect(createBranchHash(branches1)).not.toBe(createBranchHash(branches2));
213
+ });
214
+
215
+ it('should detect subtle branch property changes', () => {
216
+ const branches1: BranchInfo[] = [
217
+ {
218
+ name: 'main',
219
+ branchType: 'main',
220
+ type: 'local',
221
+ isCurrent: false,
222
+ },
223
+ ];
224
+
225
+ const branches2: BranchInfo[] = [
226
+ {
227
+ name: 'main',
228
+ branchType: 'main',
229
+ type: 'local',
230
+ isCurrent: true, // Changed from false to true
231
+ },
232
+ ];
233
+
234
+ // isCurrent change should be detected
235
+ expect(createBranchHash(branches1)).not.toBe(createBranchHash(branches2));
236
+ });
237
+ });