Files
gemini-cli/packages/cli/src/ui/commands/policiesCommand.test.ts
2026-01-23 00:36:44 +00:00

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');
});
});
});