mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-20 10:10:56 -07:00
180 lines
5.0 KiB
TypeScript
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.');
|
|
});
|
|
});
|
|
});
|