CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes45downloads
BuiltinCommandLoader.test.ts296 linesDownload Raw Back to services
1/**2 * @license3 * Copyright 2025 Google LLC4 * SPDX-License-Identifier: Apache-2.05 */6 7vi.mock('../ui/commands/aboutCommand.js', async () => {8  const { CommandKind } = await import('../ui/commands/types.js');9  return {10    aboutCommand: {11      name: 'status',12      altNames: ['about'],13      description: 'About the CLI',14      kind: CommandKind.BUILT_IN,15    },16  };17});18 19vi.mock('../ui/commands/approvalModeCommand.js', () => ({20  approvalModeCommand: {21    name: 'approval-mode',22    description: 'Approval mode command',23    kind: 'built-in',24  },25}));26vi.mock('../ui/commands/cdCommand.js', () => ({27  cdCommand: {28    name: 'cd',29    description: 'Change directory command',30    kind: 'built-in',31  },32}));33 34vi.mock('../ui/commands/ideCommand.js', async () => {35  const { CommandKind } = await import('../ui/commands/types.js');36  return {37    ideCommand: vi.fn().mockResolvedValue({38      name: 'ide',39      description: 'IDE command',40      kind: CommandKind.BUILT_IN,41    }),42  };43});44vi.mock('../ui/commands/restoreCommand.js', () => ({45  restoreCommand: vi.fn(),46}));47vi.mock('../ui/commands/trustCommand.js', async () => {48  const { CommandKind } = await import('../ui/commands/types.js');49  return {50    trustCommand: {51      name: 'trust',52      description: 'Trust command',53      kind: CommandKind.BUILT_IN,54    },55  };56});57vi.mock('../ui/commands/permissionsCommand.js', async () => {58  const { CommandKind } = await import('../ui/commands/types.js');59  return {60    permissionsCommand: {61      name: 'permissions',62      description: 'Manage permission rules',63      kind: CommandKind.BUILT_IN,64    },65  };66});67 68vi.mock('../ui/commands/hooksCommand.js', async () => {69  const { CommandKind } = await import('../ui/commands/types.js');70  return {71    hooksCommand: {72      name: 'hooks',73      description: 'Hooks command',74      kind: CommandKind.BUILT_IN,75    },76  };77});78 79import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';80import { BuiltinCommandLoader } from './BuiltinCommandLoader.js';81import type { Config } from '@qwen-code/qwen-code-core';82import { CommandKind } from '../ui/commands/types.js';83 84import { restoreCommand } from '../ui/commands/restoreCommand.js';85 86vi.mock('../ui/commands/authCommand.js', () => ({ authCommand: {} }));87vi.mock('../ui/commands/bugCommand.js', () => ({ bugCommand: {} }));88vi.mock('../ui/commands/clearCommand.js', () => ({ clearCommand: {} }));89vi.mock('../ui/commands/compressCommand.js', () => ({ compressCommand: {} }));90vi.mock('../ui/commands/docsCommand.js', () => ({ docsCommand: {} }));91vi.mock('../ui/commands/exportCommand.js', () => ({ exportCommand: {} }));92vi.mock('../ui/commands/editorCommand.js', () => ({ editorCommand: {} }));93vi.mock('../ui/commands/extensionsCommand.js', () => ({94  extensionsCommand: {},95}));96vi.mock('../ui/commands/helpCommand.js', () => ({ helpCommand: {} }));97vi.mock('../ui/commands/memoryCommand.js', () => ({ memoryCommand: {} }));98vi.mock('../ui/commands/insightCommand.js', () => ({ insightCommand: {} }));99vi.mock('../ui/commands/modelCommand.js', () => ({100  modelCommand: { name: 'model' },101}));102vi.mock('../ui/commands/quitCommand.js', () => ({103  quitCommand: {},104}));105vi.mock('../ui/commands/statsCommand.js', () => ({ statsCommand: {} }));106vi.mock('../ui/commands/themeCommand.js', () => ({ themeCommand: {} }));107vi.mock('../ui/commands/toolsCommand.js', () => ({ toolsCommand: {} }));108vi.mock('../ui/commands/mcpCommand.js', () => ({109  mcpCommand: {110    name: 'mcp',111    description: 'MCP command',112    kind: 'BUILT_IN',113  },114}));115vi.mock('../ui/commands/modelCommand.js', () => ({116  modelCommand: {117    name: 'model',118    description: 'Model command',119    kind: 'BUILT_IN',120  },121}));122 123describe('BuiltinCommandLoader', () => {124  let mockConfig: Config;125 126  const restoreCommandMock = restoreCommand as Mock;127 128  beforeEach(() => {129    vi.clearAllMocks();130    mockConfig = {131      getFolderTrust: vi.fn().mockReturnValue(true),132      getUseModelRouter: () => false,133      getDisableAllHooks: vi.fn().mockReturnValue(false),134      isManagedMemoryAvailable: vi.fn().mockReturnValue(true),135      isLspEnabled: vi.fn().mockReturnValue(false),136      isWorkflowsEnabled: vi.fn().mockReturnValue(false),137    } as unknown as Config;138 139    restoreCommandMock.mockReturnValue({140      name: 'restore',141      description: 'Restore command',142      kind: CommandKind.BUILT_IN,143    });144  });145 146  it('should correctly pass the config object to restore command factory', async () => {147    const loader = new BuiltinCommandLoader(mockConfig);148    await loader.loadCommands(new AbortController().signal);149 150    // ideCommand is now a constant, no longer needs config151    expect(restoreCommandMock).toHaveBeenCalledTimes(1);152    expect(restoreCommandMock).toHaveBeenCalledWith(mockConfig);153  });154 155  it('should filter out null command definitions returned by factories', async () => {156    // ideCommand is now a constant SlashCommand157    const loader = new BuiltinCommandLoader(mockConfig);158    const commands = await loader.loadCommands(new AbortController().signal);159 160    // The 'ide' command should be present.161    const ideCmd = commands.find((c) => c.name === 'ide');162    expect(ideCmd).toBeDefined();163 164    // Other commands should still be present.165    const statusCmd = commands.find((c) => c.name === 'status');166    expect(statusCmd).toBeDefined();167  });168 169  it('should handle a null config gracefully when calling factories', async () => {170    const loader = new BuiltinCommandLoader(null);171    await loader.loadCommands(new AbortController().signal);172    // ideCommand is now a constant, no longer needs config173    expect(restoreCommandMock).toHaveBeenCalledTimes(1);174    expect(restoreCommandMock).toHaveBeenCalledWith(null);175  });176 177  it('should return a list of all loaded commands', async () => {178    const loader = new BuiltinCommandLoader(mockConfig);179    const commands = await loader.loadCommands(new AbortController().signal);180 181    const statusCmd = commands.find((c) => c.name === 'status');182    expect(statusCmd).toBeDefined();183    expect(statusCmd?.kind).toBe(CommandKind.BUILT_IN);184 185    const approvalModeCmd = commands.find((c) => c.name === 'approval-mode');186    expect(approvalModeCmd).toBeDefined();187    expect(approvalModeCmd?.kind).toBe(CommandKind.BUILT_IN);188 189    const cdCmd = commands.find((c) => c.name === 'cd');190    expect(cdCmd).toBeDefined();191    expect(cdCmd?.kind).toBe(CommandKind.BUILT_IN);192 193    const ideCmd = commands.find((c) => c.name === 'ide');194    expect(ideCmd).toBeDefined();195 196    const importConfigCmd = commands.find((c) => c.name === 'import-config');197    expect(importConfigCmd).toBeDefined();198 199    const mcpCmd = commands.find((c) => c.name === 'mcp');200    expect(mcpCmd).toBeDefined();201 202    const modelCmd = commands.find((c) => c.name === 'model');203    expect(modelCmd).toBeDefined();204  });205 206  it('should include trust command when folder trust is enabled', async () => {207    const loader = new BuiltinCommandLoader(mockConfig);208    const commands = await loader.loadCommands(new AbortController().signal);209    const trustCmd = commands.find((c) => c.name === 'trust');210    expect(trustCmd).toBeDefined();211  });212 213  it('should exclude trust command when folder trust is disabled', async () => {214    (mockConfig.getFolderTrust as Mock).mockReturnValue(false);215    const loader = new BuiltinCommandLoader(mockConfig);216    const commands = await loader.loadCommands(new AbortController().signal);217    const trustCmd = commands.find((c) => c.name === 'trust');218    expect(trustCmd).toBeUndefined();219  });220 221  it('should always include modelCommand', async () => {222    const loader = new BuiltinCommandLoader(mockConfig);223    const commands = await loader.loadCommands(new AbortController().signal);224    const modelCmd = commands.find((c) => c.name === 'model');225    expect(modelCmd).toBeDefined();226    expect(modelCmd?.name).toBe('model');227  });228 229  it('should always register the /fork command', async () => {230    const loader = new BuiltinCommandLoader(mockConfig);231    const commands = await loader.loadCommands(new AbortController().signal);232    const forkCmd = commands.find((c) => c.name === 'fork');233    expect(forkCmd).toBeDefined();234    expect(forkCmd?.kind).toBe(CommandKind.BUILT_IN);235  });236 237  it('should include lsp command only when LSP is enabled', async () => {238    const disabledLoader = new BuiltinCommandLoader(mockConfig);239    const disabledCommands = await disabledLoader.loadCommands(240      new AbortController().signal,241    );242    expect(disabledCommands.find((c) => c.name === 'lsp')).toBeUndefined();243 244    (mockConfig.isLspEnabled as Mock).mockReturnValue(true);245    const enabledLoader = new BuiltinCommandLoader(mockConfig);246    const enabledCommands = await enabledLoader.loadCommands(247      new AbortController().signal,248    );249 250    expect(enabledCommands.find((c) => c.name === 'lsp')).toBeDefined();251  });252 253  it('should still load all other commands when ideCommand() throws', async () => {254    // Simulate ideCommand() failure (e.g., platform-specific process detection fails)255    const { ideCommand: ideCommandMock } = await import(256      '../ui/commands/ideCommand.js'257    );258    (ideCommandMock as Mock).mockRejectedValueOnce(259      new Error('PowerShell not available'),260    );261 262    const loader = new BuiltinCommandLoader(mockConfig);263    const commands = await loader.loadCommands(new AbortController().signal);264 265    // IDE command should NOT be present266    const ideCmd = commands.find((c) => c.name === 'ide');267    expect(ideCmd).toBeUndefined();268 269    // But all other built-in commands should still be loaded270    const modelCmd = commands.find((c) => c.name === 'model');271    expect(modelCmd).toBeDefined();272 273    const statusCmd = commands.find((c) => c.name === 'status');274    expect(statusCmd).toBeDefined();275 276    const mcpCmd = commands.find((c) => c.name === 'mcp');277    expect(mcpCmd).toBeDefined();278  });279 280  it('should always include hooks command regardless of disableAllHooks', async () => {281    // When disableAllHooks is false282    const loader1 = new BuiltinCommandLoader(mockConfig);283    const commands1 = await loader1.loadCommands(new AbortController().signal);284    const hooksCmd1 = commands1.find((c) => c.name === 'hooks');285    expect(hooksCmd1).toBeDefined();286 287    // When disableAllHooks is true - hooks command should still be available288    // (it will show a disabled state page in the UI instead of hiding the command)289    (mockConfig.getDisableAllHooks as Mock).mockReturnValue(true);290    const loader2 = new BuiltinCommandLoader(mockConfig);291    const commands2 = await loader2.loadCommands(new AbortController().signal);292    const hooksCmd2 = commands2.find((c) => c.name === 'hooks');293    expect(hooksCmd2).toBeDefined();294  });295});296 
basant307/AI_Governance_Project · CoolFace