@akiojin/gwt 2.2.0 → 2.3.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 (149) hide show
  1. package/README.ja.md +4 -4
  2. package/README.md +4 -4
  3. package/dist/cli/ui/components/App.d.ts +4 -4
  4. package/dist/cli/ui/components/App.d.ts.map +1 -1
  5. package/dist/cli/ui/components/App.js +144 -105
  6. package/dist/cli/ui/components/App.js.map +1 -1
  7. package/dist/cli/ui/components/common/Confirm.d.ts +1 -1
  8. package/dist/cli/ui/components/common/Confirm.d.ts.map +1 -1
  9. package/dist/cli/ui/components/common/Confirm.js +7 -7
  10. package/dist/cli/ui/components/common/Confirm.js.map +1 -1
  11. package/dist/cli/ui/components/common/ErrorBoundary.d.ts +1 -1
  12. package/dist/cli/ui/components/common/ErrorBoundary.d.ts.map +1 -1
  13. package/dist/cli/ui/components/common/ErrorBoundary.js +4 -4
  14. package/dist/cli/ui/components/common/ErrorBoundary.js.map +1 -1
  15. package/dist/cli/ui/components/common/Input.d.ts +2 -2
  16. package/dist/cli/ui/components/common/Input.d.ts.map +1 -1
  17. package/dist/cli/ui/components/common/Input.js +4 -4
  18. package/dist/cli/ui/components/common/Input.js.map +1 -1
  19. package/dist/cli/ui/components/common/LoadingIndicator.d.ts +1 -1
  20. package/dist/cli/ui/components/common/LoadingIndicator.d.ts.map +1 -1
  21. package/dist/cli/ui/components/common/LoadingIndicator.js +4 -4
  22. package/dist/cli/ui/components/common/LoadingIndicator.js.map +1 -1
  23. package/dist/cli/ui/components/common/Select.d.ts +1 -1
  24. package/dist/cli/ui/components/common/Select.d.ts.map +1 -1
  25. package/dist/cli/ui/components/common/Select.js +11 -12
  26. package/dist/cli/ui/components/common/Select.js.map +1 -1
  27. package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts +2 -2
  28. package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts.map +1 -1
  29. package/dist/cli/ui/components/screens/AIToolSelectorScreen.js +11 -11
  30. package/dist/cli/ui/components/screens/AIToolSelectorScreen.js.map +1 -1
  31. package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts +1 -1
  32. package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts.map +1 -1
  33. package/dist/cli/ui/components/screens/BranchCreatorScreen.js +39 -36
  34. package/dist/cli/ui/components/screens/BranchCreatorScreen.js.map +1 -1
  35. package/dist/cli/ui/components/screens/BranchListScreen.d.ts +3 -3
  36. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  37. package/dist/cli/ui/components/screens/BranchListScreen.js +55 -50
  38. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  39. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts +2 -2
  40. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts.map +1 -1
  41. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js +25 -25
  42. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js.map +1 -1
  43. package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts +2 -2
  44. package/dist/cli/ui/components/screens/PRCleanupScreen.js +21 -21
  45. package/dist/cli/ui/components/screens/SessionSelectorScreen.d.ts +1 -1
  46. package/dist/cli/ui/components/screens/SessionSelectorScreen.js +8 -8
  47. package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts +1 -1
  48. package/dist/cli/ui/components/screens/WorktreeManagerScreen.js +8 -8
  49. package/dist/cli/ui/screens/BranchActionSelectorScreen.d.ts.map +1 -1
  50. package/dist/cli/ui/screens/BranchActionSelectorScreen.js +7 -4
  51. package/dist/cli/ui/screens/BranchActionSelectorScreen.js.map +1 -1
  52. package/dist/cli/ui/types.d.ts.map +1 -1
  53. package/dist/client/assets/{index-V6hDu9KS.js → index-Difv1Hwu.js} +2 -2
  54. package/dist/client/index.html +1 -1
  55. package/dist/config/builtin-tools.d.ts +10 -2
  56. package/dist/config/builtin-tools.d.ts.map +1 -1
  57. package/dist/config/builtin-tools.js +40 -4
  58. package/dist/config/builtin-tools.js.map +1 -1
  59. package/dist/config/index.d.ts.map +1 -1
  60. package/dist/config/index.js.map +1 -1
  61. package/dist/config/tools.d.ts.map +1 -1
  62. package/dist/config/tools.js +4 -3
  63. package/dist/config/tools.js.map +1 -1
  64. package/dist/gemini.d.ts +12 -0
  65. package/dist/gemini.d.ts.map +1 -0
  66. package/dist/gemini.js +154 -0
  67. package/dist/gemini.js.map +1 -0
  68. package/dist/git.d.ts.map +1 -1
  69. package/dist/git.js.map +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +30 -0
  72. package/dist/index.js.map +1 -1
  73. package/dist/qwen.d.ts +12 -0
  74. package/dist/qwen.d.ts.map +1 -0
  75. package/dist/qwen.js +154 -0
  76. package/dist/qwen.js.map +1 -0
  77. package/dist/services/git.service.d.ts.map +1 -1
  78. package/dist/services/git.service.js.map +1 -1
  79. package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
  80. package/dist/web/client/src/components/BranchGraph.js +1 -1
  81. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  82. package/dist/web/client/src/components/EnvEditor.d.ts.map +1 -1
  83. package/dist/web/client/src/components/EnvEditor.js +7 -4
  84. package/dist/web/client/src/components/EnvEditor.js.map +1 -1
  85. package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
  86. package/dist/web/client/src/pages/BranchDetailPage.js +55 -18
  87. package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
  88. package/dist/web/client/src/pages/BranchListPage.d.ts.map +1 -1
  89. package/dist/web/client/src/pages/BranchListPage.js +10 -4
  90. package/dist/web/client/src/pages/BranchListPage.js.map +1 -1
  91. package/dist/web/client/src/pages/ConfigManagementPage.d.ts.map +1 -1
  92. package/dist/web/client/src/pages/ConfigManagementPage.js +4 -2
  93. package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
  94. package/package.json +2 -1
  95. package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +69 -50
  96. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +67 -45
  97. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +117 -75
  98. package/src/cli/ui/__tests__/components/App.test.tsx +45 -37
  99. package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +35 -22
  100. package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +22 -22
  101. package/src/cli/ui/__tests__/components/common/Input.test.tsx +29 -22
  102. package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +40 -34
  103. package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +57 -66
  104. package/src/cli/ui/__tests__/components/common/Select.test.tsx +121 -91
  105. package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +18 -16
  106. package/src/cli/ui/__tests__/components/parts/Header.test.tsx +13 -13
  107. package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +20 -20
  108. package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +38 -26
  109. package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +31 -31
  110. package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +73 -37
  111. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +261 -153
  112. package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +38 -32
  113. package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +39 -39
  114. package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +49 -21
  115. package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +52 -28
  116. package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +84 -48
  117. package/src/cli/ui/__tests__/integration/navigation.test.tsx +111 -83
  118. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +111 -108
  119. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +50 -37
  120. package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +75 -76
  121. package/src/cli/ui/components/App.tsx +247 -150
  122. package/src/cli/ui/components/common/Confirm.tsx +13 -9
  123. package/src/cli/ui/components/common/ErrorBoundary.tsx +8 -5
  124. package/src/cli/ui/components/common/Input.tsx +12 -4
  125. package/src/cli/ui/components/common/LoadingIndicator.tsx +8 -5
  126. package/src/cli/ui/components/common/Select.tsx +28 -17
  127. package/src/cli/ui/components/parts/Header.test.tsx +5 -15
  128. package/src/cli/ui/components/screens/AIToolSelectorScreen.tsx +19 -13
  129. package/src/cli/ui/components/screens/BranchCreatorScreen.tsx +74 -54
  130. package/src/cli/ui/components/screens/BranchListScreen.tsx +92 -75
  131. package/src/cli/ui/components/screens/ExecutionModeSelectorScreen.tsx +35 -28
  132. package/src/cli/ui/components/screens/PRCleanupScreen.tsx +22 -22
  133. package/src/cli/ui/components/screens/SessionSelectorScreen.tsx +8 -8
  134. package/src/cli/ui/components/screens/WorktreeManagerScreen.tsx +8 -8
  135. package/src/cli/ui/screens/BranchActionSelectorScreen.tsx +9 -4
  136. package/src/cli/ui/types.ts +8 -1
  137. package/src/config/builtin-tools.ts +42 -4
  138. package/src/config/index.ts +2 -12
  139. package/src/config/tools.ts +16 -6
  140. package/src/gemini.ts +202 -0
  141. package/src/git.ts +2 -1
  142. package/src/index.ts +30 -0
  143. package/src/qwen.ts +208 -0
  144. package/src/services/git.service.ts +2 -1
  145. package/src/web/client/src/components/BranchGraph.tsx +3 -2
  146. package/src/web/client/src/components/EnvEditor.tsx +44 -11
  147. package/src/web/client/src/pages/BranchDetailPage.tsx +165 -54
  148. package/src/web/client/src/pages/BranchListPage.tsx +37 -13
  149. package/src/web/client/src/pages/ConfigManagementPage.tsx +28 -9
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @vitest-environment happy-dom
3
3
  */
