diff options
Diffstat (limited to 'packages/cli/src/ui/commands/ideCommand.test.ts')
| -rw-r--r-- | packages/cli/src/ui/commands/ideCommand.test.ts | 138 |
1 files changed, 36 insertions, 102 deletions
diff --git a/packages/cli/src/ui/commands/ideCommand.test.ts b/packages/cli/src/ui/commands/ideCommand.test.ts index d1d72466..3c73f52c 100644 --- a/packages/cli/src/ui/commands/ideCommand.test.ts +++ b/packages/cli/src/ui/commands/ideCommand.test.ts @@ -15,24 +15,16 @@ import { } from 'vitest'; import { ideCommand } from './ideCommand.js'; import { type CommandContext } from './types.js'; -import { type Config } from '@google/gemini-cli-core'; -import * as child_process from 'child_process'; -import { glob } from 'glob'; - -import { IDEConnectionStatus } from '@google/gemini-cli-core/index.js'; +import { type Config, DetectedIde } from '@google/gemini-cli-core'; +import * as core from '@google/gemini-cli-core'; vi.mock('child_process'); vi.mock('glob'); - -function regexEscape(value: string) { - return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -} +vi.mock('@google/gemini-cli-core'); describe('ideCommand', () => { let mockContext: CommandContext; let mockConfig: Config; - let execSyncSpy: MockInstance; - let globSyncSpy: MockInstance; let platformSpy: MockInstance; beforeEach(() => { @@ -47,8 +39,6 @@ describe('ideCommand', () => { getIdeClient: vi.fn(), } as unknown as Config; - execSyncSpy = vi.spyOn(child_process, 'execSync'); - globSyncSpy = vi.spyOn(glob, 'sync'); platformSpy = vi.spyOn(process, 'platform', 'get'); }); @@ -64,6 +54,9 @@ describe('ideCommand', () => { it('should return the ide command if ideMode is enabled', () => { vi.mocked(mockConfig.getIdeMode).mockReturnValue(true); + vi.mocked(mockConfig.getIdeClient).mockReturnValue({ + getCurrentIde: () => DetectedIde.VSCode, + } as ReturnType<Config['getIdeClient']>); const command = ideCommand(mockConfig); expect(command).not.toBeNull(); expect(command?.name).toBe('ide'); @@ -78,12 +71,13 @@ describe('ideCommand', () => { vi.mocked(mockConfig.getIdeMode).mockReturnValue(true); vi.mocked(mockConfig.getIdeClient).mockReturnValue({ getConnectionStatus: mockGetConnectionStatus, + getCurrentIde: () => DetectedIde.VSCode, } as ReturnType<Config['getIdeClient']>); }); it('should show connected status', () => { mockGetConnectionStatus.mockReturnValue({ - status: IDEConnectionStatus.Connected, + status: core.IDEConnectionStatus.Connected, }); const command = ideCommand(mockConfig); const result = command!.subCommands![0].action!(mockContext, ''); @@ -97,7 +91,7 @@ describe('ideCommand', () => { it('should show connecting status', () => { mockGetConnectionStatus.mockReturnValue({ - status: IDEConnectionStatus.Connecting, + status: core.IDEConnectionStatus.Connecting, }); const command = ideCommand(mockConfig); const result = command!.subCommands![0].action!(mockContext, ''); @@ -110,7 +104,7 @@ describe('ideCommand', () => { }); it('should show disconnected status', () => { mockGetConnectionStatus.mockReturnValue({ - status: IDEConnectionStatus.Disconnected, + status: core.IDEConnectionStatus.Disconnected, }); const command = ideCommand(mockConfig); const result = command!.subCommands![0].action!(mockContext, ''); @@ -125,7 +119,7 @@ describe('ideCommand', () => { it('should show disconnected status with details', () => { const details = 'Something went wrong'; mockGetConnectionStatus.mockReturnValue({ - status: IDEConnectionStatus.Disconnected, + status: core.IDEConnectionStatus.Disconnected, details, }); const command = ideCommand(mockConfig); @@ -140,128 +134,68 @@ describe('ideCommand', () => { }); describe('install subcommand', () => { + const mockInstall = vi.fn(); beforeEach(() => { vi.mocked(mockConfig.getIdeMode).mockReturnValue(true); + vi.mocked(mockConfig.getIdeClient).mockReturnValue({ + getCurrentIde: () => DetectedIde.VSCode, + } as ReturnType<Config['getIdeClient']>); + vi.mocked(core.getIdeInstaller).mockReturnValue({ + install: mockInstall, + isInstalled: vi.fn(), + }); platformSpy.mockReturnValue('linux'); }); - it('should show an error if VSCode is not installed', async () => { - execSyncSpy.mockImplementation(() => { - throw new Error('Command not found'); + it('should install the extension', async () => { + mockInstall.mockResolvedValue({ + success: true, + message: 'Successfully installed.', }); const command = ideCommand(mockConfig); - - await command!.subCommands![1].action!(mockContext, ''); - expect(mockContext.ui.addItem).toHaveBeenCalledWith( - expect.objectContaining({ - type: 'error', - text: expect.stringMatching(/VS Code command-line tool .* not found/), - }), - expect.any(Number), - ); - }); - - it('should show an error if the VSIX file is not found', async () => { - execSyncSpy.mockReturnValue(''); // VSCode is installed - globSyncSpy.mockReturnValue([]); // No .vsix file found - - const command = ideCommand(mockConfig); await command!.subCommands![1].action!(mockContext, ''); - expect(mockContext.ui.addItem).toHaveBeenCalledWith( - expect.objectContaining({ - type: 'error', - text: 'Could not find the required VS Code companion extension. Please file a bug via /bug.', - }), - expect.any(Number), - ); - }); - - it('should install the extension if found in the bundle directory', async () => { - const vsixPath = '/path/to/bundle/gemini.vsix'; - execSyncSpy.mockReturnValue(''); // VSCode is installed - globSyncSpy.mockReturnValue([vsixPath]); // Found .vsix file - - const command = ideCommand(mockConfig); - await command!.subCommands![1].action!(mockContext, ''); - - expect(globSyncSpy).toHaveBeenCalledWith( - expect.stringContaining('.vsix'), - ); - expect(execSyncSpy).toHaveBeenCalledWith( - expect.stringMatching( - new RegExp( - `code(.cmd)? --install-extension ${regexEscape(vsixPath)} --force`, - ), - ), - { stdio: 'pipe' }, - ); + expect(core.getIdeInstaller).toHaveBeenCalledWith('vscode'); + expect(mockInstall).toHaveBeenCalled(); expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: 'info', - text: `Installing VS Code companion extension...`, + text: `Installing IDE companion extension...`, }), expect.any(Number), ); expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: 'info', - text: 'VS Code companion extension installed successfully. Restart gemini-cli in a fresh terminal window.', + text: 'Successfully installed.', }), expect.any(Number), ); }); - it('should install the extension if found in the dev directory', async () => { - const vsixPath = '/path/to/dev/gemini.vsix'; - execSyncSpy.mockReturnValue(''); // VSCode is installed - // First glob call for bundle returns nothing, second for dev returns path. - globSyncSpy.mockReturnValueOnce([]).mockReturnValueOnce([vsixPath]); + it('should show an error if installation fails', async () => { + mockInstall.mockResolvedValue({ + success: false, + message: 'Installation failed.', + }); const command = ideCommand(mockConfig); await command!.subCommands![1].action!(mockContext, ''); - expect(globSyncSpy).toHaveBeenCalledTimes(2); - expect(execSyncSpy).toHaveBeenCalledWith( - expect.stringMatching( - new RegExp( - `code(.cmd)? --install-extension ${regexEscape(vsixPath)} --force`, - ), - ), - { stdio: 'pipe' }, - ); + expect(core.getIdeInstaller).toHaveBeenCalledWith('vscode'); + expect(mockInstall).toHaveBeenCalled(); expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: 'info', - text: 'VS Code companion extension installed successfully. Restart gemini-cli in a fresh terminal window.', + text: `Installing IDE companion extension...`, }), expect.any(Number), ); - }); - - it('should show an error if installation fails', async () => { - const vsixPath = '/path/to/bundle/gemini.vsix'; - const errorMessage = 'Installation failed'; - execSyncSpy - .mockReturnValueOnce('') // VSCode is installed check - .mockImplementation(() => { - // Installation command - const error: Error & { stderr?: Buffer } = new Error( - 'Command failed', - ); - error.stderr = Buffer.from(errorMessage); - throw error; - }); - globSyncSpy.mockReturnValue([vsixPath]); - - const command = ideCommand(mockConfig); - await command!.subCommands![1].action!(mockContext, ''); - expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect.objectContaining({ type: 'error', - text: `Failed to install VS Code companion extension.`, + text: 'Installation failed.', }), expect.any(Number), ); |
