mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-12 22:31:12 -07:00
155 lines
4.4 KiB
TypeScript
155 lines
4.4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, type MockInstance } from 'vitest';
|
|
import { handleInstall, installCommand } from './install.js';
|
|
import yargs from 'yargs';
|
|
|
|
const mockInstallExtension = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock('../../config/extension.js', () => ({
|
|
installExtension: mockInstallExtension,
|
|
}));
|
|
|
|
vi.mock('../../utils/errors.js', () => ({
|
|
getErrorMessage: vi.fn((error: Error) => error.message),
|
|
}));
|
|
|
|
describe('extensions install command', () => {
|
|
it('should fail if no source is provided', () => {
|
|
const validationParser = yargs([]).command(installCommand).fail(false);
|
|
expect(() => validationParser.parse('install')).toThrow(
|
|
'Either source or --path must be provided.',
|
|
);
|
|
});
|
|
|
|
it('should fail if both git source and local path are provided', () => {
|
|
const validationParser = yargs([]).command(installCommand).fail(false);
|
|
expect(() =>
|
|
validationParser.parse('install some-url --path /some/path'),
|
|
).toThrow('Arguments source and path are mutually exclusive');
|
|
});
|
|
|
|
it('should fail if both auto update and local path are provided', () => {
|
|
const validationParser = yargs([]).command(installCommand).fail(false);
|
|
expect(() =>
|
|
validationParser.parse(
|
|
'install some-url --path /some/path --auto-update',
|
|
),
|
|
).toThrow('Arguments path and auto-update are mutually exclusive');
|
|
});
|
|
});
|
|
|
|
describe('handleInstall', () => {
|
|
let consoleLogSpy: MockInstance;
|
|
let consoleErrorSpy: MockInstance;
|
|
let processSpy: MockInstance;
|
|
|
|
beforeEach(() => {
|
|
consoleLogSpy = vi.spyOn(console, 'log');
|
|
consoleErrorSpy = vi.spyOn(console, 'error');
|
|
processSpy = vi
|
|
.spyOn(process, 'exit')
|
|
.mockImplementation(() => undefined as never);
|
|
});
|
|
|
|
afterEach(() => {
|
|
mockInstallExtension.mockClear();
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
it('should install an extension from a http source', async () => {
|
|
mockInstallExtension.mockResolvedValue('http-extension');
|
|
|
|
await handleInstall({
|
|
source: 'http://google.com',
|
|
});
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
'Extension "http-extension" installed successfully and enabled.',
|
|
);
|
|
});
|
|
|
|
it('should install an extension from a https source', async () => {
|
|
mockInstallExtension.mockResolvedValue('https-extension');
|
|
|
|
await handleInstall({
|
|
source: 'https://google.com',
|
|
});
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
'Extension "https-extension" installed successfully and enabled.',
|
|
);
|
|
});
|
|
|
|
it('should install an extension from a git source', async () => {
|
|
mockInstallExtension.mockResolvedValue('git-extension');
|
|
|
|
await handleInstall({
|
|
source: 'git@some-url',
|
|
});
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
'Extension "git-extension" installed successfully and enabled.',
|
|
);
|
|
});
|
|
|
|
it('throws an error from an unknown source', async () => {
|
|
await handleInstall({
|
|
source: 'test://google.com',
|
|
});
|
|
|
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
'The source "test://google.com" is not a valid URL format.',
|
|
);
|
|
expect(processSpy).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it('should install an extension from a sso source', async () => {
|
|
mockInstallExtension.mockResolvedValue('sso-extension');
|
|
|
|
await handleInstall({
|
|
source: 'sso://google.com',
|
|
});
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
'Extension "sso-extension" installed successfully and enabled.',
|
|
);
|
|
});
|
|
|
|
it('should install an extension from a local path', async () => {
|
|
mockInstallExtension.mockResolvedValue('local-extension');
|
|
|
|
await handleInstall({
|
|
path: '/some/path',
|
|
});
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
'Extension "local-extension" installed successfully and enabled.',
|
|
);
|
|
});
|
|
|
|
it('should throw an error if no source or path is provided', async () => {
|
|
await handleInstall({});
|
|
|
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
'Either --source or --path must be provided.',
|
|
);
|
|
expect(processSpy).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it('should throw an error if install extension fails', async () => {
|
|
mockInstallExtension.mockRejectedValue(
|
|
new Error('Install extension failed'),
|
|
);
|
|
|
|
await handleInstall({ source: 'git@some-url' });
|
|
|
|
expect(consoleErrorSpy).toHaveBeenCalledWith('Install extension failed');
|
|
expect(processSpy).toHaveBeenCalledWith(1);
|
|
});
|
|
});
|