diff --git a/.vscode/launch.json b/.vscode/launch.json index 95c1bf69..291c3c06 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,9 +12,9 @@ "runtimeArgs": ["run", "start"], "skipFiles": ["/**"], "cwd": "${workspaceFolder}", + "console": "integratedTerminal", "env": { - "GEMINI_SANDBOX": "false", - "GEMINI_API_KEY": "testkey" + "GEMINI_SANDBOX": "false" } }, { diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx index a5f46d93..8d56e96a 100644 --- a/packages/cli/src/ui/components/AuthDialog.test.tsx +++ b/packages/cli/src/ui/components/AuthDialog.test.tsx @@ -5,11 +5,14 @@ */ import { render } from 'ink-testing-library'; +import { describe, it, expect, vi } from 'vitest'; import { AuthDialog } from './AuthDialog.js'; -import { LoadedSettings } from '../../config/settings.js'; +import { LoadedSettings, SettingScope } from '../../config/settings.js'; import { AuthType } from '@gemini-cli/core'; describe('AuthDialog', () => { + const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms)); + it('should show an error if the initial auth type is invalid', () => { const settings: LoadedSettings = new LoadedSettings( { @@ -38,4 +41,75 @@ describe('AuthDialog', () => { 'GEMINI_API_KEY environment variable not found', ); }); + + it('should prevent exiting when no auth method is selected and show error message', async () => { + const onSelect = vi.fn(); + const settings: LoadedSettings = new LoadedSettings( + { + settings: { + selectedAuthType: undefined, + }, + path: '', + }, + { + settings: {}, + path: '', + }, + [], + ); + + const { lastFrame, stdin, unmount } = render( + {}} + settings={settings} + />, + ); + await wait(); + + // Simulate pressing escape key + stdin.write('\u001b'); // ESC key + await wait(); + + // Should show error message instead of calling onSelect + expect(lastFrame()).toContain( + 'You must select an auth method to proceed. Press Ctrl+C twice to exit.', + ); + expect(onSelect).not.toHaveBeenCalled(); + unmount(); + }); + + it('should allow exiting when auth method is already selected', async () => { + const onSelect = vi.fn(); + const settings: LoadedSettings = new LoadedSettings( + { + settings: { + selectedAuthType: AuthType.USE_GEMINI, + }, + path: '', + }, + { + settings: {}, + path: '', + }, + [], + ); + + const { stdin, unmount } = render( + {}} + settings={settings} + />, + ); + await wait(); + + // Simulate pressing escape key + stdin.write('\u001b'); // ESC key + await wait(); + + // Should call onSelect with undefined to exit + expect(onSelect).toHaveBeenCalledWith(undefined, SettingScope.User); + unmount(); + }); }); diff --git a/packages/cli/src/ui/components/AuthDialog.tsx b/packages/cli/src/ui/components/AuthDialog.tsx index 7ae8b7ee..c0e5d4f8 100644 --- a/packages/cli/src/ui/components/AuthDialog.tsx +++ b/packages/cli/src/ui/components/AuthDialog.tsx @@ -78,6 +78,13 @@ export function AuthDialog({ useInput((_input, key) => { if (key.escape) { + if (settings.merged.selectedAuthType === undefined) { + // Prevent exiting if no auth method is set + setErrorMessage( + 'You must select an auth method to proceed. Press Ctrl+C twice to exit.', + ); + return; + } onSelect(undefined, SettingScope.User); } });