mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-27 21:44:25 -07:00
feat(cli): prototype clean UI toggle and minimal-mode bleed-through (#18683)
This commit is contained in:
@@ -9,11 +9,15 @@ import { waitFor } from '../../test-utils/async.js';
|
||||
import { MainContent } from './MainContent.js';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { Box, Text } from 'ink';
|
||||
import type React from 'react';
|
||||
import { act, useState, type JSX } from 'react';
|
||||
import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js';
|
||||
import { ToolCallStatus } from '../types.js';
|
||||
import { SHELL_COMMAND_NAME } from '../constants.js';
|
||||
import type { UIState } from '../contexts/UIStateContext.js';
|
||||
import {
|
||||
UIStateContext,
|
||||
useUIState,
|
||||
type UIState,
|
||||
} from '../contexts/UIStateContext.js';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('../contexts/SettingsContext.js', async () => {
|
||||
@@ -45,7 +49,9 @@ vi.mock('../hooks/useAlternateBuffer.js', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('./AppHeader.js', () => ({
|
||||
AppHeader: () => <Text>AppHeader</Text>,
|
||||
AppHeader: ({ showDetails = true }: { showDetails?: boolean }) => (
|
||||
<Text>{showDetails ? 'AppHeader(full)' : 'AppHeader(minimal)'}</Text>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('./ShowMoreLines.js', () => ({
|
||||
@@ -58,7 +64,7 @@ vi.mock('./shared/ScrollableList.js', () => ({
|
||||
renderItem,
|
||||
}: {
|
||||
data: unknown[];
|
||||
renderItem: (props: { item: unknown }) => React.JSX.Element;
|
||||
renderItem: (props: { item: unknown }) => JSX.Element;
|
||||
}) => (
|
||||
<Box flexDirection="column">
|
||||
<Text>ScrollableList</Text>
|
||||
@@ -87,6 +93,7 @@ describe('MainContent', () => {
|
||||
activePtyId: undefined,
|
||||
embeddedShellFocused: false,
|
||||
historyRemountKey: 0,
|
||||
cleanUiDetailsVisible: true,
|
||||
bannerData: { defaultText: '', warningText: '' },
|
||||
bannerVisible: false,
|
||||
copyModeEnabled: false,
|
||||
@@ -101,7 +108,7 @@ describe('MainContent', () => {
|
||||
const { lastFrame } = renderWithProviders(<MainContent />, {
|
||||
uiState: defaultMockUiState as Partial<UIState>,
|
||||
});
|
||||
await waitFor(() => expect(lastFrame()).toContain('AppHeader'));
|
||||
await waitFor(() => expect(lastFrame()).toContain('AppHeader(full)'));
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('Hello');
|
||||
@@ -116,11 +123,81 @@ describe('MainContent', () => {
|
||||
await waitFor(() => expect(lastFrame()).toContain('ScrollableList'));
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('AppHeader');
|
||||
expect(output).toContain('AppHeader(full)');
|
||||
expect(output).toContain('Hello');
|
||||
expect(output).toContain('Hi there');
|
||||
});
|
||||
|
||||
it('renders minimal header in minimal mode (alternate buffer)', async () => {
|
||||
vi.mocked(useAlternateBuffer).mockReturnValue(true);
|
||||
|
||||
const { lastFrame } = renderWithProviders(<MainContent />, {
|
||||
uiState: {
|
||||
...defaultMockUiState,
|
||||
cleanUiDetailsVisible: false,
|
||||
} as Partial<UIState>,
|
||||
});
|
||||
await waitFor(() => expect(lastFrame()).toContain('Hello'));
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toContain('AppHeader(minimal)');
|
||||
expect(output).not.toContain('AppHeader(full)');
|
||||
expect(output).toContain('Hello');
|
||||
});
|
||||
|
||||
it('restores full header details after toggle in alternate buffer mode', async () => {
|
||||
vi.mocked(useAlternateBuffer).mockReturnValue(true);
|
||||
|
||||
let setShowDetails: ((visible: boolean) => void) | undefined;
|
||||
const ToggleHarness = () => {
|
||||
const outerState = useUIState();
|
||||
const [showDetails, setShowDetailsState] = useState(
|
||||
outerState.cleanUiDetailsVisible,
|
||||
);
|
||||
setShowDetails = setShowDetailsState;
|
||||
|
||||
return (
|
||||
<UIStateContext.Provider
|
||||
value={{ ...outerState, cleanUiDetailsVisible: showDetails }}
|
||||
>
|
||||
<MainContent />
|
||||
</UIStateContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const { lastFrame } = renderWithProviders(<ToggleHarness />, {
|
||||
uiState: {
|
||||
...defaultMockUiState,
|
||||
cleanUiDetailsVisible: false,
|
||||
} as Partial<UIState>,
|
||||
});
|
||||
|
||||
await waitFor(() => expect(lastFrame()).toContain('AppHeader(minimal)'));
|
||||
if (!setShowDetails) {
|
||||
throw new Error('setShowDetails was not initialized');
|
||||
}
|
||||
const setShowDetailsSafe = setShowDetails;
|
||||
|
||||
act(() => {
|
||||
setShowDetailsSafe(true);
|
||||
});
|
||||
|
||||
await waitFor(() => expect(lastFrame()).toContain('AppHeader(full)'));
|
||||
});
|
||||
|
||||
it('always renders full header details in normal buffer mode', async () => {
|
||||
vi.mocked(useAlternateBuffer).mockReturnValue(false);
|
||||
const { lastFrame } = renderWithProviders(<MainContent />, {
|
||||
uiState: {
|
||||
...defaultMockUiState,
|
||||
cleanUiDetailsVisible: false,
|
||||
} as Partial<UIState>,
|
||||
});
|
||||
|
||||
await waitFor(() => expect(lastFrame()).toContain('AppHeader(full)'));
|
||||
expect(lastFrame()).not.toContain('AppHeader(minimal)');
|
||||
});
|
||||
|
||||
it('does not constrain height in alternate buffer mode', async () => {
|
||||
vi.mocked(useAlternateBuffer).mockReturnValue(true);
|
||||
const { lastFrame } = renderWithProviders(<MainContent />, {
|
||||
@@ -129,7 +206,9 @@ describe('MainContent', () => {
|
||||
await waitFor(() => expect(lastFrame()).toContain('Hello'));
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
expect(output).toContain('AppHeader(full)');
|
||||
expect(output).toContain('Hello');
|
||||
expect(output).toContain('Hi there');
|
||||
});
|
||||
|
||||
describe('MainContent Tool Output Height Logic', () => {
|
||||
@@ -210,6 +289,7 @@ describe('MainContent', () => {
|
||||
isEditorDialogOpen: false,
|
||||
slashCommands: [],
|
||||
historyRemountKey: 0,
|
||||
cleanUiDetailsVisible: true,
|
||||
bannerData: {
|
||||
defaultText: '',
|
||||
warningText: '',
|
||||
|
||||
Reference in New Issue
Block a user