diff options
Diffstat (limited to 'packages/cli/src/ui/components')
4 files changed, 118 insertions, 21 deletions
diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx index 38c6972a..5f08eae4 100644 --- a/packages/cli/src/ui/components/AuthDialog.test.tsx +++ b/packages/cli/src/ui/components/AuthDialog.test.tsx @@ -45,6 +45,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -82,6 +83,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -115,6 +117,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -148,6 +151,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -182,6 +186,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -211,6 +216,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -242,6 +248,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame } = renderWithProviders( @@ -277,6 +284,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame, stdin, unmount } = renderWithProviders( @@ -316,6 +324,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { lastFrame, stdin, unmount } = renderWithProviders( @@ -358,6 +367,7 @@ describe('AuthDialog', () => { path: '', }, [], + true, ); const { stdin, unmount } = renderWithProviders( diff --git a/packages/cli/src/ui/components/FolderTrustDialog.test.tsx b/packages/cli/src/ui/components/FolderTrustDialog.test.tsx index e2b695e2..92aa0d58 100644 --- a/packages/cli/src/ui/components/FolderTrustDialog.test.tsx +++ b/packages/cli/src/ui/components/FolderTrustDialog.test.tsx @@ -8,8 +8,21 @@ import { renderWithProviders } from '../../test-utils/render.js'; import { waitFor } from '@testing-library/react'; import { vi } from 'vitest'; import { FolderTrustDialog, FolderTrustChoice } from './FolderTrustDialog.js'; +import * as process from 'process'; + +vi.mock('process', async () => { + const actual = await vi.importActual('process'); + return { + ...actual, + exit: vi.fn(), + }; +}); describe('FolderTrustDialog', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + it('should render the dialog with title and description', () => { const { lastFrame } = renderWithProviders( <FolderTrustDialog onSelect={vi.fn()} />, @@ -21,16 +34,63 @@ describe('FolderTrustDialog', () => { ); }); - it('should call onSelect with DO_NOT_TRUST when escape is pressed', async () => { + it('should call onSelect with DO_NOT_TRUST when escape is pressed and not restarting', async () => { const onSelect = vi.fn(); const { stdin } = renderWithProviders( - <FolderTrustDialog onSelect={onSelect} />, + <FolderTrustDialog onSelect={onSelect} isRestarting={false} />, ); - stdin.write('\x1b'); + stdin.write('\x1b'); // escape key await waitFor(() => { expect(onSelect).toHaveBeenCalledWith(FolderTrustChoice.DO_NOT_TRUST); }); }); + + it('should not call onSelect when escape is pressed and is restarting', async () => { + const onSelect = vi.fn(); + const { stdin } = renderWithProviders( + <FolderTrustDialog onSelect={onSelect} isRestarting={true} />, + ); + + stdin.write('\x1b'); // escape key + + await waitFor(() => { + expect(onSelect).not.toHaveBeenCalled(); + }); + }); + + it('should display restart message when isRestarting is true', () => { + const { lastFrame } = renderWithProviders( + <FolderTrustDialog onSelect={vi.fn()} isRestarting={true} />, + ); + + expect(lastFrame()).toContain( + 'To see changes, Gemini CLI must be restarted', + ); + }); + + it('should call process.exit when "r" is pressed and isRestarting is true', async () => { + const { stdin } = renderWithProviders( + <FolderTrustDialog onSelect={vi.fn()} isRestarting={true} />, + ); + + stdin.write('r'); + + await waitFor(() => { + expect(process.exit).toHaveBeenCalledWith(0); + }); + }); + + it('should not call process.exit when "r" is pressed and isRestarting is false', async () => { + const { stdin } = renderWithProviders( + <FolderTrustDialog onSelect={vi.fn()} isRestarting={false} />, + ); + + stdin.write('r'); + + await waitFor(() => { + expect(process.exit).not.toHaveBeenCalled(); + }); + }); }); diff --git a/packages/cli/src/ui/components/FolderTrustDialog.tsx b/packages/cli/src/ui/components/FolderTrustDialog.tsx index 30f3ff52..88aea32c 100644 --- a/packages/cli/src/ui/components/FolderTrustDialog.tsx +++ b/packages/cli/src/ui/components/FolderTrustDialog.tsx @@ -12,6 +12,7 @@ import { RadioSelectItem, } from './shared/RadioButtonSelect.js'; import { useKeypress } from '../hooks/useKeypress.js'; +import * as process from 'process'; export enum FolderTrustChoice { TRUST_FOLDER = 'trust_folder', @@ -21,10 +22,12 @@ export enum FolderTrustChoice { interface FolderTrustDialogProps { onSelect: (choice: FolderTrustChoice) => void; + isRestarting?: boolean; } export const FolderTrustDialog: React.FC<FolderTrustDialogProps> = ({ onSelect, + isRestarting, }) => { useKeypress( (key) => { @@ -32,7 +35,16 @@ export const FolderTrustDialog: React.FC<FolderTrustDialogProps> = ({ onSelect(FolderTrustChoice.DO_NOT_TRUST); } }, - { isActive: true }, + { isActive: !isRestarting }, + ); + + useKeypress( + (key) => { + if (key.name === 'r') { + process.exit(0); + } + }, + { isActive: !!isRestarting }, ); const options: Array<RadioSelectItem<FolderTrustChoice>> = [ @@ -51,24 +63,38 @@ export const FolderTrustDialog: React.FC<FolderTrustDialogProps> = ({ ]; return ( - <Box - flexDirection="column" - borderStyle="round" - borderColor={Colors.AccentYellow} - padding={1} - width="100%" - marginLeft={1} - > - <Box flexDirection="column" marginBottom={1}> - <Text bold>Do you trust this folder?</Text> - <Text> - Trusting a folder allows Gemini to execute commands it suggests. This - is a security feature to prevent accidental execution in untrusted - directories. - </Text> - </Box> + <Box flexDirection="column"> + <Box + flexDirection="column" + borderStyle="round" + borderColor={Colors.AccentYellow} + padding={1} + width="100%" + marginLeft={1} + > + <Box flexDirection="column" marginBottom={1}> + <Text bold>Do you trust this folder?</Text> + <Text> + Trusting a folder allows Gemini to execute commands it suggests. + This is a security feature to prevent accidental execution in + untrusted directories. + </Text> + </Box> - <RadioButtonSelect items={options} onSelect={onSelect} isFocused /> + <RadioButtonSelect + items={options} + onSelect={onSelect} + isFocused={!isRestarting} + /> + </Box> + {isRestarting && ( + <Box marginLeft={1} marginTop={1}> + <Text color={Colors.AccentYellow}> + To see changes, Gemini CLI must be restarted. Press r to exit and + apply changes now. + </Text> + </Box> + )} </Box> ); }; diff --git a/packages/cli/src/ui/components/SettingsDialog.test.tsx b/packages/cli/src/ui/components/SettingsDialog.test.tsx index ee01b2cf..76a12e57 100644 --- a/packages/cli/src/ui/components/SettingsDialog.test.tsx +++ b/packages/cli/src/ui/components/SettingsDialog.test.tsx @@ -140,6 +140,7 @@ describe('SettingsDialog', () => { path: '/workspace/settings.json', }, [], + true, ); describe('Initial Rendering', () => { |
