basant307/AI_Governance_Project
048
1/**2 * @license3 * Copyright 2025 Google LLC4 * SPDX-License-Identifier: Apache-2.05 */6 7import { describe, it, expect, vi, beforeEach } from 'vitest';8import { disableCommand, handleDisable } from './disable.js';9import yargs from 'yargs';10import { SettingScope } from '../../config/settings.js';11 12const mockDisableExtension = vi.hoisted(() => vi.fn());13const mockWriteStdoutLine = vi.hoisted(() => vi.fn());14const mockWriteStderrLine = vi.hoisted(() => vi.fn());15 16vi.mock('./utils.js', async (importOriginal) => {17 const actual = await importOriginal<typeof import('./utils.js')>();18 return {19 ...actual,20 getExtensionManager: vi.fn().mockResolvedValue({21 disableExtension: mockDisableExtension,22 }),23 };24});25 26vi.mock('../../utils/errors.js', () => ({27 getErrorMessage: vi.fn((error: Error) => error.message),28}));29 30vi.mock('../../utils/stdioHelpers.js', () => ({31 writeStdoutLine: mockWriteStdoutLine,32 writeStderrLine: mockWriteStderrLine,33 clearScreen: vi.fn(),34}));35 36describe('extensions disable command', () => {37 const parseDisableCommand = (command: string) =>38 yargs([]).command(disableCommand).fail(false).locale('en').parse(command);39 40 it('should fail if no name is provided', () => {41 expect(() => parseDisableCommand('disable')).toThrow(42 'Not enough non-option arguments: got 0, need at least 1',43 );44 });45 46 it('should fail if invalid scope is provided', () => {47 expect(() =>48 parseDisableCommand('disable test-extension --scope=invalid'),49 ).toThrow(/Invalid scope: invalid/);50 });51 52 it('should fail if unsupported system scopes are provided', () => {53 expect(() =>54 parseDisableCommand('disable test-extension --scope=system'),55 ).toThrow(/Invalid scope: system/);56 expect(() =>57 parseDisableCommand('disable test-extension --scope=systemdefaults'),58 ).toThrow(/Invalid scope: systemdefaults/);59 });60 61 it('should accept valid scope values', () => {62 // Just check that the scope option is recognized, actual execution needs name first63 expect(() =>64 parseDisableCommand('disable my-extension --scope=user'),65 ).not.toThrow();66 expect(() =>67 parseDisableCommand('disable my-extension --scope=workspace'),68 ).not.toThrow();69 });70});71 72describe('handleDisable', () => {73 beforeEach(() => {74 vi.clearAllMocks();75 });76 77 it('should disable an extension with user scope', async () => {78 const processExitSpy = vi79 .spyOn(process, 'exit')80 .mockImplementation(() => undefined as never);81 82 await handleDisable({83 name: 'test-extension',84 scope: 'user',85 });86 87 expect(mockDisableExtension).toHaveBeenCalledWith(88 'test-extension',89 SettingScope.User,90 );91 expect(mockWriteStdoutLine).toHaveBeenCalledWith(92 'Extension "test-extension" successfully disabled for scope "user".',93 );94 95 processExitSpy.mockRestore();96 });97 98 it('should disable an extension with workspace scope', async () => {99 const processExitSpy = vi100 .spyOn(process, 'exit')101 .mockImplementation(() => undefined as never);102 103 await handleDisable({104 name: 'test-extension',105 scope: 'workspace',106 });107 108 expect(mockDisableExtension).toHaveBeenCalledWith(109 'test-extension',110 SettingScope.Workspace,111 );112 expect(mockWriteStdoutLine).toHaveBeenCalledWith(113 'Extension "test-extension" successfully disabled for scope "workspace".',114 );115 116 processExitSpy.mockRestore();117 });118 119 it('should default to user scope when no scope is provided', async () => {120 const processExitSpy = vi121 .spyOn(process, 'exit')122 .mockImplementation(() => undefined as never);123 124 await handleDisable({125 name: 'test-extension',126 });127 128 expect(mockDisableExtension).toHaveBeenCalledWith(129 'test-extension',130 SettingScope.User,131 );132 133 processExitSpy.mockRestore();134 });135 136 it('should reject unsupported system scopes without disabling at user scope', async () => {137 const processExitSpy = vi138 .spyOn(process, 'exit')139 .mockImplementation(() => undefined as never);140 141 await handleDisable({142 name: 'test-extension',143 scope: 'system',144 });145 146 expect(mockDisableExtension).not.toHaveBeenCalled();147 expect(mockWriteStderrLine).toHaveBeenCalledWith(148 expect.stringMatching(/Invalid scope: system/),149 );150 expect(processExitSpy).toHaveBeenCalledWith(1);151 152 processExitSpy.mockRestore();153 });154 155 it('should handle errors and exit with code 1', async () => {156 const processExitSpy = vi157 .spyOn(process, 'exit')158 .mockImplementation(() => undefined as never);159 160 mockDisableExtension.mockRejectedValueOnce(new Error('Disable failed'));161 162 await handleDisable({163 name: 'test-extension',164 scope: 'user',165 });166 167 expect(mockWriteStderrLine).toHaveBeenCalledWith('Disable failed');168 expect(processExitSpy).toHaveBeenCalledWith(1);169 170 processExitSpy.mockRestore();171 });172});173 