mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-14 16:10:59 -07:00
119 lines
3.7 KiB
TypeScript
119 lines
3.7 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { policiesCommand } from './policiesCommand.js';
|
|
import { CommandKind } from './types.js';
|
|
import { MessageType } from '../types.js';
|
|
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
|
|
import { type Config, PolicyDecision } from '@google/gemini-cli-core';
|
|
|
|
describe('policiesCommand', () => {
|
|
let mockContext: ReturnType<typeof createMockCommandContext>;
|
|
|
|
beforeEach(() => {
|
|
mockContext = createMockCommandContext();
|
|
});
|
|
|
|
it('should have correct command definition', () => {
|
|
expect(policiesCommand.name).toBe('policies');
|
|
expect(policiesCommand.description).toBe('Manage policies');
|
|
expect(policiesCommand.kind).toBe(CommandKind.BUILT_IN);
|
|
expect(policiesCommand.subCommands).toHaveLength(1);
|
|
expect(policiesCommand.subCommands![0].name).toBe('list');
|
|
});
|
|
|
|
describe('list subcommand', () => {
|
|
it('should show error if config is missing', async () => {
|
|
mockContext.services.config = null;
|
|
const listCommand = policiesCommand.subCommands![0];
|
|
|
|
await listCommand.action!(mockContext, '');
|
|
|
|
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: MessageType.ERROR,
|
|
text: 'Error: Config not available.',
|
|
}),
|
|
expect.any(Number),
|
|
);
|
|
});
|
|
|
|
it('should show message when no policies are active', async () => {
|
|
const mockPolicyEngine = {
|
|
getRules: vi.fn().mockReturnValue([]),
|
|
};
|
|
mockContext.services.config = {
|
|
getPolicyEngine: vi.fn().mockReturnValue(mockPolicyEngine),
|
|
} as unknown as Config;
|
|
|
|
const listCommand = policiesCommand.subCommands![0];
|
|
await listCommand.action!(mockContext, '');
|
|
|
|
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: MessageType.INFO,
|
|
text: 'No active policies.',
|
|
}),
|
|
expect.any(Number),
|
|
);
|
|
});
|
|
|
|
it('should list policies grouped by mode', async () => {
|
|
const mockRules = [
|
|
{
|
|
decision: PolicyDecision.DENY,
|
|
toolName: 'dangerousTool',
|
|
priority: 10,
|
|
},
|
|
{
|
|
decision: PolicyDecision.ALLOW,
|
|
argsPattern: /safe/,
|
|
source: 'test.toml',
|
|
},
|
|
{
|
|
decision: PolicyDecision.ASK_USER,
|
|
},
|
|
];
|
|
const mockPolicyEngine = {
|
|
getRules: vi.fn().mockReturnValue(mockRules),
|
|
};
|
|
mockContext.services.config = {
|
|
getPolicyEngine: vi.fn().mockReturnValue(mockPolicyEngine),
|
|
} as unknown as Config;
|
|
|
|
const listCommand = policiesCommand.subCommands![0];
|
|
await listCommand.action!(mockContext, '');
|
|
|
|
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
type: MessageType.INFO,
|
|
text: expect.stringContaining('**Active Policies**'),
|
|
}),
|
|
expect.any(Number),
|
|
);
|
|
|
|
const call = vi.mocked(mockContext.ui.addItem).mock.calls[0];
|
|
const content = (call[0] as { text: string }).text;
|
|
|
|
expect(content).toContain('### Normal Mode Policies');
|
|
expect(content).toContain(
|
|
'### Auto Edit Mode Policies (combined with normal mode policies)',
|
|
);
|
|
expect(content).toContain(
|
|
'### Yolo Mode Policies (combined with normal mode policies)',
|
|
);
|
|
expect(content).toContain(
|
|
'**DENY** tool: `dangerousTool` [Priority: 10]',
|
|
);
|
|
expect(content).toContain(
|
|
'**ALLOW** all tools (args match: `safe`) [Source: test.toml]',
|
|
);
|
|
expect(content).toContain('**ASK_USER** all tools');
|
|
});
|
|
});
|
|
});
|