diff options
| author | christine betts <[email protected]> | 2025-07-09 21:16:42 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-09 21:16:42 +0000 |
| commit | da50a1eefbd0751aaf137882595d500e6b6b4179 (patch) | |
| tree | 4a07182ca01f20074a5544db5caf5a198cabae6c /packages/cli/src/ui | |
| parent | 063481faa4b1c86868689580ff0fbd8cb04141e3 (diff) | |
Add system-wide settings config for administrators (#3498)
Co-authored-by: Jack Wotherspoon <[email protected]>
Diffstat (limited to 'packages/cli/src/ui')
| -rw-r--r-- | packages/cli/src/ui/App.test.tsx | 62 | ||||
| -rw-r--r-- | packages/cli/src/ui/components/AuthDialog.test.tsx | 14 | ||||
| -rw-r--r-- | packages/cli/src/ui/components/ThemeDialog.tsx | 20 |
3 files changed, 73 insertions, 23 deletions
diff --git a/packages/cli/src/ui/App.test.tsx b/packages/cli/src/ui/App.test.tsx index 8390dac1..22547ae1 100644 --- a/packages/cli/src/ui/App.test.tsx +++ b/packages/cli/src/ui/App.test.tsx @@ -185,19 +185,30 @@ describe('App UI', () => { let currentUnmount: (() => void) | undefined; const createMockSettings = ( - settings: Partial<Settings> = {}, + settings: { + system?: Partial<Settings>; + user?: Partial<Settings>; + workspace?: Partial<Settings>; + } = {}, ): LoadedSettings => { + const systemSettingsFile: SettingsFile = { + path: '/system/settings.json', + settings: settings.system || {}, + }; const userSettingsFile: SettingsFile = { path: '/user/settings.json', - settings: {}, + settings: settings.user || {}, }; const workspaceSettingsFile: SettingsFile = { path: '/workspace/.gemini/settings.json', - settings: { - ...settings, - }, + settings: settings.workspace || {}, }; - return new LoadedSettings(userSettingsFile, workspaceSettingsFile, []); + return new LoadedSettings( + systemSettingsFile, + userSettingsFile, + workspaceSettingsFile, + [], + ); }; beforeEach(() => { @@ -222,7 +233,7 @@ describe('App UI', () => { mockConfig.getShowMemoryUsage.mockReturnValue(false); // Default for most tests // Ensure a theme is set so the theme dialog does not appear. - mockSettings = createMockSettings({ theme: 'Default' }); + mockSettings = createMockSettings({ workspace: { theme: 'Default' } }); }); afterEach(() => { @@ -268,8 +279,7 @@ describe('App UI', () => { it('should display custom contextFileName in footer when set and count is 1', async () => { mockSettings = createMockSettings({ - contextFileName: 'AGENTS.md', - theme: 'Default', + workspace: { contextFileName: 'AGENTS.md', theme: 'Default' }, }); mockConfig.getGeminiMdFileCount.mockReturnValue(1); mockConfig.getDebugMode.mockReturnValue(false); @@ -288,8 +298,10 @@ describe('App UI', () => { it('should display a generic message when multiple context files with different names are provided', async () => { mockSettings = createMockSettings({ - contextFileName: ['AGENTS.md', 'CONTEXT.md'], - theme: 'Default', + workspace: { + contextFileName: ['AGENTS.md', 'CONTEXT.md'], + theme: 'Default', + }, }); mockConfig.getGeminiMdFileCount.mockReturnValue(2); mockConfig.getDebugMode.mockReturnValue(false); @@ -308,8 +320,7 @@ describe('App UI', () => { it('should display custom contextFileName with plural when set and count is > 1', async () => { mockSettings = createMockSettings({ - contextFileName: 'MY_NOTES.TXT', - theme: 'Default', + workspace: { contextFileName: 'MY_NOTES.TXT', theme: 'Default' }, }); mockConfig.getGeminiMdFileCount.mockReturnValue(3); mockConfig.getDebugMode.mockReturnValue(false); @@ -328,8 +339,7 @@ describe('App UI', () => { it('should not display context file message if count is 0, even if contextFileName is set', async () => { mockSettings = createMockSettings({ - contextFileName: 'ANY_FILE.MD', - theme: 'Default', + workspace: { contextFileName: 'ANY_FILE.MD', theme: 'Default' }, }); mockConfig.getGeminiMdFileCount.mockReturnValue(0); mockConfig.getDebugMode.mockReturnValue(false); @@ -399,7 +409,9 @@ describe('App UI', () => { it('should not display Tips component when hideTips is true', async () => { mockSettings = createMockSettings({ - hideTips: true, + workspace: { + hideTips: true, + }, }); const { unmount } = render( @@ -413,6 +425,24 @@ describe('App UI', () => { expect(vi.mocked(Tips)).not.toHaveBeenCalled(); }); + it('should show tips if system says show, but workspace and user settings say hide', async () => { + mockSettings = createMockSettings({ + system: { hideTips: false }, + user: { hideTips: true }, + workspace: { hideTips: true }, + }); + + const { unmount } = render( + <App + config={mockConfig as unknown as ServerConfig} + settings={mockSettings} + />, + ); + currentUnmount = unmount; + await Promise.resolve(); + expect(vi.mocked(Tips)).toHaveBeenCalled(); + }); + describe('when no theme is set', () => { let originalNoColor: string | undefined; diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx index 60a8a930..d9f1bd2c 100644 --- a/packages/cli/src/ui/components/AuthDialog.test.tsx +++ b/packages/cli/src/ui/components/AuthDialog.test.tsx @@ -30,6 +30,10 @@ describe('AuthDialog', () => { const settings: LoadedSettings = new LoadedSettings( { + settings: {}, + path: '', + }, + { settings: { selectedAuthType: AuthType.USE_GEMINI, }, @@ -87,6 +91,12 @@ describe('AuthDialog', () => { path: '', }, { + settings: { + selectedAuthType: undefined, + }, + path: '', + }, + { settings: {}, path: '', }, @@ -148,6 +158,10 @@ describe('AuthDialog', () => { const onSelect = vi.fn(); const settings: LoadedSettings = new LoadedSettings( { + settings: {}, + path: '', + }, + { settings: { selectedAuthType: AuthType.USE_GEMINI, }, diff --git a/packages/cli/src/ui/components/ThemeDialog.tsx b/packages/cli/src/ui/components/ThemeDialog.tsx index 9351d5a1..ba49f8e3 100644 --- a/packages/cli/src/ui/components/ThemeDialog.tsx +++ b/packages/cli/src/ui/components/ThemeDialog.tsx @@ -57,6 +57,7 @@ export function ThemeDialog({ const scopeItems = [ { label: 'User Settings', value: SettingScope.User }, { label: 'Workspace Settings', value: SettingScope.Workspace }, + { label: 'System Settings', value: SettingScope.System }, ]; const handleThemeSelect = (themeName: string) => { @@ -86,16 +87,21 @@ export function ThemeDialog({ } }); + const otherScopes = Object.values(SettingScope).filter( + (scope) => scope !== selectedScope, + ); + + const modifiedInOtherScopes = otherScopes.filter( + (scope) => settings.forScope(scope).settings.theme !== undefined, + ); + let otherScopeModifiedMessage = ''; - const otherScope = - selectedScope === SettingScope.User - ? SettingScope.Workspace - : SettingScope.User; - if (settings.forScope(otherScope).settings.theme !== undefined) { + if (modifiedInOtherScopes.length > 0) { + const modifiedScopesStr = modifiedInOtherScopes.join(', '); otherScopeModifiedMessage = settings.forScope(selectedScope).settings.theme !== undefined - ? `(Also modified in ${otherScope})` - : `(Modified in ${otherScope})`; + ? `(Also modified in ${modifiedScopesStr})` + : `(Modified in ${modifiedScopesStr})`; } // Constants for calculating preview pane layout. |
