mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
fix(cli): Improve header spacing (#18531)
This commit is contained in:
@@ -4,11 +4,11 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { render } from 'ink-testing-library';
|
|
||||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||||
|
import { act } from 'react';
|
||||||
import { ModelDialog } from './ModelDialog.js';
|
import { ModelDialog } from './ModelDialog.js';
|
||||||
import { ConfigContext } from '../contexts/ConfigContext.js';
|
import { renderWithProviders } from '../../test-utils/render.js';
|
||||||
import { KeypressProvider } from '../contexts/KeypressContext.js';
|
import { waitFor } from '../../test-utils/async.js';
|
||||||
import {
|
import {
|
||||||
DEFAULT_GEMINI_MODEL,
|
DEFAULT_GEMINI_MODEL,
|
||||||
DEFAULT_GEMINI_MODEL_AUTO,
|
DEFAULT_GEMINI_MODEL_AUTO,
|
||||||
@@ -47,12 +47,14 @@ describe('<ModelDialog />', () => {
|
|||||||
setModel: (model: string, isTemporary?: boolean) => void;
|
setModel: (model: string, isTemporary?: boolean) => void;
|
||||||
getModel: () => string;
|
getModel: () => string;
|
||||||
getHasAccessToPreviewModel: () => boolean;
|
getHasAccessToPreviewModel: () => boolean;
|
||||||
|
getIdeMode: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mockConfig: MockConfig = {
|
const mockConfig: MockConfig = {
|
||||||
setModel: mockSetModel,
|
setModel: mockSetModel,
|
||||||
getModel: mockGetModel,
|
getModel: mockGetModel,
|
||||||
getHasAccessToPreviewModel: mockGetHasAccessToPreviewModel,
|
getHasAccessToPreviewModel: mockGetHasAccessToPreviewModel,
|
||||||
|
getIdeMode: () => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -68,17 +70,10 @@ describe('<ModelDialog />', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderComponent = (contextValue = mockConfig as Config) =>
|
const renderComponent = (configValue = mockConfig as Config) =>
|
||||||
render(
|
renderWithProviders(<ModelDialog onClose={mockOnClose} />, {
|
||||||
<KeypressProvider>
|
config: configValue,
|
||||||
<ConfigContext.Provider value={contextValue}>
|
});
|
||||||
<ModelDialog onClose={mockOnClose} />
|
|
||||||
</ConfigContext.Provider>
|
|
||||||
</KeypressProvider>,
|
|
||||||
);
|
|
||||||
|
|
||||||
const waitForUpdate = () =>
|
|
||||||
new Promise((resolve) => setTimeout(resolve, 150));
|
|
||||||
|
|
||||||
it('renders the initial "main" view correctly', () => {
|
it('renders the initial "main" view correctly', () => {
|
||||||
const { lastFrame } = renderComponent();
|
const { lastFrame } = renderComponent();
|
||||||
@@ -93,48 +88,60 @@ describe('<ModelDialog />', () => {
|
|||||||
|
|
||||||
// Select "Manual" (index 1)
|
// Select "Manual" (index 1)
|
||||||
// Press down arrow to move to "Manual"
|
// Press down arrow to move to "Manual"
|
||||||
stdin.write('\u001B[B'); // Arrow Down
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\u001B[B'); // Arrow Down
|
||||||
|
});
|
||||||
|
|
||||||
// Press enter to select
|
// Press enter to select
|
||||||
stdin.write('\r');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\r');
|
||||||
|
});
|
||||||
|
|
||||||
// Should now show manual options
|
// Should now show manual options
|
||||||
expect(lastFrame()).toContain(DEFAULT_GEMINI_MODEL);
|
await waitFor(() => {
|
||||||
expect(lastFrame()).toContain(DEFAULT_GEMINI_FLASH_MODEL);
|
expect(lastFrame()).toContain(DEFAULT_GEMINI_MODEL);
|
||||||
expect(lastFrame()).toContain(DEFAULT_GEMINI_FLASH_LITE_MODEL);
|
expect(lastFrame()).toContain(DEFAULT_GEMINI_FLASH_MODEL);
|
||||||
|
expect(lastFrame()).toContain(DEFAULT_GEMINI_FLASH_LITE_MODEL);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets model and closes when a model is selected in "main" view', async () => {
|
it('sets model and closes when a model is selected in "main" view', async () => {
|
||||||
const { stdin } = renderComponent();
|
const { stdin } = renderComponent();
|
||||||
|
|
||||||
// Select "Auto" (index 0)
|
// Select "Auto" (index 0)
|
||||||
stdin.write('\r');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\r');
|
||||||
|
});
|
||||||
|
|
||||||
expect(mockSetModel).toHaveBeenCalledWith(
|
await waitFor(() => {
|
||||||
DEFAULT_GEMINI_MODEL_AUTO,
|
expect(mockSetModel).toHaveBeenCalledWith(
|
||||||
true, // Session only by default
|
DEFAULT_GEMINI_MODEL_AUTO,
|
||||||
);
|
true, // Session only by default
|
||||||
expect(mockOnClose).toHaveBeenCalled();
|
);
|
||||||
|
expect(mockOnClose).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets model and closes when a model is selected in "manual" view', async () => {
|
it('sets model and closes when a model is selected in "manual" view', async () => {
|
||||||
const { stdin } = renderComponent();
|
const { stdin } = renderComponent();
|
||||||
|
|
||||||
// Navigate to Manual (index 1) and select
|
// Navigate to Manual (index 1) and select
|
||||||
stdin.write('\u001B[B');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\u001B[B');
|
||||||
stdin.write('\r');
|
});
|
||||||
await waitForUpdate();
|
await act(async () => {
|
||||||
|
stdin.write('\r');
|
||||||
|
});
|
||||||
|
|
||||||
// Now in manual view. Default selection is first item (DEFAULT_GEMINI_MODEL)
|
// Now in manual view. Default selection is first item (DEFAULT_GEMINI_MODEL)
|
||||||
stdin.write('\r');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\r');
|
||||||
|
});
|
||||||
|
|
||||||
expect(mockSetModel).toHaveBeenCalledWith(DEFAULT_GEMINI_MODEL, true);
|
await waitFor(() => {
|
||||||
expect(mockOnClose).toHaveBeenCalled();
|
expect(mockSetModel).toHaveBeenCalledWith(DEFAULT_GEMINI_MODEL, true);
|
||||||
|
expect(mockOnClose).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('toggles persist mode with Tab key', async () => {
|
it('toggles persist mode with Tab key', async () => {
|
||||||
@@ -143,48 +150,64 @@ describe('<ModelDialog />', () => {
|
|||||||
expect(lastFrame()).toContain('Remember model for future sessions: false');
|
expect(lastFrame()).toContain('Remember model for future sessions: false');
|
||||||
|
|
||||||
// Press Tab to toggle persist mode
|
// Press Tab to toggle persist mode
|
||||||
stdin.write('\t');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\t');
|
||||||
|
});
|
||||||
|
|
||||||
expect(lastFrame()).toContain('Remember model for future sessions: true');
|
await waitFor(() => {
|
||||||
|
expect(lastFrame()).toContain('Remember model for future sessions: true');
|
||||||
|
});
|
||||||
|
|
||||||
// Select "Auto" (index 0)
|
// Select "Auto" (index 0)
|
||||||
stdin.write('\r');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\r');
|
||||||
|
});
|
||||||
|
|
||||||
expect(mockSetModel).toHaveBeenCalledWith(
|
await waitFor(() => {
|
||||||
DEFAULT_GEMINI_MODEL_AUTO,
|
expect(mockSetModel).toHaveBeenCalledWith(
|
||||||
false, // Persist enabled
|
DEFAULT_GEMINI_MODEL_AUTO,
|
||||||
);
|
false, // Persist enabled
|
||||||
expect(mockOnClose).toHaveBeenCalled();
|
);
|
||||||
|
expect(mockOnClose).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('closes dialog on escape in "main" view', async () => {
|
it('closes dialog on escape in "main" view', async () => {
|
||||||
const { stdin } = renderComponent();
|
const { stdin } = renderComponent();
|
||||||
|
|
||||||
stdin.write('\u001B'); // Escape
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\u001B'); // Escape
|
||||||
|
});
|
||||||
|
|
||||||
expect(mockOnClose).toHaveBeenCalled();
|
await waitFor(() => {
|
||||||
|
expect(mockOnClose).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('goes back to "main" view on escape in "manual" view', async () => {
|
it('goes back to "main" view on escape in "manual" view', async () => {
|
||||||
const { lastFrame, stdin } = renderComponent();
|
const { lastFrame, stdin } = renderComponent();
|
||||||
|
|
||||||
// Go to manual view
|
// Go to manual view
|
||||||
stdin.write('\u001B[B');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\u001B[B');
|
||||||
stdin.write('\r');
|
});
|
||||||
await waitForUpdate();
|
await act(async () => {
|
||||||
|
stdin.write('\r');
|
||||||
|
});
|
||||||
|
|
||||||
expect(lastFrame()).toContain(DEFAULT_GEMINI_MODEL);
|
await waitFor(() => {
|
||||||
|
expect(lastFrame()).toContain(DEFAULT_GEMINI_MODEL);
|
||||||
|
});
|
||||||
|
|
||||||
// Press Escape
|
// Press Escape
|
||||||
stdin.write('\u001B');
|
await act(async () => {
|
||||||
await waitForUpdate();
|
stdin.write('\u001B');
|
||||||
|
});
|
||||||
|
|
||||||
expect(mockOnClose).not.toHaveBeenCalled();
|
await waitFor(() => {
|
||||||
// Should be back to main view (Manual option visible)
|
expect(mockOnClose).not.toHaveBeenCalled();
|
||||||
expect(lastFrame()).toContain('Manual');
|
// Should be back to main view (Manual option visible)
|
||||||
|
expect(lastFrame()).toContain('Manual');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const UserIdentity: React.FC<UserIdentityProps> = ({ config }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box marginY={1} flexDirection="column">
|
<Box marginTop={1} flexDirection="column">
|
||||||
<Box>
|
<Box>
|
||||||
<Text color={theme.text.primary}>
|
<Text color={theme.text.primary}>
|
||||||
{authType === AuthType.LOGIN_WITH_GOOGLE ? (
|
{authType === AuthType.LOGIN_WITH_GOOGLE ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user