4
- import { describe, it, expect, beforeEach, vi } from 'vitest';
5
- import { render } from '@testing-library/react';
6
- import React from 'react';
7
- import { ExecutionModeSelectorScreen } from '../../../components/screens/ExecutionModeSelectorScreen.js';
8
- import { Window } from 'happy-dom';
4
+ import { describe, it, expect, beforeEach, vi } from "vitest";
5
+ import { render } from "@testing-library/react";
6
+ import React from "react";
7
+ import { ExecutionModeSelectorScreen } from "../../../components/screens/ExecutionModeSelectorScreen.js";
8
+ import { Window } from "happy-dom";
9
9
 
10
- describe('ExecutionModeSelectorScreen', () => {
10
+ describe("ExecutionModeSelectorScreen", () => {
11
11
  beforeEach(() => {
12
12
  // Setup happy-dom
13
13
  const window = new Window();
@@ -15,21 +15,21 @@ describe('ExecutionModeSelectorScreen', () => {
15
15
  globalThis.document = window.document as any;
16
16
  });
17
17
 
18
- it('should render header with title', () => {
18
+ it("should render header with title", () => {
19
19
  const onBack = vi.fn();
20
20
  const onSelect = vi.fn();
21
21
  const { container } = render(
22
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
22
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
23
23
  );
24
24
 
25
25
  expect(container).toBeDefined();
26
26
  });
27
27
 
28
- it('should render execution mode options', () => {
28
+ it("should render execution mode options", () => {
29
29
  const onBack = vi.fn();
30
30
  const onSelect = vi.fn();
31
31
  const { getByText } = render(
32
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
32
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
33
33
  );
34
34
 
35
35
  expect(getByText(/Normal/i)).toBeDefined();
@@ -37,25 +37,25 @@ describe('ExecutionModeSelectorScreen', () => {
37
37
  expect(getByText(/Resume/i)).toBeDefined();
38
38
  });
39
39
 
40
- it('should render footer with actions', () => {
40
+ it("should render footer with actions", () => {
41
41
  const onBack = vi.fn();
42
42
  const onSelect = vi.fn();
43
43
  const { getAllByText } = render(
44
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
44
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
45
45
  );
46
46
 
47
47
  expect(getAllByText(/enter/i).length).toBeGreaterThan(0);
48
48
  expect(getAllByText(/esc/i).length).toBeGreaterThan(0);
49
49
  });
50
50
 
51
- it('should use terminal height for layout calculation', () => {
51
+ it("should use terminal height for layout calculation", () => {
52
52
  const originalRows = process.stdout.rows;
53
53
  process.stdout.rows = 30;
54
54
 
55
55
  const onBack = vi.fn();
56
56
  const onSelect = vi.fn();
57
57
  const { container } = render(
58
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
58
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
59
59
  );
60
60
 
61
61
  expect(container).toBeDefined();
@@ -63,22 +63,22 @@ describe('ExecutionModeSelectorScreen', () => {
63
63
  process.stdout.rows = originalRows;
64
64
  });
65
65
 
66
- it('should handle back navigation with ESC key', () => {
66
+ it("should handle back navigation with ESC key", () => {
67
67
  const onBack = vi.fn();
68
68
  const onSelect = vi.fn();
69
69
  const { container } = render(
70
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
70
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
71
71
  );
72
72
 
73
73
  // Test will verify onBack is called when ESC is pressed
74
74
  expect(container).toBeDefined();
75
75
  });
76
76
 
77
- it('should handle mode selection', () => {
77
+ it("should handle mode selection", () => {
78
78
  const onBack = vi.fn();
79
79
  const onSelect = vi.fn();
80
80
  const { container } = render(
81
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
81
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
82
82
  );
83
83
 
84
84
  // Test will verify onSelect is called with correct mode
@@ -87,12 +87,12 @@ describe('ExecutionModeSelectorScreen', () => {
87
87
 
88
88
  // TDD: Tests for 2-step selection (mode + skipPermissions)
89
89
  // TODO: Implement integration tests with user interaction simulation
90
- describe.skip('Skip Permissions Selection', () => {
91
- it('should render skip permissions prompt after mode selection', () => {
90
+ describe.skip("Skip Permissions Selection", () => {
91
+ it("should render skip permissions prompt after mode selection", () => {
92
92
  const onBack = vi.fn();
93
93
  const onSelect = vi.fn();
94
94
  const { getByText } = render(
95
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
95
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
96
96
  );
97
97
 
98
98
  // After selecting a mode, should show skip permissions prompt
@@ -100,11 +100,11 @@ describe('ExecutionModeSelectorScreen', () => {
100
100
  expect(getByText(/Skip permission checks/i)).toBeDefined();
101
101
  });
102
102
 
103
- it('should show correct flag hints for skipPermissions prompt', () => {
103
+ it("should show correct flag hints for skipPermissions prompt", () => {
104
104
  const onBack = vi.fn();
105
105
  const onSelect = vi.fn();
106
106
  const { getByText } = render(
107
- <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />
107
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
108
108
  );
109
109
 
110
110
  // Should show both --dangerously-skip-permissions and --yolo hints
@@ -112,10 +112,12 @@ describe('ExecutionModeSelectorScreen', () => {
112
112
  expect(getByText(/--yolo/i)).toBeDefined();
113
113
  });
114
114
 
115
- it('should call onSelect with mode and skipPermissions=true when Yes is selected', () => {
115
+ it("should call onSelect with mode and skipPermissions=true when Yes is selected", () => {
116
116
  const onBack = vi.fn();
117
117
  const onSelect = vi.fn();
118
- render(<ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />);
118
+ render(
119
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
120
+ );
119
121
 
120
122
  // After selecting mode and Yes for skipPermissions
121
123
  // onSelect should be called with { mode: 'normal', skipPermissions: true }
@@ -124,14 +126,16 @@ describe('ExecutionModeSelectorScreen', () => {
124
126
  expect.objectContaining({
125
127
  mode: expect.any(String),
126
128
  skipPermissions: true,
127
- })
129
+ }),
128
130
  );
129
131
  });
130
132
 
131
- it('should call onSelect with mode and skipPermissions=false when No is selected', () => {
133
+ it("should call onSelect with mode and skipPermissions=false when No is selected", () => {
132
134
  const onBack = vi.fn();
133
135
  const onSelect = vi.fn();
134
- render(<ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />);
136
+ render(
137
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
138
+ );
135
139
 
136
140
  // After selecting mode and No for skipPermissions
137
141
  // onSelect should be called with { mode: 'normal', skipPermissions: false }
@@ -140,21 +144,23 @@ describe('ExecutionModeSelectorScreen', () => {
140
144
  expect.objectContaining({
141
145
  mode: expect.any(String),
142
146
  skipPermissions: false,
143
- })
147
+ }),
144
148
  );
145
149
  });
146
150
 
147
- it('should default skipPermissions to false', () => {
151
+ it("should default skipPermissions to false", () => {
148
152
  const onBack = vi.fn();
149
153
  const onSelect = vi.fn();
150
- render(<ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />);
154
+ render(
155
+ <ExecutionModeSelectorScreen onBack={onBack} onSelect={onSelect} />,
156
+ );
151
157
 
152
158
  // Default should be No (skipPermissions: false)
153
159
  // This test will fail until implementation
154
160
  expect(onSelect).toHaveBeenCalledWith(
155
161
  expect.objectContaining({
156
162
  skipPermissions: false,
157
- })
163
+ }),
158
164
  );
159
165
  });
160
166
  });
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * @vitest-environment happy-dom
3
3
  */
4
- import { describe, it, expect, beforeEach, vi } from 'vitest';
5
- import { render } from '@testing-library/react';
6
- import React from 'react';
7
- import { PRCleanupScreen } from '../../../components/screens/PRCleanupScreen.js';
8
- import { Window } from 'happy-dom';
9
- import type { CleanupTarget } from '../../../types.js';
10
-
11
- describe('PRCleanupScreen', () => {
4
+ import { describe, it, expect, beforeEach, vi } from "vitest";
5
+ import { render } from "@testing-library/react";
6
+ import React from "react";
7
+ import { PRCleanupScreen } from "../../../components/screens/PRCleanupScreen.js";
8
+ import { Window } from "happy-dom";
9
+ import type { CleanupTarget } from "../../../types.js";
10
+
11
+ describe("PRCleanupScreen", () => {
12
12
  beforeEach(() => {
13
13
  // Setup happy-dom
14
14
  const window = new Window();
@@ -18,30 +18,30 @@ describe('PRCleanupScreen', () => {
18
18
 
19
19
  const mockTargets: CleanupTarget[] = [
20
20
  {
21
- branch: 'feature/add-new-feature',
22
- cleanupType: 'worktree-and-branch',
21
+ branch: "feature/add-new-feature",
22
+ cleanupType: "worktree-and-branch",
23
23
  pullRequest: {
24
24
  number: 123,
25
- title: 'Add new feature',
26
- branch: 'feature/add-new-feature',
27
- mergedAt: '2025-01-20T10:00:00Z',
28
- author: 'user1',
25
+ title: "Add new feature",
26
+ branch: "feature/add-new-feature",
27
+ mergedAt: "2025-01-20T10:00:00Z",
28
+ author: "user1",
29
29
  },
30
- worktreePath: '/workspace/feature-add-new-feature',
30
+ worktreePath: "/workspace/feature-add-new-feature",
31
31
  hasUncommittedChanges: false,
32
32
  hasUnpushedCommits: false,
33
33
  hasRemoteBranch: true,
34
34
  isAccessible: true,
35
35
  },
36
36
  {
37
- branch: 'hotfix/fix-bug',
38
- cleanupType: 'branch-only',
37
+ branch: "hotfix/fix-bug",
38
+ cleanupType: "branch-only",
39
39
  pullRequest: {
40
40
  number: 124,
41
- title: 'Fix bug',
42
- branch: 'hotfix/fix-bug',
43
- mergedAt: '2025-01-21T15:30:00Z',
44
- author: 'user2',
41
+ title: "Fix bug",
42
+ branch: "hotfix/fix-bug",
43
+ mergedAt: "2025-01-21T15:30:00Z",
44
+ author: "user2",
45
45
  },
46
46
  worktreePath: null,
47
47
  hasUncommittedChanges: false,
@@ -50,7 +50,7 @@ describe('PRCleanupScreen', () => {
50
50
  },
51
51
  ];
52
52
 
53
- it('should render header with title', () => {
53
+ it("should render header with title", () => {
54
54
  const onBack = vi.fn();
55
55
  const onCleanup = vi.fn();
56
56
  const { getByText } = render(
@@ -61,13 +61,13 @@ describe('PRCleanupScreen', () => {
61
61
  onBack={onBack}
62
62
  onRefresh={vi.fn()}
63
63
  onCleanup={onCleanup}
64
- />
64
+ />,
65
65
  );
66
66
 
67
67
  expect(getByText(/Branch Cleanup/i)).toBeDefined();
68
68
  });
69
69
 
70
- it('should render PR list', () => {
70
+ it("should render PR list", () => {
71
71
  const onBack = vi.fn();
72
72
  const onCleanup = vi.fn();
73
73
  const { getByText } = render(
@@ -78,14 +78,14 @@ describe('PRCleanupScreen', () => {
78
78
  onBack={onBack}
79
79
  onRefresh={vi.fn()}
80
80
  onCleanup={onCleanup}
81
- />
81
+ />,
82
82
  );
83
83
 
84
84
  expect(getByText(/feature\/add-new-feature/i)).toBeDefined();
85
85
  expect(getByText(/hotfix\/fix-bug/i)).toBeDefined();
86
86
  });
87
87
 
88
- it('should render footer with actions', () => {
88
+ it("should render footer with actions", () => {
89
89
  const onBack = vi.fn();
90
90
  const onCleanup = vi.fn();
91
91
  const { getAllByText } = render(
@@ -96,14 +96,14 @@ describe('PRCleanupScreen', () => {
96
96
  onBack={onBack}
97
97
  onRefresh={vi.fn()}
98
98
  onCleanup={onCleanup}
99
- />
99
+ />,
100
100
  );
101
101
 
102
102
  expect(getAllByText(/enter/i).length).toBeGreaterThan(0);
103
103
  expect(getAllByText(/esc/i).length).toBeGreaterThan(0);
104
104
  });
105
105
 
106
- it('should handle empty PR list', () => {
106
+ it("should handle empty PR list", () => {
107
107
  const onBack = vi.fn();
108
108
  const onCleanup = vi.fn();
109
109
  const { getByText } = render(
@@ -114,13 +114,13 @@ describe('PRCleanupScreen', () => {
114
114
  onBack={onBack}
115
115
  onRefresh={vi.fn()}
116
116
  onCleanup={onCleanup}
117
- />
117
+ />,
118
118
  );
119
119
 
120
120
  expect(getByText(/No cleanup targets found/i)).toBeDefined();
121
121
  });
122
122
 
123
- it('should display PR count in stats', () => {
123
+ it("should display PR count in stats", () => {
124
124
  const onBack = vi.fn();
125
125
  const onCleanup = vi.fn();
126
126
  const { getByText, getAllByText } = render(
@@ -131,14 +131,14 @@ describe('PRCleanupScreen', () => {
131
131
  onBack={onBack}
132
132
  onRefresh={vi.fn()}
133
133
  onCleanup={onCleanup}
134
- />
134
+ />,
135
135
  );
136
136
 
137
137
  expect(getByText(/Total:/i)).toBeDefined();
138
138
  expect(getAllByText(/^2$/).length).toBeGreaterThan(0);
139
139
  });
140
140
 
141
- it('should use terminal height for layout calculation', () => {
141
+ it("should use terminal height for layout calculation", () => {
142
142
  const originalRows = process.stdout.rows;
143
143
  process.stdout.rows = 30;
144
144
 
@@ -152,7 +152,7 @@ describe('PRCleanupScreen', () => {
152
152
  onBack={onBack}
153
153
  onRefresh={vi.fn()}
154
154
  onCleanup={onCleanup}
155
- />
155
+ />,
156
156
  );
157
157
 
158
158
  expect(container).toBeDefined();
@@ -160,7 +160,7 @@ describe('PRCleanupScreen', () => {
160
160
  process.stdout.rows = originalRows;
161
161
  });
162
162
 
163
- it('should handle back navigation with ESC key', () => {
163
+ it("should handle back navigation with ESC key", () => {
164
164
  const onBack = vi.fn();
165
165
  const onCleanup = vi.fn();
166
166
  const { container } = render(
@@ -171,14 +171,14 @@ describe('PRCleanupScreen', () => {
171
171
  onBack={onBack}
172
172
  onRefresh={vi.fn()}
173
173
  onCleanup={onCleanup}
174
- />
174
+ />,
175
175
  );
176
176
 
177
177
  // Test will verify onBack is called when ESC is pressed
178
178
  expect(container).toBeDefined();
179
179
  });
180
180
 
181
- it('should render status message when provided', () => {
181
+ it("should render status message when provided", () => {
182
182
  const onBack = vi.fn();
183
183
  const onCleanup = vi.fn();
184
184
  const { getByText } = render(
@@ -190,13 +190,13 @@ describe('PRCleanupScreen', () => {
190
190
  onBack={onBack}
191
191
  onRefresh={vi.fn()}
192
192
  onCleanup={onCleanup}
193
- />
193
+ />,
194
194
  );
195
195
 
196
196
  expect(getByText(/Cleanup completed/i)).toBeDefined();
197
197
  });
198
198
 
199
- it('should render loading message when loading', () => {
199
+ it("should render loading message when loading", () => {
200
200
  const onBack = vi.fn();
201
201
  const onCleanup = vi.fn();
202
202
  const { getByText } = render(
@@ -207,7 +207,7 @@ describe('PRCleanupScreen', () => {
207
207
  onBack={onBack}
208
208
  onRefresh={vi.fn()}
209
209
  onCleanup={onCleanup}
210
- />
210
+ />,
211
211
  );
212
212
 
213
213
  expect(getByText(/Loading cleanup targets/i)).toBeDefined();
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @vitest-environment happy-dom
3
3
  */
4
- import { describe, it, expect, beforeEach, vi } from 'vitest';
5
- import { render } from '@testing-library/react';
6
- import React from 'react';
7
- import { SessionSelectorScreen } from '../../../components/screens/SessionSelectorScreen.js';
8
- import { Window } from 'happy-dom';
4
+ import { describe, it, expect, beforeEach, vi } from "vitest";
5
+ import { render } from "@testing-library/react";
6
+ import React from "react";
7
+ import { SessionSelectorScreen } from "../../../components/screens/SessionSelectorScreen.js";
8
+ import { Window } from "happy-dom";
9
9
 
10
- describe('SessionSelectorScreen', () => {
10
+ describe("SessionSelectorScreen", () => {
11
11
  beforeEach(() => {
12
12
  // Setup happy-dom
13
13
  const window = new Window();
@@ -15,23 +15,31 @@ describe('SessionSelectorScreen', () => {
15
15
  globalThis.document = window.document as any;
16
16
  });
17
17
 
18
- const mockSessions = ['session-1', 'session-2', 'session-3'];
18
+ const mockSessions = ["session-1", "session-2", "session-3"];
19
19
 
20
- it('should render header with title', () => {
20
+ it("should render header with title", () => {
21
21
  const onBack = vi.fn();
22
22
  const onSelect = vi.fn();
23
23
  const { getByText } = render(
24
- <SessionSelectorScreen sessions={mockSessions} onBack={onBack} onSelect={onSelect} />
24
+ <SessionSelectorScreen
25
+ sessions={mockSessions}
26
+ onBack={onBack}
27
+ onSelect={onSelect}
28
+ />,
25
29
  );
26
30
 
27
31
  expect(getByText(/Session Selection/i)).toBeDefined();
28
32
  });
29
33
 
30
- it('should render session list', () => {
34
+ it("should render session list", () => {
31
35
  const onBack = vi.fn();
32
36
  const onSelect = vi.fn();
33
37
  const { getByText } = render(
34
- <SessionSelectorScreen sessions={mockSessions} onBack={onBack} onSelect={onSelect} />
38
+ <SessionSelectorScreen
39
+ sessions={mockSessions}
40
+ onBack={onBack}
41
+ onSelect={onSelect}
42
+ />,
35
43
  );
36
44
 
37
45
  expect(getByText(/session-1/i)).toBeDefined();
@@ -39,46 +47,62 @@ describe('SessionSelectorScreen', () => {
39
47
  expect(getByText(/session-3/i)).toBeDefined();
40
48
  });
41
49
 
42
- it('should render footer with actions', () => {
50
+ it("should render footer with actions", () => {
43
51
  const onBack = vi.fn();
44
52
  const onSelect = vi.fn();
45
53
  const { getAllByText } = render(
46
- <SessionSelectorScreen sessions={mockSessions} onBack={onBack} onSelect={onSelect} />
54
+ <SessionSelectorScreen
55
+ sessions={mockSessions}
56
+ onBack={onBack}
57
+ onSelect={onSelect}
58
+ />,
47
59
  );
48
60
 
49
61
  expect(getAllByText(/enter/i).length).toBeGreaterThan(0);
50
62
  expect(getAllByText(/esc/i).length).toBeGreaterThan(0);
51
63
  });
52
64
 
53
- it('should handle empty session list', () => {
65
+ it("should handle empty session list", () => {
54
66
  const onBack = vi.fn();
55
67
  const onSelect = vi.fn();
56
68
  const { getByText } = render(
57
- <SessionSelectorScreen sessions={[]} onBack={onBack} onSelect={onSelect} />
69
+ <SessionSelectorScreen
70
+ sessions={[]}
71
+ onBack={onBack}
72
+ onSelect={onSelect}
73
+ />,
58
74
  );
59
75
 
60
76
  expect(getByText(/No sessions found/i)).toBeDefined();
61
77
  });
62
78
 
63
- it('should display session count in stats', () => {
79
+ it("should display session count in stats", () => {
64
80
  const onBack = vi.fn();
65
81
  const onSelect = vi.fn();
66
82
  const { getByText, getAllByText } = render(
67
- <SessionSelectorScreen sessions={mockSessions} onBack={onBack} onSelect={onSelect} />
83
+ <SessionSelectorScreen
84
+ sessions={mockSessions}
85
+ onBack={onBack}
86
+ onSelect={onSelect}
87
+ />,
68
88
  );
69
89
 
70
90
  expect(getByText(/Total:/i)).toBeDefined();
71
91
  expect(getAllByText(/3/).length).toBeGreaterThan(0);
72
92
  });
73
93
 
74
- it('should use terminal height for layout calculation', () => {
94
+ it("should use terminal height for layout calculation", () => {
75
95
  const originalRows = process.stdout.rows;
76
96
  process.stdout.rows = 30;
77
97
 
78
98
  const onBack = vi.fn();
79
99
  const onSelect = vi.fn();
80
100
  const { container } = render(
81
- <SessionSelectorScreen sessions={mockSessions} onBack={onBack} onSelect={onSelect} />
101
+ <SessionSelectorScreen
102
+ sessions={mockSessions}
103
+ onBack={onBack}
104
+ onSelect={onSelect}
105
+ />,
82
106
  );
83
107
 
84
108
  expect(container).toBeDefined();
@@ -86,11 +110,15 @@ describe('SessionSelectorScreen', () => {
86
110
  process.stdout.rows = originalRows;
87
111
  });
88
112
 
89
- it('should handle back navigation with ESC key', () => {
113
+ it("should handle back navigation with ESC key", () => {
90
114
  const onBack = vi.fn();
91
115
  const onSelect = vi.fn();
92
116
  const { container } = render(
93
- <SessionSelectorScreen sessions={mockSessions} onBack={onBack} onSelect={onSelect} />
117
+ <SessionSelectorScreen
118
+ sessions={mockSessions}
119
+ onBack={onBack}
120
+ onSelect={onSelect}
121
+ />,
94
122
  );
95
123
 
96
124
  // Test will verify onBack is called when ESC is pressed