diff options
| author | shrutip90 <[email protected]> | 2025-08-14 11:15:48 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-14 18:15:48 +0000 |
| commit | 69c55827239b5c937c177eef4b4fbcc2758ef23e (patch) | |
| tree | f2dc2f1a55e64cd9a235bcf0e3d9caaa7f552b7c /packages/cli/src/ui/hooks | |
| parent | 69d666cfafe97e49a6cacb306df9a737d4aa9f20 (diff) | |
feat: Show untrusted status in the Footer (#6210)
Co-authored-by: Jacob Richman <[email protected]>
Diffstat (limited to 'packages/cli/src/ui/hooks')
| -rw-r--r-- | packages/cli/src/ui/hooks/useFolderTrust.test.ts | 44 | ||||
| -rw-r--r-- | packages/cli/src/ui/hooks/useFolderTrust.ts | 82 |
2 files changed, 82 insertions, 44 deletions
diff --git a/packages/cli/src/ui/hooks/useFolderTrust.test.ts b/packages/cli/src/ui/hooks/useFolderTrust.test.ts index e565ab05..3103cab4 100644 --- a/packages/cli/src/ui/hooks/useFolderTrust.test.ts +++ b/packages/cli/src/ui/hooks/useFolderTrust.test.ts @@ -7,7 +7,6 @@ import { vi } from 'vitest'; import { renderHook, act } from '@testing-library/react'; import { useFolderTrust } from './useFolderTrust.js'; -import { type Config } from '@google/gemini-cli-core'; import { LoadedSettings } from '../../config/settings.js'; import { FolderTrustChoice } from '../components/FolderTrustDialog.js'; import { @@ -25,9 +24,10 @@ vi.mock('process', () => ({ describe('useFolderTrust', () => { let mockSettings: LoadedSettings; - let mockConfig: Config; let mockTrustedFolders: LoadedTrustedFolders; let loadTrustedFoldersSpy: vi.SpyInstance; + let isWorkspaceTrustedSpy: vi.SpyInstance; + let onTrustChange: (isTrusted: boolean | undefined) => void; beforeEach(() => { mockSettings = { @@ -38,10 +38,6 @@ describe('useFolderTrust', () => { setValue: vi.fn(), } as unknown as LoadedSettings; - mockConfig = { - isTrustedFolder: vi.fn().mockReturnValue(undefined), - } as unknown as Config; - mockTrustedFolders = { setValue: vi.fn(), } as unknown as LoadedTrustedFolders; @@ -49,7 +45,9 @@ describe('useFolderTrust', () => { loadTrustedFoldersSpy = vi .spyOn(trustedFolders, 'loadTrustedFolders') .mockReturnValue(mockTrustedFolders); + isWorkspaceTrustedSpy = vi.spyOn(trustedFolders, 'isWorkspaceTrusted'); (process.cwd as vi.Mock).mockReturnValue('/test/path'); + onTrustChange = vi.fn(); }); afterEach(() => { @@ -57,34 +55,39 @@ describe('useFolderTrust', () => { }); it('should not open dialog when folder is already trusted', () => { - (mockConfig.isTrustedFolder as vi.Mock).mockReturnValue(true); + isWorkspaceTrustedSpy.mockReturnValue(true); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); expect(result.current.isFolderTrustDialogOpen).toBe(false); + expect(onTrustChange).toHaveBeenCalledWith(true); }); it('should not open dialog when folder is already untrusted', () => { - (mockConfig.isTrustedFolder as vi.Mock).mockReturnValue(false); + isWorkspaceTrustedSpy.mockReturnValue(false); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); expect(result.current.isFolderTrustDialogOpen).toBe(false); + expect(onTrustChange).toHaveBeenCalledWith(false); }); it('should open dialog when folder trust is undefined', () => { - (mockConfig.isTrustedFolder as vi.Mock).mockReturnValue(undefined); + isWorkspaceTrustedSpy.mockReturnValue(undefined); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); expect(result.current.isFolderTrustDialogOpen).toBe(true); + expect(onTrustChange).toHaveBeenCalledWith(undefined); }); it('should handle TRUST_FOLDER choice', () => { + isWorkspaceTrustedSpy.mockReturnValue(undefined); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); + isWorkspaceTrustedSpy.mockReturnValue(true); act(() => { result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_FOLDER); }); @@ -95,13 +98,16 @@ describe('useFolderTrust', () => { TrustLevel.TRUST_FOLDER, ); expect(result.current.isFolderTrustDialogOpen).toBe(false); + expect(onTrustChange).toHaveBeenLastCalledWith(true); }); it('should handle TRUST_PARENT choice', () => { + isWorkspaceTrustedSpy.mockReturnValue(undefined); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); + isWorkspaceTrustedSpy.mockReturnValue(true); act(() => { result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_PARENT); }); @@ -111,13 +117,16 @@ describe('useFolderTrust', () => { TrustLevel.TRUST_PARENT, ); expect(result.current.isFolderTrustDialogOpen).toBe(false); + expect(onTrustChange).toHaveBeenLastCalledWith(true); }); it('should handle DO_NOT_TRUST choice', () => { + isWorkspaceTrustedSpy.mockReturnValue(undefined); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); + isWorkspaceTrustedSpy.mockReturnValue(false); act(() => { result.current.handleFolderTrustSelect(FolderTrustChoice.DO_NOT_TRUST); }); @@ -127,11 +136,13 @@ describe('useFolderTrust', () => { TrustLevel.DO_NOT_TRUST, ); expect(result.current.isFolderTrustDialogOpen).toBe(false); + expect(onTrustChange).toHaveBeenLastCalledWith(false); }); it('should do nothing for default choice', () => { + isWorkspaceTrustedSpy.mockReturnValue(undefined); const { result } = renderHook(() => - useFolderTrust(mockSettings, mockConfig), + useFolderTrust(mockSettings, onTrustChange), ); act(() => { @@ -143,5 +154,6 @@ describe('useFolderTrust', () => { expect(mockTrustedFolders.setValue).not.toHaveBeenCalled(); expect(mockSettings.setValue).not.toHaveBeenCalled(); expect(result.current.isFolderTrustDialogOpen).toBe(true); + expect(onTrustChange).toHaveBeenCalledWith(undefined); }); }); diff --git a/packages/cli/src/ui/hooks/useFolderTrust.ts b/packages/cli/src/ui/hooks/useFolderTrust.ts index 6458d4aa..28b82b30 100644 --- a/packages/cli/src/ui/hooks/useFolderTrust.ts +++ b/packages/cli/src/ui/hooks/useFolderTrust.ts @@ -4,42 +4,68 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { useState, useCallback } from 'react'; -import { type Config } from '@google/gemini-cli-core'; -import { LoadedSettings } from '../../config/settings.js'; +import { useState, useCallback, useEffect } from 'react'; +import { Settings, LoadedSettings } from '../../config/settings.js'; import { FolderTrustChoice } from '../components/FolderTrustDialog.js'; -import { loadTrustedFolders, TrustLevel } from '../../config/trustedFolders.js'; +import { + loadTrustedFolders, + TrustLevel, + isWorkspaceTrusted, +} from '../../config/trustedFolders.js'; import * as process from 'process'; -export const useFolderTrust = (settings: LoadedSettings, config: Config) => { - const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState( - config.isTrustedFolder() === undefined, - ); +export const useFolderTrust = ( + settings: LoadedSettings, + onTrustChange: (isTrusted: boolean | undefined) => void, +) => { + const [isTrusted, setIsTrusted] = useState<boolean | undefined>(undefined); + const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState(false); + + const { folderTrust, folderTrustFeature } = settings.merged; + useEffect(() => { + const trusted = isWorkspaceTrusted({ + folderTrust, + folderTrustFeature, + } as Settings); + setIsTrusted(trusted); + setIsFolderTrustDialogOpen(trusted === undefined); + onTrustChange(trusted); + }, [onTrustChange, folderTrust, folderTrustFeature]); - const handleFolderTrustSelect = useCallback((choice: FolderTrustChoice) => { - const trustedFolders = loadTrustedFolders(); - const cwd = process.cwd(); - let trustLevel: TrustLevel; + const handleFolderTrustSelect = useCallback( + (choice: FolderTrustChoice) => { + const trustedFolders = loadTrustedFolders(); + const cwd = process.cwd(); + let trustLevel: TrustLevel; - switch (choice) { - case FolderTrustChoice.TRUST_FOLDER: - trustLevel = TrustLevel.TRUST_FOLDER; - break; - case FolderTrustChoice.TRUST_PARENT: - trustLevel = TrustLevel.TRUST_PARENT; - break; - case FolderTrustChoice.DO_NOT_TRUST: - trustLevel = TrustLevel.DO_NOT_TRUST; - break; - default: - return; - } + switch (choice) { + case FolderTrustChoice.TRUST_FOLDER: + trustLevel = TrustLevel.TRUST_FOLDER; + break; + case FolderTrustChoice.TRUST_PARENT: + trustLevel = TrustLevel.TRUST_PARENT; + break; + case FolderTrustChoice.DO_NOT_TRUST: + trustLevel = TrustLevel.DO_NOT_TRUST; + break; + default: + return; + } - trustedFolders.setValue(cwd, trustLevel); - setIsFolderTrustDialogOpen(false); - }, []); + trustedFolders.setValue(cwd, trustLevel); + const trusted = isWorkspaceTrusted({ + folderTrust, + folderTrustFeature, + } as Settings); + setIsTrusted(trusted); + setIsFolderTrustDialogOpen(false); + onTrustChange(trusted); + }, + [onTrustChange, folderTrust, folderTrustFeature], + ); return { + isTrusted, isFolderTrustDialogOpen, handleFolderTrustSelect, }; |
