mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 14:10:37 -07:00
Add install as an option when extension is selected. (#20358)
This commit is contained in:
@@ -21,6 +21,10 @@ import {
|
||||
ConfigExtensionDialog,
|
||||
type ConfigExtensionDialogProps,
|
||||
} from '../components/ConfigExtensionDialog.js';
|
||||
import {
|
||||
ExtensionRegistryView,
|
||||
type ExtensionRegistryViewProps,
|
||||
} from '../components/views/ExtensionRegistryView.js';
|
||||
import { type CommandContext, type SlashCommand } from './types.js';
|
||||
|
||||
import {
|
||||
@@ -39,6 +43,8 @@ import {
|
||||
} from '../../config/extension-manager.js';
|
||||
import { SettingScope } from '../../config/settings.js';
|
||||
import { stat } from 'node:fs/promises';
|
||||
import { type RegistryExtension } from '../../config/extensionRegistryClient.js';
|
||||
import { waitFor } from '../../test-utils/async.js';
|
||||
|
||||
vi.mock('../../config/extension-manager.js', async (importOriginal) => {
|
||||
const actual =
|
||||
@@ -167,6 +173,7 @@ describe('extensionsCommand', () => {
|
||||
},
|
||||
ui: {
|
||||
dispatchExtensionStateUpdate: mockDispatchExtensionState,
|
||||
removeComponent: vi.fn(),
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -429,6 +436,61 @@ describe('extensionsCommand', () => {
|
||||
throw new Error('Explore action not found');
|
||||
}
|
||||
|
||||
it('should return ExtensionRegistryView custom dialog when experimental.extensionRegistry is true', async () => {
|
||||
mockContext.services.settings.merged.experimental.extensionRegistry = true;
|
||||
|
||||
const result = await exploreAction(mockContext, '');
|
||||
|
||||
expect(result).toBeDefined();
|
||||
if (result?.type !== 'custom_dialog') {
|
||||
throw new Error('Expected custom_dialog');
|
||||
}
|
||||
|
||||
const component =
|
||||
result.component as ReactElement<ExtensionRegistryViewProps>;
|
||||
expect(component.type).toBe(ExtensionRegistryView);
|
||||
expect(component.props.extensionManager).toBe(mockExtensionLoader);
|
||||
});
|
||||
|
||||
it('should handle onSelect and onClose in ExtensionRegistryView', async () => {
|
||||
mockContext.services.settings.merged.experimental.extensionRegistry = true;
|
||||
|
||||
const result = await exploreAction(mockContext, '');
|
||||
if (result?.type !== 'custom_dialog') {
|
||||
throw new Error('Expected custom_dialog');
|
||||
}
|
||||
|
||||
const component =
|
||||
result.component as ReactElement<ExtensionRegistryViewProps>;
|
||||
|
||||
const extension = {
|
||||
extensionName: 'test-ext',
|
||||
url: 'https://github.com/test/ext.git',
|
||||
} as RegistryExtension;
|
||||
|
||||
vi.mocked(inferInstallMetadata).mockResolvedValue({
|
||||
source: extension.url,
|
||||
type: 'git',
|
||||
});
|
||||
mockInstallExtension.mockResolvedValue({ name: extension.url });
|
||||
|
||||
// Call onSelect
|
||||
component.props.onSelect?.(extension);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(inferInstallMetadata).toHaveBeenCalledWith(extension.url);
|
||||
expect(mockInstallExtension).toHaveBeenCalledWith({
|
||||
source: extension.url,
|
||||
type: 'git',
|
||||
});
|
||||
});
|
||||
expect(mockContext.ui.removeComponent).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Call onClose
|
||||
component.props.onClose?.();
|
||||
expect(mockContext.ui.removeComponent).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("should add an info message and call 'open' in a non-sandbox environment", async () => {
|
||||
// Ensure no special environment variables that would affect behavior
|
||||
vi.stubEnv('NODE_ENV', '');
|
||||
|
||||
@@ -280,7 +280,9 @@ async function exploreAction(
|
||||
type: 'custom_dialog' as const,
|
||||
component: React.createElement(ExtensionRegistryView, {
|
||||
onSelect: (extension) => {
|
||||
debugLogger.debug(`Selected extension: ${extension.extensionName}`);
|
||||
debugLogger.log(`Selected extension: ${extension.extensionName}`);
|
||||
void installAction(context, extension.url);
|
||||
context.ui.removeComponent();
|
||||
},
|
||||
onClose: () => context.ui.removeComponent(),
|
||||
extensionManager,
|
||||
|
||||
@@ -24,7 +24,7 @@ import { useRegistrySearch } from '../../hooks/useRegistrySearch.js';
|
||||
|
||||
import { useUIState } from '../../contexts/UIStateContext.js';
|
||||
|
||||
interface ExtensionRegistryViewProps {
|
||||
export interface ExtensionRegistryViewProps {
|
||||
onSelect?: (extension: RegistryExtension) => void;
|
||||
onClose?: () => void;
|
||||
extensionManager: ExtensionManager;
|
||||
|
||||
Reference in New Issue
Block a user