Make ideCommand test windows compatible. (#4746)

This commit is contained in:
Tommaso Sciortino 2025-07-23 14:01:51 -07:00 committed by GitHub
parent 4fd7cf9177
commit 209c8783b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 43 additions and 25 deletions

View File

@ -4,7 +4,15 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; import {
MockInstance,
vi,
describe,
it,
expect,
beforeEach,
afterEach,
} from 'vitest';
import { ideCommand } from './ideCommand.js'; import { ideCommand } from './ideCommand.js';
import { type CommandContext } from './types.js'; import { type CommandContext } from './types.js';
import { type Config } from '@google/gemini-cli-core'; import { type Config } from '@google/gemini-cli-core';
@ -31,14 +39,18 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
}; };
}); });
function regexEscape(value: string) {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
describe('ideCommand', () => { describe('ideCommand', () => {
let mockContext: CommandContext; let mockContext: CommandContext;
let mockConfig: Config; let mockConfig: Config;
let execSyncSpy: vi.SpyInstance; let execSyncSpy: MockInstance;
let globSyncSpy: vi.SpyInstance; let globSyncSpy: MockInstance;
let platformSpy: vi.SpyInstance; let platformSpy: MockInstance;
let getMCPServerStatusSpy: vi.SpyInstance; let getMCPServerStatusSpy: MockInstance;
let getMCPDiscoveryStateSpy: vi.SpyInstance; let getMCPDiscoveryStateSpy: MockInstance;
beforeEach(() => { beforeEach(() => {
mockContext = { mockContext = {
@ -63,13 +75,13 @@ describe('ideCommand', () => {
}); });
it('should return null if ideMode is not enabled', () => { it('should return null if ideMode is not enabled', () => {
(mockConfig.getIdeMode as vi.Mock).mockReturnValue(false); vi.mocked(mockConfig.getIdeMode).mockReturnValue(false);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
expect(command).toBeNull(); expect(command).toBeNull();
}); });
it('should return the ide command if ideMode is enabled', () => { it('should return the ide command if ideMode is enabled', () => {
(mockConfig.getIdeMode as vi.Mock).mockReturnValue(true); vi.mocked(mockConfig.getIdeMode).mockReturnValue(true);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
expect(command).not.toBeNull(); expect(command).not.toBeNull();
expect(command?.name).toBe('ide'); expect(command?.name).toBe('ide');
@ -80,13 +92,13 @@ describe('ideCommand', () => {
describe('status subcommand', () => { describe('status subcommand', () => {
beforeEach(() => { beforeEach(() => {
(mockConfig.getIdeMode as vi.Mock).mockReturnValue(true); vi.mocked(mockConfig.getIdeMode).mockReturnValue(true);
}); });
it('should show connected status', () => { it('should show connected status', () => {
getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.CONNECTED); getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.CONNECTED);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
const result = command?.subCommands?.[0].action(mockContext, ''); const result = command!.subCommands![0].action!(mockContext, '');
expect(getMCPServerStatusSpy).toHaveBeenCalledWith(IDE_SERVER_NAME); expect(getMCPServerStatusSpy).toHaveBeenCalledWith(IDE_SERVER_NAME);
expect(result).toEqual({ expect(result).toEqual({
type: 'message', type: 'message',
@ -98,7 +110,7 @@ describe('ideCommand', () => {
it('should show connecting status', () => { it('should show connecting status', () => {
getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.CONNECTING); getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.CONNECTING);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
const result = command?.subCommands?.[0].action(mockContext, ''); const result = command!.subCommands![0].action!(mockContext, '');
expect(result).toEqual({ expect(result).toEqual({
type: 'message', type: 'message',
messageType: 'info', messageType: 'info',
@ -110,7 +122,7 @@ describe('ideCommand', () => {
getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.DISCONNECTED); getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.DISCONNECTED);
getMCPDiscoveryStateSpy.mockReturnValue(MCPDiscoveryState.IN_PROGRESS); getMCPDiscoveryStateSpy.mockReturnValue(MCPDiscoveryState.IN_PROGRESS);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
const result = command?.subCommands?.[0].action(mockContext, ''); const result = command!.subCommands![0].action!(mockContext, '');
expect(result).toEqual({ expect(result).toEqual({
type: 'message', type: 'message',
messageType: 'info', messageType: 'info',
@ -120,9 +132,9 @@ describe('ideCommand', () => {
it('should show disconnected status', () => { it('should show disconnected status', () => {
getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.DISCONNECTED); getMCPServerStatusSpy.mockReturnValue(MCPServerStatus.DISCONNECTED);
getMCPDiscoveryStateSpy.mockReturnValue(MCPDiscoveryState.NOT_FOUND); getMCPDiscoveryStateSpy.mockReturnValue(MCPDiscoveryState.COMPLETED);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
const result = command?.subCommands?.[0].action(mockContext, ''); const result = command!.subCommands![0].action!(mockContext, '');
expect(result).toEqual({ expect(result).toEqual({
type: 'message', type: 'message',
messageType: 'error', messageType: 'error',
@ -133,7 +145,7 @@ describe('ideCommand', () => {
describe('install subcommand', () => { describe('install subcommand', () => {
beforeEach(() => { beforeEach(() => {
(mockConfig.getIdeMode as vi.Mock).mockReturnValue(true); vi.mocked(mockConfig.getIdeMode).mockReturnValue(true);
platformSpy.mockReturnValue('linux'); platformSpy.mockReturnValue('linux');
}); });
@ -143,14 +155,12 @@ describe('ideCommand', () => {
}); });
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
await command?.subCommands?.[1].action(mockContext, '');
await command!.subCommands![1].action!(mockContext, '');
expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({
type: 'error', type: 'error',
text: expect.stringContaining( text: expect.stringMatching(/VS Code command-line tool .* not found/),
'VS Code command-line tool "code" not found',
),
}), }),
expect.any(Number), expect.any(Number),
); );
@ -161,7 +171,7 @@ describe('ideCommand', () => {
globSyncSpy.mockReturnValue([]); // No .vsix file found globSyncSpy.mockReturnValue([]); // No .vsix file found
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
await command?.subCommands?.[1].action(mockContext, ''); await command!.subCommands![1].action!(mockContext, '');
expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({
@ -178,13 +188,17 @@ describe('ideCommand', () => {
globSyncSpy.mockReturnValue([vsixPath]); // Found .vsix file globSyncSpy.mockReturnValue([vsixPath]); // Found .vsix file
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
await command?.subCommands?.[1].action(mockContext, ''); await command!.subCommands![1].action!(mockContext, '');
expect(globSyncSpy).toHaveBeenCalledWith( expect(globSyncSpy).toHaveBeenCalledWith(
expect.stringContaining('.vsix'), expect.stringContaining('.vsix'),
); );
expect(execSyncSpy).toHaveBeenCalledWith( expect(execSyncSpy).toHaveBeenCalledWith(
`code --install-extension ${vsixPath} --force`, expect.stringMatching(
new RegExp(
`code(.cmd)? --install-extension ${regexEscape(vsixPath)} --force`,
),
),
{ stdio: 'pipe' }, { stdio: 'pipe' },
); );
expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect(mockContext.ui.addItem).toHaveBeenCalledWith(
@ -210,11 +224,15 @@ describe('ideCommand', () => {
globSyncSpy.mockReturnValueOnce([]).mockReturnValueOnce([vsixPath]); globSyncSpy.mockReturnValueOnce([]).mockReturnValueOnce([vsixPath]);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
await command?.subCommands?.[1].action(mockContext, ''); await command!.subCommands![1].action!(mockContext, '');
expect(globSyncSpy).toHaveBeenCalledTimes(2); expect(globSyncSpy).toHaveBeenCalledTimes(2);
expect(execSyncSpy).toHaveBeenCalledWith( expect(execSyncSpy).toHaveBeenCalledWith(
`code --install-extension ${vsixPath} --force`, expect.stringMatching(
new RegExp(
`code(.cmd)? --install-extension ${regexEscape(vsixPath)} --force`,
),
),
{ stdio: 'pipe' }, { stdio: 'pipe' },
); );
expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect(mockContext.ui.addItem).toHaveBeenCalledWith(
@ -242,7 +260,7 @@ describe('ideCommand', () => {
globSyncSpy.mockReturnValue([vsixPath]); globSyncSpy.mockReturnValue([vsixPath]);
const command = ideCommand(mockConfig); const command = ideCommand(mockConfig);
await command?.subCommands?.[1].action(mockContext, ''); await command!.subCommands![1].action!(mockContext, '');
expect(mockContext.ui.addItem).toHaveBeenCalledWith( expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({