@google/gemini-cli 0.1.9-nightly.250708.137ffec3 → 0.1.9-nightly.250708.a4097ae6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/google-gemini-cli-0.1.9.tgz +0 -0
- package/dist/package.json +2 -2
- package/dist/src/config/config.js +0 -2
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/gemini.test.d.ts +6 -0
- package/dist/src/gemini.test.js +122 -0
- package/dist/src/gemini.test.js.map +1 -0
- package/dist/src/generated/git-commit.d.ts +1 -1
- package/dist/src/generated/git-commit.js +1 -1
- package/dist/src/test-utils/mockCommandContext.d.ts +18 -0
- package/dist/src/test-utils/mockCommandContext.js +75 -0
- package/dist/src/test-utils/mockCommandContext.js.map +1 -0
- package/dist/src/ui/App.test.d.ts +6 -0
- package/dist/src/ui/App.test.js +300 -0
- package/dist/src/ui/App.test.js.map +1 -0
- package/dist/src/ui/components/AuthDialog.test.d.ts +6 -0
- package/dist/src/ui/components/AuthDialog.test.js +86 -0
- package/dist/src/ui/components/AuthDialog.test.js.map +1 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.js +81 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -0
- package/dist/src/ui/components/InputPrompt.test.d.ts +6 -0
- package/dist/src/ui/components/InputPrompt.test.js +334 -0
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -0
- package/dist/src/ui/components/LoadingIndicator.js +1 -2
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.d.ts +6 -0
- package/dist/src/ui/components/LoadingIndicator.test.js +141 -0
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -0
- package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/ModelStatsDisplay.test.js +217 -0
- package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -0
- package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/SessionSummaryDisplay.test.js +60 -0
- package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -0
- package/dist/src/ui/components/StatsDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/StatsDisplay.test.js +275 -0
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -0
- package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/ToolStatsDisplay.test.js +160 -0
- package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -0
- package/dist/src/ui/components/messages/DiffRenderer.test.d.ts +6 -0
- package/dist/src/ui/components/messages/DiffRenderer.test.js +239 -0
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +37 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolMessage.test.js +116 -0
- package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -0
- package/dist/src/ui/components/shared/MaxSizedBox.test.d.ts +6 -0
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +134 -0
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -0
- package/dist/src/ui/contexts/SessionContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/SessionContext.test.js +96 -0
- package/dist/src/ui/contexts/SessionContext.test.js.map +1 -0
- package/dist/src/ui/hooks/useGeminiStream.test.d.ts +6 -0
- package/dist/src/ui/hooks/useGeminiStream.test.js +838 -0
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -0
- package/dist/src/ui/utils/MarkdownDisplay.test.d.ts +6 -0
- package/dist/src/ui/utils/MarkdownDisplay.test.js +211 -0
- package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2025 Google LLC
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { OverflowProvider } from '../../contexts/OverflowContext.js';
|
|
8
|
+
import { render } from 'ink-testing-library';
|
|
9
|
+
import { DiffRenderer } from './DiffRenderer.js';
|
|
10
|
+
import * as CodeColorizer from '../../utils/CodeColorizer.js';
|
|
11
|
+
import { vi } from 'vitest';
|
|
12
|
+
describe('<OverflowProvider><DiffRenderer /></OverflowProvider>', () => {
|
|
13
|
+
const mockColorizeCode = vi.spyOn(CodeColorizer, 'colorizeCode');
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
mockColorizeCode.mockClear();
|
|
16
|
+
});
|
|
17
|
+
const sanitizeOutput = (output, terminalWidth) => output?.replace(/GAP_INDICATOR/g, '═'.repeat(terminalWidth));
|
|
18
|
+
it('should call colorizeCode with correct language for new file with known extension', () => {
|
|
19
|
+
const newFileDiffContent = `
|
|
20
|
+
diff --git a/test.py b/test.py
|
|
21
|
+
new file mode 100644
|
|
22
|
+
index 0000000..e69de29
|
|
23
|
+
--- /dev/null
|
|
24
|
+
+++ b/test.py
|
|
25
|
+
@@ -0,0 +1 @@
|
|
26
|
+
+print("hello world")
|
|
27
|
+
`;
|
|
28
|
+
render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: newFileDiffContent, filename: "test.py", terminalWidth: 80 }) }));
|
|
29
|
+
expect(mockColorizeCode).toHaveBeenCalledWith('print("hello world")', 'python', undefined, 80);
|
|
30
|
+
});
|
|
31
|
+
it('should call colorizeCode with null language for new file with unknown extension', () => {
|
|
32
|
+
const newFileDiffContent = `
|
|
33
|
+
diff --git a/test.unknown b/test.unknown
|
|
34
|
+
new file mode 100644
|
|
35
|
+
index 0000000..e69de29
|
|
36
|
+
--- /dev/null
|
|
37
|
+
+++ b/test.unknown
|
|
38
|
+
@@ -0,0 +1 @@
|
|
39
|
+
+some content
|
|
40
|
+
`;
|
|
41
|
+
render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: newFileDiffContent, filename: "test.unknown", terminalWidth: 80 }) }));
|
|
42
|
+
expect(mockColorizeCode).toHaveBeenCalledWith('some content', null, undefined, 80);
|
|
43
|
+
});
|
|
44
|
+
it('should call colorizeCode with null language for new file if no filename is provided', () => {
|
|
45
|
+
const newFileDiffContent = `
|
|
46
|
+
diff --git a/test.txt b/test.txt
|
|
47
|
+
new file mode 100644
|
|
48
|
+
index 0000000..e69de29
|
|
49
|
+
--- /dev/null
|
|
50
|
+
+++ b/test.txt
|
|
51
|
+
@@ -0,0 +1 @@
|
|
52
|
+
+some text content
|
|
53
|
+
`;
|
|
54
|
+
render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: newFileDiffContent, terminalWidth: 80 }) }));
|
|
55
|
+
expect(mockColorizeCode).toHaveBeenCalledWith('some text content', null, undefined, 80);
|
|
56
|
+
});
|
|
57
|
+
it('should render diff content for existing file (not calling colorizeCode directly for the whole block)', () => {
|
|
58
|
+
const existingFileDiffContent = `
|
|
59
|
+
diff --git a/test.txt b/test.txt
|
|
60
|
+
index 0000001..0000002 100644
|
|
61
|
+
--- a/test.txt
|
|
62
|
+
+++ b/test.txt
|
|
63
|
+
@@ -1 +1 @@
|
|
64
|
+
-old line
|
|
65
|
+
+new line
|
|
66
|
+
`;
|
|
67
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: existingFileDiffContent, filename: "test.txt", terminalWidth: 80 }) }));
|
|
68
|
+
// colorizeCode is used internally by the line-by-line rendering, not for the whole block
|
|
69
|
+
expect(mockColorizeCode).not.toHaveBeenCalledWith(expect.stringContaining('old line'), expect.anything());
|
|
70
|
+
expect(mockColorizeCode).not.toHaveBeenCalledWith(expect.stringContaining('new line'), expect.anything());
|
|
71
|
+
const output = lastFrame();
|
|
72
|
+
const lines = output.split('\n');
|
|
73
|
+
expect(lines[0]).toBe('1 - old line');
|
|
74
|
+
expect(lines[1]).toBe('1 + new line');
|
|
75
|
+
});
|
|
76
|
+
it('should handle diff with only header and no changes', () => {
|
|
77
|
+
const noChangeDiff = `diff --git a/file.txt b/file.txt
|
|
78
|
+
index 1234567..1234567 100644
|
|
79
|
+
--- a/file.txt
|
|
80
|
+
+++ b/file.txt
|
|
81
|
+
`;
|
|
82
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: noChangeDiff, filename: "file.txt", terminalWidth: 80 }) }));
|
|
83
|
+
expect(lastFrame()).toContain('No changes detected');
|
|
84
|
+
expect(mockColorizeCode).not.toHaveBeenCalled();
|
|
85
|
+
});
|
|
86
|
+
it('should handle empty diff content', () => {
|
|
87
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: "", terminalWidth: 80 }) }));
|
|
88
|
+
expect(lastFrame()).toContain('No diff content');
|
|
89
|
+
expect(mockColorizeCode).not.toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('should render a gap indicator for skipped lines', () => {
|
|
92
|
+
const diffWithGap = `
|
|
93
|
+
diff --git a/file.txt b/file.txt
|
|
94
|
+
index 123..456 100644
|
|
95
|
+
--- a/file.txt
|
|
96
|
+
+++ b/file.txt
|
|
97
|
+
@@ -1,2 +1,2 @@
|
|
98
|
+
context line 1
|
|
99
|
+
-deleted line
|
|
100
|
+
+added line
|
|
101
|
+
@@ -10,2 +10,2 @@
|
|
102
|
+
context line 10
|
|
103
|
+
context line 11
|
|
104
|
+
`;
|
|
105
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: diffWithGap, filename: "file.txt", terminalWidth: 80 }) }));
|
|
106
|
+
const output = lastFrame();
|
|
107
|
+
expect(output).toContain('═'); // Check for the border character used in the gap
|
|
108
|
+
// Verify that lines before and after the gap are rendered
|
|
109
|
+
expect(output).toContain('context line 1');
|
|
110
|
+
expect(output).toContain('added line');
|
|
111
|
+
expect(output).toContain('context line 10');
|
|
112
|
+
});
|
|
113
|
+
it('should not render a gap indicator for small gaps (<= MAX_CONTEXT_LINES_WITHOUT_GAP)', () => {
|
|
114
|
+
const diffWithSmallGap = `
|
|
115
|
+
diff --git a/file.txt b/file.txt
|
|
116
|
+
index abc..def 100644
|
|
117
|
+
--- a/file.txt
|
|
118
|
+
+++ b/file.txt
|
|
119
|
+
@@ -1,5 +1,5 @@
|
|
120
|
+
context line 1
|
|
121
|
+
context line 2
|
|
122
|
+
context line 3
|
|
123
|
+
context line 4
|
|
124
|
+
context line 5
|
|
125
|
+
@@ -11,5 +11,5 @@
|
|
126
|
+
context line 11
|
|
127
|
+
context line 12
|
|
128
|
+
context line 13
|
|
129
|
+
context line 14
|
|
130
|
+
context line 15
|
|
131
|
+
`;
|
|
132
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: diffWithSmallGap, filename: "file.txt", terminalWidth: 80 }) }));
|
|
133
|
+
const output = lastFrame();
|
|
134
|
+
expect(output).not.toContain('═'); // Ensure no separator is rendered
|
|
135
|
+
// Verify that lines before and after the gap are rendered
|
|
136
|
+
expect(output).toContain('context line 5');
|
|
137
|
+
expect(output).toContain('context line 11');
|
|
138
|
+
});
|
|
139
|
+
describe('should correctly render a diff with multiple hunks and a gap indicator', () => {
|
|
140
|
+
const diffWithMultipleHunks = `
|
|
141
|
+
diff --git a/multi.js b/multi.js
|
|
142
|
+
index 123..789 100644
|
|
143
|
+
--- a/multi.js
|
|
144
|
+
+++ b/multi.js
|
|
145
|
+
@@ -1,3 +1,3 @@
|
|
146
|
+
console.log('first hunk');
|
|
147
|
+
-const oldVar = 1;
|
|
148
|
+
+const newVar = 1;
|
|
149
|
+
console.log('end of first hunk');
|
|
150
|
+
@@ -20,3 +20,3 @@
|
|
151
|
+
console.log('second hunk');
|
|
152
|
+
-const anotherOld = 'test';
|
|
153
|
+
+const anotherNew = 'test';
|
|
154
|
+
console.log('end of second hunk');
|
|
155
|
+
`;
|
|
156
|
+
it.each([
|
|
157
|
+
{
|
|
158
|
+
terminalWidth: 80,
|
|
159
|
+
height: undefined,
|
|
160
|
+
expected: `1 console.log('first hunk');
|
|
161
|
+
2 - const oldVar = 1;
|
|
162
|
+
2 + const newVar = 1;
|
|
163
|
+
3 console.log('end of first hunk');
|
|
164
|
+
════════════════════════════════════════════════════════════════════════════════
|
|
165
|
+
20 console.log('second hunk');
|
|
166
|
+
21 - const anotherOld = 'test';
|
|
167
|
+
21 + const anotherNew = 'test';
|
|
168
|
+
22 console.log('end of second hunk');`,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
terminalWidth: 80,
|
|
172
|
+
height: 6,
|
|
173
|
+
expected: `... first 4 lines hidden ...
|
|
174
|
+
════════════════════════════════════════════════════════════════════════════════
|
|
175
|
+
20 console.log('second hunk');
|
|
176
|
+
21 - const anotherOld = 'test';
|
|
177
|
+
21 + const anotherNew = 'test';
|
|
178
|
+
22 console.log('end of second hunk');`,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
terminalWidth: 30,
|
|
182
|
+
height: 6,
|
|
183
|
+
expected: `... first 10 lines hidden ...
|
|
184
|
+
'test';
|
|
185
|
+
21 + const anotherNew =
|
|
186
|
+
'test';
|
|
187
|
+
22 console.log('end of
|
|
188
|
+
second hunk');`,
|
|
189
|
+
},
|
|
190
|
+
])('with terminalWidth $terminalWidth and height $height', ({ terminalWidth, height, expected }) => {
|
|
191
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: diffWithMultipleHunks, filename: "multi.js", terminalWidth: terminalWidth, availableTerminalHeight: height }) }));
|
|
192
|
+
const output = lastFrame();
|
|
193
|
+
expect(sanitizeOutput(output, terminalWidth)).toEqual(expected);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
it('should correctly render a diff with a SVN diff format', () => {
|
|
197
|
+
const newFileDiff = `
|
|
198
|
+
fileDiff Index: file.txt
|
|
199
|
+
===================================================================
|
|
200
|
+
--- a/file.txt Current
|
|
201
|
+
+++ b/file.txt Proposed
|
|
202
|
+
--- a/multi.js
|
|
203
|
+
+++ b/multi.js
|
|
204
|
+
@@ -1,1 +1,1 @@
|
|
205
|
+
-const oldVar = 1;
|
|
206
|
+
+const newVar = 1;
|
|
207
|
+
@@ -20,1 +20,1 @@
|
|
208
|
+
-const anotherOld = 'test';
|
|
209
|
+
+const anotherNew = 'test';
|
|
210
|
+
\
|
|
211
|
+
`;
|
|
212
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: newFileDiff, filename: "TEST", terminalWidth: 80 }) }));
|
|
213
|
+
const output = lastFrame();
|
|
214
|
+
expect(output).toEqual(`1 - const oldVar = 1;
|
|
215
|
+
1 + const newVar = 1;
|
|
216
|
+
════════════════════════════════════════════════════════════════════════════════
|
|
217
|
+
20 - const anotherOld = 'test';
|
|
218
|
+
20 + const anotherNew = 'test';`);
|
|
219
|
+
});
|
|
220
|
+
it('should correctly render a new file with no file extension correctly', () => {
|
|
221
|
+
const newFileDiff = `
|
|
222
|
+
fileDiff Index: Dockerfile
|
|
223
|
+
===================================================================
|
|
224
|
+
--- Dockerfile Current
|
|
225
|
+
+++ Dockerfile Proposed
|
|
226
|
+
@@ -0,0 +1,3 @@
|
|
227
|
+
+FROM node:14
|
|
228
|
+
+RUN npm install
|
|
229
|
+
+RUN npm run build
|
|
230
|
+
\
|
|
231
|
+
`;
|
|
232
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(DiffRenderer, { diffContent: newFileDiff, filename: "Dockerfile", terminalWidth: 80 }) }));
|
|
233
|
+
const output = lastFrame();
|
|
234
|
+
expect(output).toEqual(`1 FROM node:14
|
|
235
|
+
2 RUN npm install
|
|
236
|
+
3 RUN npm run build`);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
//# sourceMappingURL=DiffRenderer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiffRenderer.test.js","sourceRoot":"","sources":["../../../../../src/ui/components/messages/DiffRenderer.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2025 Google LLC
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { render } from 'ink-testing-library';
|
|
8
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
9
|
+
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
|
|
10
|
+
describe('ToolConfirmationMessage', () => {
|
|
11
|
+
it('should not display urls if prompt and url are the same', () => {
|
|
12
|
+
const confirmationDetails = {
|
|
13
|
+
type: 'info',
|
|
14
|
+
title: 'Confirm Web Fetch',
|
|
15
|
+
prompt: 'https://example.com',
|
|
16
|
+
urls: ['https://example.com'],
|
|
17
|
+
onConfirm: vi.fn(),
|
|
18
|
+
};
|
|
19
|
+
const { lastFrame } = render(_jsx(ToolConfirmationMessage, { confirmationDetails: confirmationDetails, availableTerminalHeight: 30, terminalWidth: 80 }));
|
|
20
|
+
expect(lastFrame()).not.toContain('URLs to fetch:');
|
|
21
|
+
});
|
|
22
|
+
it('should display urls if prompt and url are different', () => {
|
|
23
|
+
const confirmationDetails = {
|
|
24
|
+
type: 'info',
|
|
25
|
+
title: 'Confirm Web Fetch',
|
|
26
|
+
prompt: 'fetch https://github.com/google/gemini-react/blob/main/README.md',
|
|
27
|
+
urls: [
|
|
28
|
+
'https://raw.githubusercontent.com/google/gemini-react/main/README.md',
|
|
29
|
+
],
|
|
30
|
+
onConfirm: vi.fn(),
|
|
31
|
+
};
|
|
32
|
+
const { lastFrame } = render(_jsx(ToolConfirmationMessage, { confirmationDetails: confirmationDetails, availableTerminalHeight: 30, terminalWidth: 80 }));
|
|
33
|
+
expect(lastFrame()).toContain('URLs to fetch:');
|
|
34
|
+
expect(lastFrame()).toContain('- https://raw.githubusercontent.com/google/gemini-react/main/README.md');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=ToolConfirmationMessage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolConfirmationMessage.test.js","sourceRoot":"","sources":["../../../../../src/ui/components/messages/ToolConfirmationMessage.test.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,mBAAmB,GAAgC;YACvD,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EAAE,qBAAqB;YAC7B,IAAI,EAAE,CAAC,qBAAqB,CAAC;YAC7B,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;SACnB,CAAC;QAEF,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAC1B,KAAC,uBAAuB,IACtB,mBAAmB,EAAE,mBAAmB,EACxC,uBAAuB,EAAE,EAAE,EAC3B,aAAa,EAAE,EAAE,GACjB,CACH,CAAC;QAEF,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,mBAAmB,GAAgC;YACvD,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EACJ,kEAAkE;YACpE,IAAI,EAAE;gBACJ,sEAAsE;aACvE;YACD,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;SACnB,CAAC;QAEF,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAC1B,KAAC,uBAAuB,IACtB,mBAAmB,EAAE,mBAAmB,EACxC,uBAAuB,EAAE,EAAE,EAC3B,aAAa,EAAE,EAAE,GACjB,CACH,CAAC;QAEF,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QAChD,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAC3B,wEAAwE,CACzE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2025 Google LLC
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { render } from 'ink-testing-library';
|
|
9
|
+
import { ToolMessage } from './ToolMessage.js';
|
|
10
|
+
import { StreamingState, ToolCallStatus } from '../../types.js';
|
|
11
|
+
import { Text } from 'ink';
|
|
12
|
+
import { StreamingContext } from '../../contexts/StreamingContext.js';
|
|
13
|
+
// Mock child components or utilities if they are complex or have side effects
|
|
14
|
+
vi.mock('../GeminiRespondingSpinner.js', () => ({
|
|
15
|
+
GeminiRespondingSpinner: ({ nonRespondingDisplay, }) => {
|
|
16
|
+
const streamingState = React.useContext(StreamingContext);
|
|
17
|
+
if (streamingState === StreamingState.Responding) {
|
|
18
|
+
return _jsx(Text, { children: "MockRespondingSpinner" });
|
|
19
|
+
}
|
|
20
|
+
return nonRespondingDisplay ? _jsx(Text, { children: nonRespondingDisplay }) : null;
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
vi.mock('./DiffRenderer.js', () => ({
|
|
24
|
+
DiffRenderer: function MockDiffRenderer({ diffContent, }) {
|
|
25
|
+
return _jsxs(Text, { children: ["MockDiff:", diffContent] });
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
28
|
+
vi.mock('../../utils/MarkdownDisplay.js', () => ({
|
|
29
|
+
MarkdownDisplay: function MockMarkdownDisplay({ text }) {
|
|
30
|
+
return _jsxs(Text, { children: ["MockMarkdown:", text] });
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
// Helper to render with context
|
|
34
|
+
const renderWithContext = (ui, streamingState) => {
|
|
35
|
+
const contextValue = streamingState;
|
|
36
|
+
return render(_jsx(StreamingContext.Provider, { value: contextValue, children: ui }));
|
|
37
|
+
};
|
|
38
|
+
describe('<ToolMessage />', () => {
|
|
39
|
+
const baseProps = {
|
|
40
|
+
callId: 'tool-123',
|
|
41
|
+
name: 'test-tool',
|
|
42
|
+
description: 'A tool for testing',
|
|
43
|
+
resultDisplay: 'Test result',
|
|
44
|
+
status: ToolCallStatus.Success,
|
|
45
|
+
terminalWidth: 80,
|
|
46
|
+
confirmationDetails: undefined,
|
|
47
|
+
emphasis: 'medium',
|
|
48
|
+
};
|
|
49
|
+
it('renders basic tool information', () => {
|
|
50
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps }), StreamingState.Idle);
|
|
51
|
+
const output = lastFrame();
|
|
52
|
+
expect(output).toContain('✔'); // Success indicator
|
|
53
|
+
expect(output).toContain('test-tool');
|
|
54
|
+
expect(output).toContain('A tool for testing');
|
|
55
|
+
expect(output).toContain('MockMarkdown:Test result');
|
|
56
|
+
});
|
|
57
|
+
describe('ToolStatusIndicator rendering', () => {
|
|
58
|
+
it('shows ✔ for Success status', () => {
|
|
59
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Success }), StreamingState.Idle);
|
|
60
|
+
expect(lastFrame()).toContain('✔');
|
|
61
|
+
});
|
|
62
|
+
it('shows o for Pending status', () => {
|
|
63
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Pending }), StreamingState.Idle);
|
|
64
|
+
expect(lastFrame()).toContain('o');
|
|
65
|
+
});
|
|
66
|
+
it('shows ? for Confirming status', () => {
|
|
67
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Confirming }), StreamingState.Idle);
|
|
68
|
+
expect(lastFrame()).toContain('?');
|
|
69
|
+
});
|
|
70
|
+
it('shows - for Canceled status', () => {
|
|
71
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Canceled }), StreamingState.Idle);
|
|
72
|
+
expect(lastFrame()).toContain('-');
|
|
73
|
+
});
|
|
74
|
+
it('shows x for Error status', () => {
|
|
75
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Error }), StreamingState.Idle);
|
|
76
|
+
expect(lastFrame()).toContain('x');
|
|
77
|
+
});
|
|
78
|
+
it('shows paused spinner for Executing status when streamingState is Idle', () => {
|
|
79
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Executing }), StreamingState.Idle);
|
|
80
|
+
expect(lastFrame()).toContain('⊷');
|
|
81
|
+
expect(lastFrame()).not.toContain('MockRespondingSpinner');
|
|
82
|
+
expect(lastFrame()).not.toContain('✔');
|
|
83
|
+
});
|
|
84
|
+
it('shows paused spinner for Executing status when streamingState is WaitingForConfirmation', () => {
|
|
85
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Executing }), StreamingState.WaitingForConfirmation);
|
|
86
|
+
expect(lastFrame()).toContain('⊷');
|
|
87
|
+
expect(lastFrame()).not.toContain('MockRespondingSpinner');
|
|
88
|
+
expect(lastFrame()).not.toContain('✔');
|
|
89
|
+
});
|
|
90
|
+
it('shows MockRespondingSpinner for Executing status when streamingState is Responding', () => {
|
|
91
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, status: ToolCallStatus.Executing }), StreamingState.Responding);
|
|
92
|
+
expect(lastFrame()).toContain('MockRespondingSpinner');
|
|
93
|
+
expect(lastFrame()).not.toContain('✔');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
it('renders DiffRenderer for diff results', () => {
|
|
97
|
+
const diffResult = {
|
|
98
|
+
fileDiff: '--- a/file.txt\n+++ b/file.txt\n@@ -1 +1 @@\n-old\n+new',
|
|
99
|
+
fileName: 'file.txt',
|
|
100
|
+
};
|
|
101
|
+
const { lastFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, resultDisplay: diffResult }), StreamingState.Idle);
|
|
102
|
+
// Check that the output contains the MockDiff content as part of the whole message
|
|
103
|
+
expect(lastFrame()).toMatch(/MockDiff:--- a\/file\.txt/);
|
|
104
|
+
});
|
|
105
|
+
it('renders emphasis correctly', () => {
|
|
106
|
+
const { lastFrame: highEmphasisFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, emphasis: "high" }), StreamingState.Idle);
|
|
107
|
+
// Check for trailing indicator or specific color if applicable (Colors are not easily testable here)
|
|
108
|
+
expect(highEmphasisFrame()).toContain('←'); // Trailing indicator for high emphasis
|
|
109
|
+
const { lastFrame: lowEmphasisFrame } = renderWithContext(_jsx(ToolMessage, { ...baseProps, emphasis: "low" }), StreamingState.Idle);
|
|
110
|
+
// For low emphasis, the name and description might be dimmed (check for dimColor if possible)
|
|
111
|
+
// This is harder to assert directly in text output without color checks.
|
|
112
|
+
// We can at least ensure it doesn't have the high emphasis indicator.
|
|
113
|
+
expect(lowEmphasisFrame()).not.toContain('←');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=ToolMessage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolMessage.test.js","sourceRoot":"","sources":["../../../../../src/ui/components/messages/ToolMessage.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2025 Google LLC
|
|
5
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
*/
|
|
7
|
+
import { render } from 'ink-testing-library';
|
|
8
|
+
import { OverflowProvider } from '../../contexts/OverflowContext.js';
|
|
9
|
+
import { MaxSizedBox, setMaxSizedBoxDebugging } from './MaxSizedBox.js';
|
|
10
|
+
import { Box, Text } from 'ink';
|
|
11
|
+
import { describe, it, expect } from 'vitest';
|
|
12
|
+
describe('<MaxSizedBox />', () => {
|
|
13
|
+
// Make sure MaxSizedBox logs errors on invalid configurations.
|
|
14
|
+
// This is useful for debugging issues with the component.
|
|
15
|
+
// It should be set to false in production for performance and to avoid
|
|
16
|
+
// cluttering the console if there are ignorable issues.
|
|
17
|
+
setMaxSizedBoxDebugging(true);
|
|
18
|
+
it('renders children without truncation when they fit', () => {
|
|
19
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, children: _jsx(Box, { children: _jsx(Text, { children: "Hello, World!" }) }) }) }));
|
|
20
|
+
expect(lastFrame()).equals('Hello, World!');
|
|
21
|
+
});
|
|
22
|
+
it('hides lines when content exceeds maxHeight', () => {
|
|
23
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 2, children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 3" }) })] }) }));
|
|
24
|
+
expect(lastFrame()).equals(`... first 2 lines hidden ...
|
|
25
|
+
Line 3`);
|
|
26
|
+
});
|
|
27
|
+
it('hides lines at the end when content exceeds maxHeight and overflowDirection is bottom', () => {
|
|
28
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 2, overflowDirection: "bottom", children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 3" }) })] }) }));
|
|
29
|
+
expect(lastFrame()).equals(`Line 1
|
|
30
|
+
... last 2 lines hidden ...`);
|
|
31
|
+
});
|
|
32
|
+
it('wraps text that exceeds maxWidth', () => {
|
|
33
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 10, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "This is a long line of text" }) }) }) }));
|
|
34
|
+
expect(lastFrame()).equals(`This is a
|
|
35
|
+
long line
|
|
36
|
+
of text`);
|
|
37
|
+
});
|
|
38
|
+
it('handles mixed wrapping and non-wrapping segments', () => {
|
|
39
|
+
const multilineText = `This part will wrap around.
|
|
40
|
+
And has a line break.
|
|
41
|
+
Leading spaces preserved.`;
|
|
42
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 20, maxHeight: 20, children: [_jsx(Box, { children: _jsx(Text, { children: "Example" }) }), _jsxs(Box, { children: [_jsx(Text, { children: "No Wrap: " }), _jsx(Text, { wrap: "wrap", children: multilineText })] }), _jsxs(Box, { children: [_jsx(Text, { children: "Longer No Wrap: " }), _jsx(Text, { wrap: "wrap", children: "This part will wrap around." })] })] }) }));
|
|
43
|
+
expect(lastFrame()).equals(`Example
|
|
44
|
+
No Wrap: This part
|
|
45
|
+
will wrap
|
|
46
|
+
around.
|
|
47
|
+
And has a
|
|
48
|
+
line break.
|
|
49
|
+
Leading
|
|
50
|
+
spaces
|
|
51
|
+
preserved.
|
|
52
|
+
Longer No Wrap: This
|
|
53
|
+
part
|
|
54
|
+
will
|
|
55
|
+
wrap
|
|
56
|
+
arou
|
|
57
|
+
nd.`);
|
|
58
|
+
});
|
|
59
|
+
it('handles words longer than maxWidth by splitting them', () => {
|
|
60
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 5, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "Supercalifragilisticexpialidocious" }) }) }) }));
|
|
61
|
+
expect(lastFrame()).equals(`... …
|
|
62
|
+
istic
|
|
63
|
+
expia
|
|
64
|
+
lidoc
|
|
65
|
+
ious`);
|
|
66
|
+
});
|
|
67
|
+
it('does not truncate when maxHeight is undefined', () => {
|
|
68
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: undefined, children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) })] }) }));
|
|
69
|
+
expect(lastFrame()).equals(`Line 1
|
|
70
|
+
Line 2`);
|
|
71
|
+
});
|
|
72
|
+
it('shows plural "lines" when more than one line is hidden', () => {
|
|
73
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 2, children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 3" }) })] }) }));
|
|
74
|
+
expect(lastFrame()).equals(`... first 2 lines hidden ...
|
|
75
|
+
Line 3`);
|
|
76
|
+
});
|
|
77
|
+
it('shows plural "lines" when more than one line is hidden and overflowDirection is bottom', () => {
|
|
78
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 2, overflowDirection: "bottom", children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 3" }) })] }) }));
|
|
79
|
+
expect(lastFrame()).equals(`Line 1
|
|
80
|
+
... last 2 lines hidden ...`);
|
|
81
|
+
});
|
|
82
|
+
it('renders an empty box for empty children', () => {
|
|
83
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10 }) }));
|
|
84
|
+
// Expect an empty string or a box with nothing in it.
|
|
85
|
+
// Ink renders an empty box as an empty string.
|
|
86
|
+
expect(lastFrame()).equals('');
|
|
87
|
+
});
|
|
88
|
+
it('wraps text with multi-byte unicode characters correctly', () => {
|
|
89
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 5, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "\u4F60\u597D\u4E16\u754C" }) }) }) }));
|
|
90
|
+
// "你好" has a visual width of 4. "世界" has a visual width of 4.
|
|
91
|
+
// With maxWidth=5, it should wrap after the second character.
|
|
92
|
+
expect(lastFrame()).equals(`你好
|
|
93
|
+
世界`);
|
|
94
|
+
});
|
|
95
|
+
it('wraps text with multi-byte emoji characters correctly', () => {
|
|
96
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 5, maxHeight: 5, children: _jsx(Box, { children: _jsx(Text, { wrap: "wrap", children: "\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36\uD83D\uDC36" }) }) }) }));
|
|
97
|
+
// Each "🐶" has a visual width of 2.
|
|
98
|
+
// With maxWidth=5, it should wrap every 2 emojis.
|
|
99
|
+
expect(lastFrame()).equals(`🐶🐶
|
|
100
|
+
🐶🐶
|
|
101
|
+
🐶`);
|
|
102
|
+
});
|
|
103
|
+
it('accounts for additionalHiddenLinesCount', () => {
|
|
104
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 2, additionalHiddenLinesCount: 5, children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 3" }) })] }) }));
|
|
105
|
+
// 1 line is hidden by overflow, 5 are additionally hidden.
|
|
106
|
+
expect(lastFrame()).equals(`... first 7 lines hidden ...
|
|
107
|
+
Line 3`);
|
|
108
|
+
});
|
|
109
|
+
it('handles React.Fragment as a child', () => {
|
|
110
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsxs(MaxSizedBox, { maxWidth: 80, maxHeight: 10, children: [_jsxs(_Fragment, { children: [_jsx(Box, { children: _jsx(Text, { children: "Line 1 from Fragment" }) }), _jsx(Box, { children: _jsx(Text, { children: "Line 2 from Fragment" }) })] }), _jsx(Box, { children: _jsx(Text, { children: "Line 3 direct child" }) })] }) }));
|
|
111
|
+
expect(lastFrame()).equals(`Line 1 from Fragment
|
|
112
|
+
Line 2 from Fragment
|
|
113
|
+
Line 3 direct child`);
|
|
114
|
+
});
|
|
115
|
+
it('clips a long single text child from the top', () => {
|
|
116
|
+
const THIRTY_LINES = Array.from({ length: 30 }, (_, i) => `Line ${i + 1}`).join('\n');
|
|
117
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, children: _jsx(Box, { children: _jsx(Text, { children: THIRTY_LINES }) }) }) }));
|
|
118
|
+
const expected = [
|
|
119
|
+
'... first 21 lines hidden ...',
|
|
120
|
+
...Array.from({ length: 9 }, (_, i) => `Line ${22 + i}`),
|
|
121
|
+
].join('\n');
|
|
122
|
+
expect(lastFrame()).equals(expected);
|
|
123
|
+
});
|
|
124
|
+
it('clips a long single text child from the bottom', () => {
|
|
125
|
+
const THIRTY_LINES = Array.from({ length: 30 }, (_, i) => `Line ${i + 1}`).join('\n');
|
|
126
|
+
const { lastFrame } = render(_jsx(OverflowProvider, { children: _jsx(MaxSizedBox, { maxWidth: 80, maxHeight: 10, overflowDirection: "bottom", children: _jsx(Box, { children: _jsx(Text, { children: THIRTY_LINES }) }) }) }));
|
|
127
|
+
const expected = [
|
|
128
|
+
...Array.from({ length: 9 }, (_, i) => `Line ${i + 1}`),
|
|
129
|
+
'... last 21 lines hidden ...',
|
|
130
|
+
].join('\n');
|
|
131
|
+
expect(lastFrame()).equals(expected);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
//# sourceMappingURL=MaxSizedBox.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaxSizedBox.test.js","sourceRoot":"","sources":["../../../../../src/ui/components/shared/MaxSizedBox.test.tsx"],"names":[],"mappings":"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"}
|