fix(cli): Improve header spacing (#18531)

This commit is contained in:
N. Taylor Mullen
2026-02-09 18:12:42 -08:00
committed by GitHub
parent 9081743a7f
commit 0a3ecf3a75
2 changed files with 83 additions and 60 deletions
@@ -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 ? (