mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-13 07:30:52 -07:00
119 lines
3.3 KiB
TypeScript
119 lines
3.3 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
import { planCommand } from './planCommand.js';
|
|
import { type CommandContext } from './types.js';
|
|
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
|
|
import { MessageType } from '../types.js';
|
|
import {
|
|
ApprovalMode,
|
|
coreEvents,
|
|
processSingleFileContent,
|
|
type ProcessedFileReadResult,
|
|
} from '@google/gemini-cli-core';
|
|
|
|
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|
const actual =
|
|
await importOriginal<typeof import('@google/gemini-cli-core')>();
|
|
return {
|
|
...actual,
|
|
coreEvents: {
|
|
emitFeedback: vi.fn(),
|
|
},
|
|
processSingleFileContent: vi.fn(),
|
|
partToString: vi.fn((val) => val),
|
|
};
|
|
});
|
|
|
|
vi.mock('node:path', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('node:path')>();
|
|
return {
|
|
...actual,
|
|
default: { ...actual },
|
|
join: vi.fn((...args) => args.join('/')),
|
|
};
|
|
});
|
|
|
|
describe('planCommand', () => {
|
|
let mockContext: CommandContext;
|
|
|
|
beforeEach(() => {
|
|
mockContext = createMockCommandContext({
|
|
services: {
|
|
config: {
|
|
isPlanEnabled: vi.fn(),
|
|
setApprovalMode: vi.fn(),
|
|
getApprovedPlanPath: vi.fn(),
|
|
getApprovalMode: vi.fn(),
|
|
getFileSystemService: vi.fn(),
|
|
storage: {
|
|
getProjectTempPlansDir: vi.fn().mockReturnValue('/mock/plans/dir'),
|
|
},
|
|
},
|
|
},
|
|
ui: {
|
|
addItem: vi.fn(),
|
|
},
|
|
} as unknown as CommandContext);
|
|
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it('should have the correct name and description', () => {
|
|
expect(planCommand.name).toBe('plan');
|
|
expect(planCommand.description).toBe(
|
|
'Switch to Plan Mode and view current plan',
|
|
);
|
|
});
|
|
|
|
it('should switch to plan mode if enabled', async () => {
|
|
vi.mocked(mockContext.services.config!.isPlanEnabled).mockReturnValue(true);
|
|
vi.mocked(mockContext.services.config!.getApprovedPlanPath).mockReturnValue(
|
|
undefined,
|
|
);
|
|
|
|
if (!planCommand.action) throw new Error('Action missing');
|
|
await planCommand.action(mockContext, '');
|
|
|
|
expect(mockContext.services.config!.setApprovalMode).toHaveBeenCalledWith(
|
|
ApprovalMode.PLAN,
|
|
);
|
|
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
|
|
'info',
|
|
'Switched to Plan Mode.',
|
|
);
|
|
});
|
|
|
|
it('should display the approved plan from config', async () => {
|
|
const mockPlanPath = '/mock/plans/dir/approved-plan.md';
|
|
vi.mocked(mockContext.services.config!.isPlanEnabled).mockReturnValue(true);
|
|
vi.mocked(mockContext.services.config!.getApprovedPlanPath).mockReturnValue(
|
|
mockPlanPath,
|
|
);
|
|
vi.mocked(processSingleFileContent).mockResolvedValue({
|
|
llmContent: '# Approved Plan Content',
|
|
returnDisplay: '# Approved Plan Content',
|
|
} as ProcessedFileReadResult);
|
|
|
|
if (!planCommand.action) throw new Error('Action missing');
|
|
await planCommand.action(mockContext, '');
|
|
|
|
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
|
|
'info',
|
|
'Approved Plan: approved-plan.md',
|
|
);
|
|
expect(mockContext.ui.addItem).toHaveBeenCalledWith({
|
|
type: MessageType.GEMINI,
|
|
text: '# Approved Plan Content',
|
|
});
|
|
});
|
|
});
|