mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-13 23:51:16 -07:00
237 lines
7.6 KiB
TypeScript
237 lines
7.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
import type { Mock } from 'vitest';
|
|
import { renderWithProviders } from '../../test-utils/render.js';
|
|
import { waitFor } from '../../test-utils/async.js';
|
|
import { PermissionsModifyTrustDialog } from './PermissionsModifyTrustDialog.js';
|
|
import { TrustLevel } from '../../config/trustedFolders.js';
|
|
import { act } from 'react';
|
|
import * as processUtils from '../../utils/processUtils.js';
|
|
import { usePermissionsModifyTrust } from '../hooks/usePermissionsModifyTrust.js';
|
|
|
|
// Hoist mocks for dependencies of the usePermissionsModifyTrust hook
|
|
const mockedCwd = vi.hoisted(() => vi.fn());
|
|
const mockedLoadTrustedFolders = vi.hoisted(() => vi.fn());
|
|
const mockedIsWorkspaceTrusted = vi.hoisted(() => vi.fn());
|
|
|
|
// Mock the modules themselves
|
|
vi.mock('node:process', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('node:process')>();
|
|
return {
|
|
...actual,
|
|
cwd: mockedCwd,
|
|
};
|
|
});
|
|
|
|
vi.mock('../../config/trustedFolders.js', () => ({
|
|
loadTrustedFolders: mockedLoadTrustedFolders,
|
|
isWorkspaceTrusted: mockedIsWorkspaceTrusted,
|
|
TrustLevel: {
|
|
TRUST_FOLDER: 'TRUST_FOLDER',
|
|
TRUST_PARENT: 'TRUST_PARENT',
|
|
DO_NOT_TRUST: 'DO_NOT_TRUST',
|
|
},
|
|
}));
|
|
|
|
vi.mock('../hooks/usePermissionsModifyTrust.js');
|
|
|
|
describe('PermissionsModifyTrustDialog', () => {
|
|
let mockUpdateTrustLevel: Mock;
|
|
let mockCommitTrustLevelChange: Mock;
|
|
|
|
beforeEach(() => {
|
|
mockedCwd.mockReturnValue('/test/dir');
|
|
mockUpdateTrustLevel = vi.fn();
|
|
mockCommitTrustLevelChange = vi.fn();
|
|
vi.mocked(usePermissionsModifyTrust).mockReturnValue({
|
|
cwd: '/test/dir',
|
|
currentTrustLevel: TrustLevel.DO_NOT_TRUST,
|
|
isInheritedTrustFromParent: false,
|
|
isInheritedTrustFromIde: false,
|
|
needsRestart: false,
|
|
updateTrustLevel: mockUpdateTrustLevel,
|
|
commitTrustLevelChange: mockCommitTrustLevelChange,
|
|
isFolderTrustEnabled: true,
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
it('should render the main dialog with current trust level', async () => {
|
|
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => {
|
|
expect(lastFrame()).toContain('Modify Trust Level');
|
|
expect(lastFrame()).toContain('Folder: /test/dir');
|
|
expect(lastFrame()).toContain('Current Level: DO_NOT_TRUST');
|
|
});
|
|
unmount();
|
|
});
|
|
|
|
it('should display the inherited trust note from parent', async () => {
|
|
vi.mocked(usePermissionsModifyTrust).mockReturnValue({
|
|
cwd: '/test/dir',
|
|
currentTrustLevel: TrustLevel.DO_NOT_TRUST,
|
|
isInheritedTrustFromParent: true,
|
|
isInheritedTrustFromIde: false,
|
|
needsRestart: false,
|
|
updateTrustLevel: mockUpdateTrustLevel,
|
|
commitTrustLevelChange: mockCommitTrustLevelChange,
|
|
isFolderTrustEnabled: true,
|
|
});
|
|
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => {
|
|
expect(lastFrame()).toContain(
|
|
'Note: This folder behaves as a trusted folder because one of the parent folders is trusted.',
|
|
);
|
|
});
|
|
unmount();
|
|
});
|
|
|
|
it('should display the inherited trust note from IDE', async () => {
|
|
vi.mocked(usePermissionsModifyTrust).mockReturnValue({
|
|
cwd: '/test/dir',
|
|
currentTrustLevel: TrustLevel.DO_NOT_TRUST,
|
|
isInheritedTrustFromParent: false,
|
|
isInheritedTrustFromIde: true,
|
|
needsRestart: false,
|
|
updateTrustLevel: mockUpdateTrustLevel,
|
|
commitTrustLevelChange: mockCommitTrustLevelChange,
|
|
isFolderTrustEnabled: true,
|
|
});
|
|
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => {
|
|
expect(lastFrame()).toContain(
|
|
'Note: This folder behaves as a trusted folder because the connected IDE workspace is trusted.',
|
|
);
|
|
});
|
|
unmount();
|
|
});
|
|
|
|
it('should render the labels with folder names', async () => {
|
|
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={vi.fn()} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => {
|
|
expect(lastFrame()).toContain('Trust this folder (dir)');
|
|
expect(lastFrame()).toContain('Trust parent folder (test)');
|
|
});
|
|
unmount();
|
|
});
|
|
|
|
it('should call onExit when escape is pressed', async () => {
|
|
const onExit = vi.fn();
|
|
const { stdin, lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => expect(lastFrame()).not.toContain('Loading...'));
|
|
|
|
await act(async () => {
|
|
stdin.write('\u001b[27u'); // Kitty escape key
|
|
});
|
|
// Escape key has a 50ms timeout in KeypressContext, so we need to wrap waitUntilReady in act
|
|
await act(async () => {
|
|
await waitUntilReady();
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(onExit).toHaveBeenCalled();
|
|
});
|
|
unmount();
|
|
});
|
|
|
|
it('should commit and restart `r` keypress', async () => {
|
|
const mockRelaunchApp = vi
|
|
.spyOn(processUtils, 'relaunchApp')
|
|
.mockResolvedValue(undefined);
|
|
mockCommitTrustLevelChange.mockReturnValue(true);
|
|
vi.mocked(usePermissionsModifyTrust).mockReturnValue({
|
|
cwd: '/test/dir',
|
|
currentTrustLevel: TrustLevel.DO_NOT_TRUST,
|
|
isInheritedTrustFromParent: false,
|
|
isInheritedTrustFromIde: false,
|
|
needsRestart: true,
|
|
updateTrustLevel: mockUpdateTrustLevel,
|
|
commitTrustLevelChange: mockCommitTrustLevelChange,
|
|
isFolderTrustEnabled: true,
|
|
});
|
|
|
|
const onExit = vi.fn();
|
|
const { stdin, lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => expect(lastFrame()).not.toContain('Loading...'));
|
|
|
|
await act(async () => {
|
|
stdin.write('r'); // Press 'r' to restart
|
|
});
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => {
|
|
expect(mockCommitTrustLevelChange).toHaveBeenCalled();
|
|
expect(mockRelaunchApp).toHaveBeenCalled();
|
|
});
|
|
|
|
mockRelaunchApp.mockRestore();
|
|
unmount();
|
|
});
|
|
|
|
it('should not commit when escape is pressed during restart prompt', async () => {
|
|
vi.mocked(usePermissionsModifyTrust).mockReturnValue({
|
|
cwd: '/test/dir',
|
|
currentTrustLevel: TrustLevel.DO_NOT_TRUST,
|
|
isInheritedTrustFromParent: false,
|
|
isInheritedTrustFromIde: false,
|
|
needsRestart: true,
|
|
updateTrustLevel: mockUpdateTrustLevel,
|
|
commitTrustLevelChange: mockCommitTrustLevelChange,
|
|
isFolderTrustEnabled: true,
|
|
});
|
|
|
|
const onExit = vi.fn();
|
|
const { stdin, lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
|
<PermissionsModifyTrustDialog onExit={onExit} addItem={vi.fn()} />,
|
|
);
|
|
await waitUntilReady();
|
|
|
|
await waitFor(() => expect(lastFrame()).not.toContain('Loading...'));
|
|
|
|
await act(async () => {
|
|
stdin.write('\u001b[27u'); // Press kitty escape key
|
|
});
|
|
await act(async () => {
|
|
await waitUntilReady();
|
|
});
|
|
|
|
await waitFor(() => {
|
|
expect(mockCommitTrustLevelChange).not.toHaveBeenCalled();
|
|
expect(onExit).toHaveBeenCalled();
|
|
});
|
|
unmount();
|
|
});
|
|
});
|