Sync upstream Gemini-CLI v0.8.2 (#838)

This commit is contained in:
tanzhenxin
2025-10-23 09:27:04 +08:00
committed by GitHub
parent 096fabb5d6
commit eb95c131be
644 changed files with 70389 additions and 23709 deletions

View File

@@ -23,17 +23,35 @@ vi.mock('../ui/commands/approvalModeCommand.js', () => ({
},
}));
vi.mock('../ui/commands/ideCommand.js', () => ({ ideCommand: vi.fn() }));
vi.mock('../ui/commands/ideCommand.js', async () => {
const { CommandKind } = await import('../ui/commands/types.js');
return {
ideCommand: vi.fn().mockResolvedValue({
name: 'ide',
description: 'IDE command',
kind: CommandKind.BUILT_IN,
}),
};
});
vi.mock('../ui/commands/restoreCommand.js', () => ({
restoreCommand: vi.fn(),
}));
vi.mock('../ui/commands/permissionsCommand.js', async () => {
const { CommandKind } = await import('../ui/commands/types.js');
return {
permissionsCommand: {
name: 'permissions',
description: 'Permissions command',
kind: CommandKind.BUILT_IN,
},
};
});
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
import { BuiltinCommandLoader } from './BuiltinCommandLoader.js';
import type { Config } from '@qwen-code/qwen-code-core';
import { CommandKind } from '../ui/commands/types.js';
import { ideCommand } from '../ui/commands/ideCommand.js';
import { restoreCommand } from '../ui/commands/restoreCommand.js';
vi.mock('../ui/commands/authCommand.js', () => ({ authCommand: {} }));
@@ -49,7 +67,9 @@ vi.mock('../ui/commands/extensionsCommand.js', () => ({
}));
vi.mock('../ui/commands/helpCommand.js', () => ({ helpCommand: {} }));
vi.mock('../ui/commands/memoryCommand.js', () => ({ memoryCommand: {} }));
vi.mock('../ui/commands/privacyCommand.js', () => ({ privacyCommand: {} }));
vi.mock('../ui/commands/modelCommand.js', () => ({
modelCommand: { name: 'model' },
}));
vi.mock('../ui/commands/quitCommand.js', () => ({
quitCommand: {},
quitConfirmCommand: {},
@@ -75,18 +95,15 @@ vi.mock('../ui/commands/modelCommand.js', () => ({
describe('BuiltinCommandLoader', () => {
let mockConfig: Config;
const ideCommandMock = ideCommand as Mock;
const restoreCommandMock = restoreCommand as Mock;
beforeEach(() => {
vi.clearAllMocks();
mockConfig = { some: 'config' } as unknown as Config;
mockConfig = {
getFolderTrust: vi.fn().mockReturnValue(true),
getUseModelRouter: () => false,
} as unknown as Config;
ideCommandMock.mockReturnValue({
name: 'ide',
description: 'IDE command',
kind: CommandKind.BUILT_IN,
});
restoreCommandMock.mockReturnValue({
name: 'restore',
description: 'Restore command',
@@ -94,25 +111,23 @@ describe('BuiltinCommandLoader', () => {
});
});
it('should correctly pass the config object to command factory functions', async () => {
it('should correctly pass the config object to restore command factory', async () => {
const loader = new BuiltinCommandLoader(mockConfig);
await loader.loadCommands(new AbortController().signal);
expect(ideCommandMock).toHaveBeenCalledTimes(1);
expect(ideCommandMock).toHaveBeenCalledWith(mockConfig);
// ideCommand is now a constant, no longer needs config
expect(restoreCommandMock).toHaveBeenCalledTimes(1);
expect(restoreCommandMock).toHaveBeenCalledWith(mockConfig);
});
it('should filter out null command definitions returned by factories', async () => {
// Override the mock's behavior for this specific test.
ideCommandMock.mockReturnValue(null);
// ideCommand is now a constant SlashCommand
const loader = new BuiltinCommandLoader(mockConfig);
const commands = await loader.loadCommands(new AbortController().signal);
// The 'ide' command should be filtered out.
// The 'ide' command should be present.
const ideCmd = commands.find((c) => c.name === 'ide');
expect(ideCmd).toBeUndefined();
expect(ideCmd).toBeDefined();
// Other commands should still be present.
const aboutCmd = commands.find((c) => c.name === 'about');
@@ -122,8 +137,7 @@ describe('BuiltinCommandLoader', () => {
it('should handle a null config gracefully when calling factories', async () => {
const loader = new BuiltinCommandLoader(null);
await loader.loadCommands(new AbortController().signal);
expect(ideCommandMock).toHaveBeenCalledTimes(1);
expect(ideCommandMock).toHaveBeenCalledWith(null);
// ideCommand is now a constant, no longer needs config
expect(restoreCommandMock).toHaveBeenCalledTimes(1);
expect(restoreCommandMock).toHaveBeenCalledWith(null);
});
@@ -149,4 +163,27 @@ describe('BuiltinCommandLoader', () => {
const modelCmd = commands.find((c) => c.name === 'model');
expect(modelCmd).toBeDefined();
});
it('should include permissions command when folder trust is enabled', async () => {
const loader = new BuiltinCommandLoader(mockConfig);
const commands = await loader.loadCommands(new AbortController().signal);
const permissionsCmd = commands.find((c) => c.name === 'permissions');
expect(permissionsCmd).toBeDefined();
});
it('should exclude permissions command when folder trust is disabled', async () => {
(mockConfig.getFolderTrust as Mock).mockReturnValue(false);
const loader = new BuiltinCommandLoader(mockConfig);
const commands = await loader.loadCommands(new AbortController().signal);
const permissionsCmd = commands.find((c) => c.name === 'permissions');
expect(permissionsCmd).toBeUndefined();
});
it('should always include modelCommand', async () => {
const loader = new BuiltinCommandLoader(mockConfig);
const commands = await loader.loadCommands(new AbortController().signal);
const modelCmd = commands.find((c) => c.name === 'model');
expect(modelCmd).toBeDefined();
expect(modelCmd?.name).toBe('model');
});
});