/** * @license * Copyright 2026 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { describe, it, expect, vi } from 'vitest'; import { SettingScope, type LoadedSettings, type LoadableSettingScope, } from '../config/settings.js'; import { enableSkill, disableSkill } from './skillSettings.js'; function createMockLoadedSettings(opts: { userSettings?: Record; workspaceSettings?: Record; userPath?: string; workspacePath?: string; }): LoadedSettings { const scopes: Record< string, { settings: Record; originalSettings: Record; path: string; } > = { [SettingScope.User]: { settings: opts.userSettings ?? {}, originalSettings: opts.userSettings ?? {}, path: opts.userPath ?? '/home/user/.gemini/settings.json', }, [SettingScope.Workspace]: { settings: opts.workspaceSettings ?? {}, originalSettings: opts.workspaceSettings ?? {}, path: opts.workspacePath ?? '/project/.gemini/settings.json', }, }; return { forScope: vi.fn((scope: LoadableSettingScope) => scopes[scope]), setValue: vi.fn(), } as unknown as LoadedSettings; } describe('skillSettings', () => { describe('skillStrategy (via enableSkill / disableSkill)', () => { describe('enableSkill', () => { it('should return no-op when the skill is not in any disabled list', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: [] } }, workspaceSettings: { skills: { disabled: [] } }, }); const result = enableSkill(settings, 'my-skill'); expect(result.status).toBe('no-op'); expect(result.action).toBe('enable'); expect(result.skillName).toBe('my-skill'); expect(result.modifiedScopes).toHaveLength(0); expect(settings.setValue).not.toHaveBeenCalled(); }); it('should return no-op when skills.disabled is undefined', () => { const settings = createMockLoadedSettings({ userSettings: {}, workspaceSettings: {}, }); const result = enableSkill(settings, 'my-skill'); expect(result.status).toBe('no-op'); expect(result.action).toBe('enable'); expect(result.modifiedScopes).toHaveLength(0); }); it('should enable the skill when it is in the disabled list of one scope', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: ['my-skill'] } }, workspaceSettings: { skills: { disabled: [] } }, }); const result = enableSkill(settings, 'my-skill'); expect(result.status).toBe('success'); expect(result.action).toBe('enable'); expect(result.modifiedScopes).toHaveLength(1); expect(result.modifiedScopes[0].scope).toBe(SettingScope.User); expect(result.alreadyInStateScopes).toHaveLength(1); expect(result.alreadyInStateScopes[0].scope).toBe( SettingScope.Workspace, ); expect(settings.setValue).toHaveBeenCalledTimes(1); }); it('should enable the skill when it is in the disabled list of both scopes', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: ['my-skill', 'other-skill'] } }, workspaceSettings: { skills: { disabled: ['my-skill'] } }, }); const result = enableSkill(settings, 'my-skill'); expect(result.status).toBe('success'); expect(result.modifiedScopes).toHaveLength(2); expect(result.alreadyInStateScopes).toHaveLength(0); expect(settings.setValue).toHaveBeenCalledTimes(2); }); it('should not affect other skills in the disabled list', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: ['my-skill', 'keep-disabled'] } }, workspaceSettings: { skills: { disabled: [] } }, }); const result = enableSkill(settings, 'my-skill'); expect(result.status).toBe('success'); expect(settings.setValue).toHaveBeenCalledTimes(1); }); }); describe('disableSkill', () => { it('should return no-op when the skill is already in the disabled list', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: ['my-skill'] } }, }); const result = disableSkill(settings, 'my-skill', SettingScope.User); expect(result.status).toBe('no-op'); expect(result.action).toBe('disable'); expect(result.skillName).toBe('my-skill'); expect(result.modifiedScopes).toHaveLength(0); expect(result.alreadyInStateScopes).toHaveLength(1); expect(settings.setValue).not.toHaveBeenCalled(); }); it('should disable the skill when it is not in the disabled list', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: [] } }, }); const result = disableSkill(settings, 'my-skill', SettingScope.User); expect(result.status).toBe('success'); expect(result.action).toBe('disable'); expect(result.modifiedScopes).toHaveLength(1); expect(result.modifiedScopes[0].scope).toBe(SettingScope.User); expect(settings.setValue).toHaveBeenCalledTimes(1); }); it('should disable the skill when skills.disabled is undefined', () => { const settings = createMockLoadedSettings({ userSettings: {}, }); const result = disableSkill(settings, 'my-skill', SettingScope.User); expect(result.status).toBe('success'); expect(result.action).toBe('disable'); expect(result.modifiedScopes).toHaveLength(1); expect(settings.setValue).toHaveBeenCalledTimes(1); }); it('should return error for an invalid scope', () => { const settings = createMockLoadedSettings({}); const result = disableSkill(settings, 'my-skill', SettingScope.Session); expect(result.status).toBe('error'); expect(result.error).toContain('Invalid settings scope'); }); it('should disable in workspace and report user as already disabled', () => { const settings = createMockLoadedSettings({ userSettings: { skills: { disabled: ['my-skill'] } }, workspaceSettings: { skills: { disabled: [] } }, }); const result = disableSkill( settings, 'my-skill', SettingScope.Workspace, ); expect(result.status).toBe('success'); expect(result.modifiedScopes).toHaveLength(1); expect(result.modifiedScopes[0].scope).toBe(SettingScope.Workspace); expect(result.alreadyInStateScopes).toHaveLength(1); expect(result.alreadyInStateScopes[0].scope).toBe(SettingScope.User); }); }); }); });