Files
gemini-cli/packages/cli/src/commands/skills/list.test.ts
T

180 lines
5.0 KiB
TypeScript

/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {
vi,
describe,
it,
expect,
beforeEach,
afterEach,
type MockInstance,
} from 'vitest';
import { type Config } from '@google/gemini-cli-core';
import { handleList, listCommand } from './list.js';
import { loadSettings, type LoadedSettings } from '../../config/settings.js';
import { loadCliConfig } from '../../config/config.js';
import chalk from 'chalk';
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const { mockCoreDebugLogger } = await import(
'../../test-utils/mockDebugLogger.js'
);
return mockCoreDebugLogger(
await importOriginal<typeof import('@google/gemini-cli-core')>(),
{
stripAnsi: false,
},
);
});
vi.mock('../../config/settings.js');
vi.mock('../../config/config.js');
vi.mock('../utils.js', () => ({
exitCli: vi.fn(),
}));
describe('skills list command', () => {
const mockLoadSettings = vi.mocked(loadSettings);
const mockLoadCliConfig = vi.mocked(loadCliConfig);
let stdoutWriteSpy: MockInstance<typeof process.stdout.write>;
beforeEach(async () => {
vi.clearAllMocks();
mockLoadSettings.mockReturnValue({
merged: {},
} as unknown as LoadedSettings);
stdoutWriteSpy = vi
.spyOn(process.stdout, 'write')
.mockImplementation(() => true);
});
afterEach(() => {
vi.restoreAllMocks();
});
describe('handleList', () => {
it('should log a message if no skills are discovered', async () => {
const mockConfig = {
initialize: vi.fn().mockResolvedValue(undefined),
getSkillManager: vi.fn().mockReturnValue({
getAllSkills: vi.fn().mockReturnValue([]),
}),
};
mockLoadCliConfig.mockResolvedValue(mockConfig as unknown as Config);
await handleList({});
expect(stdoutWriteSpy).toHaveBeenCalledWith('No skills discovered.\n');
});
it('should list all discovered skills', async () => {
const skills = [
{
name: 'skill1',
description: 'desc1',
disabled: false,
location: '/path/to/skill1',
},
{
name: 'skill2',
description: 'desc2',
disabled: true,
location: '/path/to/skill2',
},
];
const mockConfig = {
initialize: vi.fn().mockResolvedValue(undefined),
getSkillManager: vi.fn().mockReturnValue({
getAllSkills: vi.fn().mockReturnValue(skills),
}),
};
mockLoadCliConfig.mockResolvedValue(mockConfig as unknown as Config);
await handleList({});
expect(stdoutWriteSpy).toHaveBeenCalledWith(
chalk.bold('Discovered Agent Skills:') + '\n\n',
);
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining('skill1'),
);
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining(chalk.green('[Enabled]')),
);
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining('skill2'),
);
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining(chalk.red('[Disabled]')),
);
});
it('should filter built-in skills by default and show them with { all: true }', async () => {
const skills = [
{
name: 'regular',
description: 'desc1',
disabled: false,
location: '/loc1',
},
{
name: 'builtin',
description: 'desc2',
disabled: false,
location: '/loc2',
isBuiltin: true,
},
];
const mockConfig = {
initialize: vi.fn().mockResolvedValue(undefined),
getSkillManager: vi.fn().mockReturnValue({
getAllSkills: vi.fn().mockReturnValue(skills),
}),
};
mockLoadCliConfig.mockResolvedValue(mockConfig as unknown as Config);
// Default
await handleList({ all: false });
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining('regular'),
);
expect(stdoutWriteSpy).not.toHaveBeenCalledWith(
expect.stringContaining('builtin'),
);
vi.clearAllMocks();
// With all: true
await handleList({ all: true });
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining('regular'),
);
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining('builtin'),
);
expect(stdoutWriteSpy).toHaveBeenCalledWith(
expect.stringContaining(chalk.gray(' [Built-in]')),
);
});
it('should throw an error when listing fails', async () => {
mockLoadCliConfig.mockRejectedValue(new Error('List failed'));
await expect(handleList({})).rejects.toThrow('List failed');
});
});
describe('listCommand', () => {
const command = listCommand;
it('should have correct command and describe', () => {
expect(command.command).toBe('list [--all]');
expect(command.describe).toBe('Lists discovered agent skills.');
});
});
});