Download packages/cli/src/ui/components/messages/DiffRenderer.test.tsx from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 12.9 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx
-
curl -L -o DiffRenderer.test.tsx https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/components/messages/DiffRenderer.test.tsx
12.9 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { OverflowProvider } from '../../contexts/OverflowContext.js'; | |
| import { renderWithProviders } from '../../../test-utils/render.js'; | |
| import { createMockSettings } from '../../../test-utils/settings.js'; | |
| import { waitFor } from '../../../test-utils/async.js'; | |
| import { DiffRenderer } from './DiffRenderer.js'; | |
| import * as CodeColorizer from '../../utils/CodeColorizer.js'; | |
| import { vi } from 'vitest'; | |
| describe('<OverflowProvider><DiffRenderer /></OverflowProvider>', () => { | |
| const mockColorizeCode = vi.spyOn(CodeColorizer, 'colorizeCode'); | |
| beforeEach(() => { | |
| mockColorizeCode.mockClear(); | |
| }); | |
| const sanitizeOutput = (output: string | undefined, terminalWidth: number) => | |
| output?.replace(/GAP_INDICATOR/g, '═'.repeat(terminalWidth)); | |
| describe.each([true, false])( | |
| 'with useAlternateBuffer = %s', | |
| (useAlternateBuffer) => { | |
| it('should call colorizeCode with correct language for new file with known extension', async () => { | |
| const newFileDiffContent = ` | |
| diff --git a/test.py b/test.py | |
| new file mode 100644 | |
| index 0000000..e69de29 | |
| --- /dev/null | |
| +++ b/test.py | |
| @@ -0,0 +1 @@ | |
| +print("hello world") | |
| `; | |
| await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={newFileDiffContent} | |
| filename="test.py" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => | |
| expect(mockColorizeCode).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| code: 'print("hello world")', | |
| language: 'python', | |
| availableHeight: undefined, | |
| maxWidth: 80, | |
| theme: undefined, | |
| settings: expect.anything(), | |
| disableColor: false, | |
| paddingX: 0, | |
| }), | |
| ), | |
| ); | |
| }); | |
| it('should call colorizeCode with null language for new file with unknown extension', async () => { | |
| const newFileDiffContent = ` | |
| diff --git a/test.unknown b/test.unknown | |
| new file mode 100644 | |
| index 0000000..e69de29 | |
| --- /dev/null | |
| +++ b/test.unknown | |
| @@ -0,0 +1 @@ | |
| +some content | |
| `; | |
| await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={newFileDiffContent} | |
| filename="test.unknown" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => | |
| expect(mockColorizeCode).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| code: 'some content', | |
| language: null, | |
| availableHeight: undefined, | |
| maxWidth: 80, | |
| theme: undefined, | |
| settings: expect.anything(), | |
| disableColor: false, | |
| paddingX: 0, | |
| }), | |
| ), | |
| ); | |
| }); | |
| it('should call colorizeCode with null language for new file if no filename is provided', async () => { | |
| const newFileDiffContent = ` | |
| diff --git a/test.txt b/test.txt | |
| new file mode 100644 | |
| index 0000000..e69de29 | |
| --- /dev/null | |
| +++ b/test.txt | |
| @@ -0,0 +1 @@ | |
| +some text content | |
| `; | |
| await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer diffContent={newFileDiffContent} terminalWidth={80} /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => | |
| expect(mockColorizeCode).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| code: 'some text content', | |
| language: null, | |
| availableHeight: undefined, | |
| maxWidth: 80, | |
| theme: undefined, | |
| settings: expect.anything(), | |
| disableColor: false, | |
| paddingX: 0, | |
| }), | |
| ), | |
| ); | |
| }); | |
| it('should render diff content for existing file (not calling colorizeCode directly for the whole block)', async () => { | |
| const existingFileDiffContent = ` | |
| diff --git a/test.txt b/test.txt | |
| index 0000001..0000002 100644 | |
| --- a/test.txt | |
| +++ b/test.txt | |
| @@ -1 +1 @@ | |
| -old line | |
| +new line | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={existingFileDiffContent} | |
| filename="test.txt" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| // colorizeCode is used internally by the line-by-line rendering, not for the whole block | |
| await waitFor(() => expect(lastFrame()).toContain('new line')); | |
| expect(mockColorizeCode).not.toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| code: expect.stringContaining('old line'), | |
| }), | |
| ); | |
| expect(mockColorizeCode).not.toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| code: expect.stringContaining('new line'), | |
| }), | |
| ); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| }); | |
| it('should handle diff with only header and no changes', async () => { | |
| const noChangeDiff = `diff --git a/file.txt b/file.txt | |
| index 1234567..1234567 100644 | |
| --- a/file.txt | |
| +++ b/file.txt | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={noChangeDiff} | |
| filename="file.txt" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toBeDefined()); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| expect(mockColorizeCode).not.toHaveBeenCalled(); | |
| }); | |
| it('should handle empty diff content', async () => { | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer diffContent="" terminalWidth={80} /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toBeDefined()); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| expect(mockColorizeCode).not.toHaveBeenCalled(); | |
| }); | |
| it('should render a gap indicator for skipped lines', async () => { | |
| const diffWithGap = ` | |
| diff --git a/file.txt b/file.txt | |
| index 123..456 100644 | |
| --- a/file.txt | |
| +++ b/file.txt | |
| @@ -1,2 +1,2 @@ | |
| context line 1 | |
| -deleted line | |
| +added line | |
| @@ -10,2 +10,2 @@ | |
| context line 10 | |
| context line 11 | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={diffWithGap} | |
| filename="file.txt" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toContain('added line')); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| }); | |
| it('should not render a gap indicator for small gaps (<= MAX_CONTEXT_LINES_WITHOUT_GAP)', async () => { | |
| const diffWithSmallGap = ` | |
| diff --git a/file.txt b/file.txt | |
| index abc..def 100644 | |
| --- a/file.txt | |
| +++ b/file.txt | |
| @@ -1,5 +1,5 @@ | |
| context line 1 | |
| context line 2 | |
| context line 3 | |
| context line 4 | |
| context line 5 | |
| @@ -11,5 +11,5 @@ | |
| context line 11 | |
| context line 12 | |
| context line 13 | |
| context line 14 | |
| context line 15 | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={diffWithSmallGap} | |
| filename="file.txt" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toContain('context line 15')); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| }); | |
| describe('should correctly render a diff with multiple hunks and a gap indicator', () => { | |
| const diffWithMultipleHunks = ` | |
| diff --git a/multi.js b/multi.js | |
| index 123..789 100644 | |
| --- a/multi.js | |
| +++ b/multi.js | |
| @@ -1,3 +1,3 @@ | |
| console.log('first hunk'); | |
| -const oldVar = 1; | |
| +const newVar = 1; | |
| console.log('end of first hunk'); | |
| @@ -20,3 +20,3 @@ | |
| console.log('second hunk'); | |
| -const anotherOld = 'test'; | |
| +const anotherNew = 'test'; | |
| console.log('end of second hunk'); | |
| `; | |
| it.each([ | |
| { | |
| terminalWidth: 80, | |
| height: undefined, | |
| }, | |
| { | |
| terminalWidth: 80, | |
| height: 6, | |
| }, | |
| { | |
| terminalWidth: 30, | |
| height: 6, | |
| }, | |
| ])( | |
| 'with terminalWidth $terminalWidth and height $height', | |
| async ({ terminalWidth, height }) => { | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={diffWithMultipleHunks} | |
| filename="multi.js" | |
| terminalWidth={terminalWidth} | |
| availableTerminalHeight={height} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toContain('anotherNew')); | |
| const output = lastFrame(); | |
| expect(sanitizeOutput(output, terminalWidth)).toMatchSnapshot(); | |
| }, | |
| ); | |
| }); | |
| it('should correctly render a diff with a SVN diff format', async () => { | |
| const newFileDiff = ` | |
| fileDiff Index: file.txt | |
| =================================================================== | |
| --- a/file.txt Current | |
| +++ b/file.txt Proposed | |
| --- a/multi.js | |
| +++ b/multi.js | |
| @@ -1,1 +1,1 @@ | |
| -const oldVar = 1; | |
| +const newVar = 1; | |
| @@ -20,1 +20,1 @@ | |
| -const anotherOld = 'test'; | |
| +const anotherNew = 'test'; | |
| \\ No newline at end of file | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={newFileDiff} | |
| filename="TEST" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toContain('newVar')); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| }); | |
| it('should correctly render a new file with no file extension correctly', async () => { | |
| const newFileDiff = ` | |
| fileDiff Index: Dockerfile | |
| =================================================================== | |
| --- Dockerfile Current | |
| +++ Dockerfile Proposed | |
| @@ -0,0 +1,3 @@ | |
| +FROM node:14 | |
| +RUN npm install | |
| +RUN npm run build | |
| \\ No newline at end of file | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={newFileDiff} | |
| filename="Dockerfile" | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| { | |
| settings: createMockSettings({ ui: { useAlternateBuffer } }), | |
| }, | |
| ); | |
| await waitFor(() => expect(lastFrame()).toContain('RUN npm run build')); | |
| expect(lastFrame()).toMatchSnapshot(); | |
| }); | |
| it('should disable truncation and render all diff lines without hidden lines indicator when disableTruncation is true', async () => { | |
| const longDiff = ` | |
| diff --git a/test.txt b/test.txt | |
| --- a/test.txt | |
| +++ b/test.txt | |
| @@ -1,10 +1,10 @@ | |
| -old line 1 | |
| -old line 2 | |
| -old line 3 | |
| -old line 4 | |
| -old line 5 | |
| +new line 1 | |
| +new line 2 | |
| +new line 3 | |
| +new line 4 | |
| +new line 5 | |
| `; | |
| const { lastFrame } = await renderWithProviders( | |
| <OverflowProvider> | |
| <DiffRenderer | |
| diffContent={longDiff} | |
| filename="test.txt" | |
| availableTerminalHeight={3} | |
| disableTruncation={true} | |
| terminalWidth={80} | |
| /> | |
| </OverflowProvider>, | |
| ); | |
| await waitFor(() => { | |
| expect(lastFrame()).toContain('new line 1'); | |
| expect(lastFrame()).toContain('new line 5'); | |
| expect(lastFrame()).not.toContain('hidden'); | |
| }); | |
| }); | |
| }, | |
| ); | |
| }); | |