mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-13 15:40:57 -07:00
142 lines
3.7 KiB
TypeScript
142 lines
3.7 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
import { act } from 'react';
|
|
import { renderWithProviders } from '../../test-utils/render.js';
|
|
import { waitFor } from '../../test-utils/async.js';
|
|
import { PolicyUpdateDialog } from './PolicyUpdateDialog.js';
|
|
import {
|
|
type Config,
|
|
type PolicyUpdateConfirmationRequest,
|
|
PolicyIntegrityManager,
|
|
} from '@google/gemini-cli-core';
|
|
|
|
const { mockAcceptIntegrity } = vi.hoisted(() => ({
|
|
mockAcceptIntegrity: vi.fn(),
|
|
}));
|
|
|
|
// Mock PolicyIntegrityManager
|
|
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|
const original =
|
|
await importOriginal<typeof import('@google/gemini-cli-core')>();
|
|
return {
|
|
...original,
|
|
PolicyIntegrityManager: vi.fn().mockImplementation(() => ({
|
|
acceptIntegrity: mockAcceptIntegrity,
|
|
checkIntegrity: vi.fn(),
|
|
})),
|
|
};
|
|
});
|
|
|
|
describe('PolicyUpdateDialog', () => {
|
|
let mockConfig: Config;
|
|
let mockRequest: PolicyUpdateConfirmationRequest;
|
|
let onClose: () => void;
|
|
|
|
beforeEach(() => {
|
|
mockConfig = {
|
|
loadWorkspacePolicies: vi.fn().mockResolvedValue(undefined),
|
|
} as unknown as Config;
|
|
|
|
mockRequest = {
|
|
scope: 'workspace',
|
|
identifier: '/test/workspace/.gemini/policies',
|
|
policyDir: '/test/workspace/.gemini/policies',
|
|
newHash: 'test-hash',
|
|
} as PolicyUpdateConfirmationRequest;
|
|
|
|
onClose = vi.fn();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('renders correctly and matches snapshot', async () => {
|
|
const { lastFrame, waitUntilReady } = renderWithProviders(
|
|
<PolicyUpdateDialog
|
|
config={mockConfig}
|
|
request={mockRequest}
|
|
onClose={onClose}
|
|
/>,
|
|
);
|
|
|
|
await waitUntilReady();
|
|
const output = lastFrame();
|
|
expect(output).toMatchSnapshot();
|
|
expect(output).toContain('New or changed workspace policies detected');
|
|
expect(output).toContain('Location: /test/workspace/.gemini/policies');
|
|
expect(output).toContain('Accept and Load');
|
|
expect(output).toContain('Ignore');
|
|
});
|
|
|
|
it('handles ACCEPT correctly', async () => {
|
|
const { stdin } = renderWithProviders(
|
|
<PolicyUpdateDialog
|
|
config={mockConfig}
|
|
request={mockRequest}
|
|
onClose={onClose}
|
|
/>,
|
|
);
|
|
|
|
// Accept is the first option, so pressing enter should select it
|
|
await act(async () => {
|
|
stdin.write('\r');
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(PolicyIntegrityManager).toHaveBeenCalled();
|
|
expect(mockConfig.loadWorkspacePolicies).toHaveBeenCalledWith(
|
|
mockRequest.policyDir,
|
|
);
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('handles IGNORE correctly', async () => {
|
|
const { stdin } = renderWithProviders(
|
|
<PolicyUpdateDialog
|
|
config={mockConfig}
|
|
request={mockRequest}
|
|
onClose={onClose}
|
|
/>,
|
|
);
|
|
|
|
// Move down to Ignore option
|
|
await act(async () => {
|
|
stdin.write('\x1B[B'); // Down arrow
|
|
});
|
|
await act(async () => {
|
|
stdin.write('\r'); // Enter
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(PolicyIntegrityManager).not.toHaveBeenCalled();
|
|
expect(mockConfig.loadWorkspacePolicies).not.toHaveBeenCalled();
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('calls onClose when Escape key is pressed', async () => {
|
|
const { stdin } = renderWithProviders(
|
|
<PolicyUpdateDialog
|
|
config={mockConfig}
|
|
request={mockRequest}
|
|
onClose={onClose}
|
|
/>,
|
|
);
|
|
|
|
await act(async () => {
|
|
stdin.write('\x1B'); // Escape key (matches Command.ESCAPE default)
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|