mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-29 06:25:16 -07:00
fix(cli): ctrl c/ctrl d close cli when in dialogs (#8685)
Co-authored-by: Jacob Richman <jacob314@gmail.com> Co-authored-by: matt korwel <matt.korwel@gmail.com>
This commit is contained in:
@@ -605,4 +605,164 @@ describe('AppContainer State Management', () => {
|
||||
expect(lastCall[2]).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Keyboard Input Handling', () => {
|
||||
it('should block quit command during authentication', () => {
|
||||
mockedUseAuthCommand.mockReturnValue({
|
||||
authState: 'unauthenticated',
|
||||
setAuthState: vi.fn(),
|
||||
authError: null,
|
||||
onAuthError: vi.fn(),
|
||||
});
|
||||
|
||||
const mockHandleSlashCommand = vi.fn();
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: mockHandleSlashCommand,
|
||||
slashCommands: [],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
render(
|
||||
<AppContainer
|
||||
config={mockConfig}
|
||||
settings={mockSettings}
|
||||
version="1.0.0"
|
||||
initializationResult={mockInitResult}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
});
|
||||
|
||||
it('should prevent exit command when text buffer has content', () => {
|
||||
mockedUseTextBuffer.mockReturnValue({
|
||||
text: 'some user input',
|
||||
setText: vi.fn(),
|
||||
});
|
||||
|
||||
const mockHandleSlashCommand = vi.fn();
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: mockHandleSlashCommand,
|
||||
slashCommands: [],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
render(
|
||||
<AppContainer
|
||||
config={mockConfig}
|
||||
settings={mockSettings}
|
||||
version="1.0.0"
|
||||
initializationResult={mockInitResult}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
});
|
||||
|
||||
it('should require double Ctrl+C to exit when dialogs are open', () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
mockedUseThemeCommand.mockReturnValue({
|
||||
isThemeDialogOpen: true,
|
||||
openThemeDialog: vi.fn(),
|
||||
handleThemeSelect: vi.fn(),
|
||||
handleThemeHighlight: vi.fn(),
|
||||
});
|
||||
|
||||
const mockHandleSlashCommand = vi.fn();
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: mockHandleSlashCommand,
|
||||
slashCommands: [],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
render(
|
||||
<AppContainer
|
||||
config={mockConfig}
|
||||
settings={mockSettings}
|
||||
version="1.0.0"
|
||||
initializationResult={mockInitResult}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should cancel ongoing request on first Ctrl+C', () => {
|
||||
const mockCancelOngoingRequest = vi.fn();
|
||||
mockedUseGeminiStream.mockReturnValue({
|
||||
streamingState: 'responding',
|
||||
submitQuery: vi.fn(),
|
||||
initError: null,
|
||||
pendingHistoryItems: [],
|
||||
thought: null,
|
||||
cancelOngoingRequest: mockCancelOngoingRequest,
|
||||
});
|
||||
|
||||
const mockHandleSlashCommand = vi.fn();
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: mockHandleSlashCommand,
|
||||
slashCommands: [],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
render(
|
||||
<AppContainer
|
||||
config={mockConfig}
|
||||
settings={mockSettings}
|
||||
version="1.0.0"
|
||||
initializationResult={mockInitResult}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
});
|
||||
|
||||
it('should reset Ctrl+C state after timeout', () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
const mockHandleSlashCommand = vi.fn();
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: mockHandleSlashCommand,
|
||||
slashCommands: [],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
render(
|
||||
<AppContainer
|
||||
config={mockConfig}
|
||||
settings={mockSettings}
|
||||
version="1.0.0"
|
||||
initializationResult={mockInitResult}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
|
||||
vi.advanceTimersByTime(1001);
|
||||
|
||||
expect(mockHandleSlashCommand).not.toHaveBeenCalledWith('/quit');
|
||||
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user