CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
settings.test.ts346 linesDownload Raw Back to extensions
1/**2 * @license3 * Copyright 2025 Google LLC4 * SPDX-License-Identifier: Apache-2.05 */6 7import { describe, it, expect, vi, beforeEach } from 'vitest';8import { settingsCommand } from './settings.js';9import yargs from 'yargs';10 11const mockGetLoadedExtensions = vi.hoisted(() => vi.fn());12const mockGetScopedEnvContents = vi.hoisted(() => vi.fn());13const mockUpdateSetting = vi.hoisted(() => vi.fn());14const mockPromptForSetting = vi.hoisted(() => vi.fn());15const mockWriteStdoutLine = vi.hoisted(() => vi.fn());16 17vi.mock('../../utils/stdioHelpers.js', () => ({18  writeStdoutLine: mockWriteStdoutLine,19  writeStderrLine: vi.fn(),20  clearScreen: vi.fn(),21}));22 23vi.mock('./utils.js', () => ({24  getExtensionManager: vi.fn().mockResolvedValue({25    getLoadedExtensions: mockGetLoadedExtensions,26  }),27}));28 29vi.mock('@qwen-code/qwen-code-core', () => ({30  ExtensionSettingScope: {31    USER: 'user',32    WORKSPACE: 'workspace',33  },34  getScopedEnvContents: mockGetScopedEnvContents,35  promptForSetting: mockPromptForSetting,36  updateSetting: mockUpdateSetting,37}));38 39describe('extensions settings command', () => {40  it('should fail if no subcommand is provided', () => {41    const validationParser = yargs([])42      .command(settingsCommand)43      .fail(false)44      .locale('en');45    expect(() => validationParser.parse('settings')).toThrow(46      'Not enough non-option arguments: got 0, need at least 1',47    );48  });49 50  it('should register set subcommand', () => {51    const parser = yargs([]).command(settingsCommand).fail(false).locale('en');52    expect(() => parser.parse('settings set')).toThrow(53      'Not enough non-option arguments',54    );55  });56 57  it('should register list subcommand', () => {58    const parser = yargs([]).command(settingsCommand).fail(false).locale('en');59    expect(() => parser.parse('settings list')).toThrow(60      'Not enough non-option arguments',61    );62  });63 64  it('should accept set command with name and setting', () => {65    const parser = yargs([]).command(settingsCommand).fail(false).locale('en');66    expect(() =>67      parser.parse('settings set my-extension API_KEY'),68    ).not.toThrow();69  });70 71  it('should accept set command with scope option', () => {72    const parser = yargs([]).command(settingsCommand).fail(false).locale('en');73    expect(() =>74      parser.parse('settings set my-extension API_KEY --scope=workspace'),75    ).not.toThrow();76  });77 78  it('should fail set command with invalid scope', () => {79    const parser = yargs([]).command(settingsCommand).fail(false).locale('en');80    expect(() =>81      parser.parse('settings set my-extension API_KEY --scope=invalid'),82    ).toThrow();83  });84 85  it('should accept list command with name', () => {86    const parser = yargs([]).command(settingsCommand).fail(false).locale('en');87    expect(() => parser.parse('settings list my-extension')).not.toThrow();88  });89});90 91describe('settings set handler', () => {92  beforeEach(() => {93    vi.clearAllMocks();94  });95 96  it('should return early if extension manager is not available', async () => {97    const { getExtensionManager } = await import('./utils.js');98    vi.mocked(getExtensionManager).mockResolvedValueOnce(null as never);99 100    const parser = yargs([]).command(settingsCommand);101    await parser.parseAsync('settings set my-extension API_KEY');102 103    expect(mockUpdateSetting).not.toHaveBeenCalled();104  });105 106  it('should return early if no extensions are loaded', async () => {107    mockGetLoadedExtensions.mockReturnValueOnce([]);108 109    const parser = yargs([]).command(settingsCommand);110    await parser.parseAsync('settings set my-extension API_KEY');111 112    expect(mockUpdateSetting).not.toHaveBeenCalled();113  });114 115  it('should log error if extension is not found', async () => {116    mockGetLoadedExtensions.mockReturnValueOnce([117      { name: 'other-extension', id: 'other-id', config: {} },118    ]);119 120    const parser = yargs([]).command(settingsCommand);121    await parser.parseAsync('settings set my-extension API_KEY');122 123    expect(mockWriteStdoutLine).toHaveBeenCalledWith(124      'Extension "my-extension" not found.',125    );126    expect(mockUpdateSetting).not.toHaveBeenCalled();127  });128 129  it('should call updateSetting with correct arguments for user scope', async () => {130    const mockExtension = {131      name: 'my-extension',132      id: 'ext-id-123',133      config: { name: 'my-extension', settings: [] },134    };135    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);136 137    const parser = yargs([]).command(settingsCommand);138    await parser.parseAsync('settings set my-extension API_KEY');139 140    expect(mockUpdateSetting).toHaveBeenCalledWith(141      mockExtension.config,142      mockExtension.id,143      'API_KEY',144      mockPromptForSetting,145      'user',146    );147  });148 149  it('should call updateSetting with workspace scope when specified', async () => {150    const mockExtension = {151      name: 'my-extension',152      id: 'ext-id-123',153      config: { name: 'my-extension', settings: [] },154    };155    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);156 157    const parser = yargs([]).command(settingsCommand);158    await parser.parseAsync(159      'settings set my-extension API_KEY --scope=workspace',160    );161 162    expect(mockUpdateSetting).toHaveBeenCalledWith(163      mockExtension.config,164      mockExtension.id,165      'API_KEY',166      mockPromptForSetting,167      'workspace',168    );169  });170});171 172describe('settings list handler', () => {173  beforeEach(() => {174    vi.clearAllMocks();175  });176 177  it('should return early if extension manager is not available', async () => {178    const { getExtensionManager } = await import('./utils.js');179    vi.mocked(getExtensionManager).mockResolvedValueOnce(null as never);180 181    const parser = yargs([]).command(settingsCommand);182    await parser.parseAsync('settings list my-extension');183 184    expect(mockGetScopedEnvContents).not.toHaveBeenCalled();185  });186 187  it('should return early if no extensions are loaded', async () => {188    mockGetLoadedExtensions.mockReturnValueOnce([]);189 190    const parser = yargs([]).command(settingsCommand);191    await parser.parseAsync('settings list my-extension');192 193    expect(mockGetScopedEnvContents).not.toHaveBeenCalled();194  });195 196  it('should log error if extension is not found', async () => {197    mockGetLoadedExtensions.mockReturnValueOnce([198      { name: 'other-extension', id: 'other-id', config: {} },199    ]);200 201    const parser = yargs([]).command(settingsCommand);202    await parser.parseAsync('settings list my-extension');203 204    expect(mockWriteStdoutLine).toHaveBeenCalledWith(205      'Extension "my-extension" not found.',206    );207  });208 209  it('should log message if extension has no settings', async () => {210    const mockExtension = {211      name: 'my-extension',212      id: 'ext-id-123',213      config: { name: 'my-extension' },214      settings: [],215    };216    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);217 218    const parser = yargs([]).command(settingsCommand);219    await parser.parseAsync('settings list my-extension');220 221    expect(mockWriteStdoutLine).toHaveBeenCalledWith(222      'Extension "my-extension" has no settings to configure.',223    );224  });225 226  it('should list settings with their values', async () => {227    const mockExtension = {228      name: 'my-extension',229      id: 'ext-id-123',230      config: { name: 'my-extension' },231      settings: [232        {233          name: 'API Key',234          envVar: 'API_KEY',235          description: 'Your API key',236          sensitive: false,237        },238        {239          name: 'Secret Token',240          envVar: 'SECRET_TOKEN',241          description: 'A secret token',242          sensitive: true,243        },244      ],245    };246    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);247    mockGetScopedEnvContents248      .mockResolvedValueOnce({ API_KEY: 'my-api-key' }) // user scope249      .mockResolvedValueOnce({}); // workspace scope250 251    const parser = yargs([]).command(settingsCommand);252    await parser.parseAsync('settings list my-extension');253 254    expect(mockWriteStdoutLine).toHaveBeenCalledWith(255      'Settings for "my-extension":',256    );257    expect(mockWriteStdoutLine).toHaveBeenCalledWith('\n- API Key (API_KEY)');258    expect(mockWriteStdoutLine).toHaveBeenCalledWith(259      '  Description: Your API key',260    );261    expect(mockWriteStdoutLine).toHaveBeenCalledWith(262      '  Value: my-api-key (user)',263    );264  });265 266  it('should show workspace scope for workspace-scoped settings', async () => {267    const mockExtension = {268      name: 'my-extension',269      id: 'ext-id-123',270      config: { name: 'my-extension' },271      settings: [272        {273          name: 'API Key',274          envVar: 'API_KEY',275          description: 'Your API key',276          sensitive: false,277        },278      ],279    };280    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);281    mockGetScopedEnvContents282      .mockResolvedValueOnce({ API_KEY: 'user-value' }) // user scope283      .mockResolvedValueOnce({ API_KEY: 'workspace-value' }); // workspace scope284 285    const parser = yargs([]).command(settingsCommand);286    await parser.parseAsync('settings list my-extension');287 288    // Workspace should override user, and show (workspace) scope289    expect(mockWriteStdoutLine).toHaveBeenCalledWith(290      '  Value: workspace-value (workspace)',291    );292  });293 294  it('should show [not set] for undefined settings', async () => {295    const mockExtension = {296      name: 'my-extension',297      id: 'ext-id-123',298      config: { name: 'my-extension' },299      settings: [300        {301          name: 'API Key',302          envVar: 'API_KEY',303          description: 'Your API key',304          sensitive: false,305        },306      ],307    };308    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);309    mockGetScopedEnvContents310      .mockResolvedValueOnce({}) // user scope311      .mockResolvedValueOnce({}); // workspace scope312 313    const parser = yargs([]).command(settingsCommand);314    await parser.parseAsync('settings list my-extension');315 316    expect(mockWriteStdoutLine).toHaveBeenCalledWith('  Value: [not set]');317  });318 319  it('should show [value stored in keychain] for sensitive settings', async () => {320    const mockExtension = {321      name: 'my-extension',322      id: 'ext-id-123',323      config: { name: 'my-extension' },324      settings: [325        {326          name: 'Secret Token',327          envVar: 'SECRET_TOKEN',328          description: 'A secret token',329          sensitive: true,330        },331      ],332    };333    mockGetLoadedExtensions.mockReturnValueOnce([mockExtension]);334    mockGetScopedEnvContents335      .mockResolvedValueOnce({ SECRET_TOKEN: 'secret-value' }) // user scope336      .mockResolvedValueOnce({}); // workspace scope337 338    const parser = yargs([]).command(settingsCommand);339    await parser.parseAsync('settings list my-extension');340 341    expect(mockWriteStdoutLine).toHaveBeenCalledWith(342      '  Value: [value stored in keychain] (user)',343    );344  });345});346 
basant307/AI_Governance_Project · CoolFace