Download packages/a2a-server/src/config/settings.test.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 7.27 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/a2a-server/src/config/settings.test.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/a2a-server/src/config/settings.test.ts
-
curl -L -o settings.test.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/a2a-server/src/config/settings.test.ts
7.27 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; | |
| import * as fs from 'node:fs'; | |
| import * as path from 'node:path'; | |
| import * as os from 'node:os'; | |
| import { loadSettings, USER_SETTINGS_PATH } from './settings.js'; | |
| import { debugLogger, checkPathTrust } from '@google/gemini-cli-core'; | |
| const mocks = vi.hoisted(() => { | |
| const suffix = Math.random().toString(36).slice(2); | |
| return { | |
| suffix, | |
| }; | |
| }); | |
| vi.mock('node:os', async (importOriginal) => { | |
| const actual = await importOriginal<typeof import('node:os')>(); | |
| const path = await import('node:path'); | |
| return { | |
| ...actual, | |
| homedir: () => path.join(actual.tmpdir(), `gemini-home-${mocks.suffix}`), | |
| }; | |
| }); | |
| vi.mock('@google/gemini-cli-core', async (importOriginal) => { | |
| const actual = | |
| await importOriginal<typeof import('@google/gemini-cli-core')>(); | |
| const path = await import('node:path'); | |
| const os = await import('node:os'); | |
| return { | |
| ...actual, | |
| GEMINI_DIR: '.gemini', | |
| debugLogger: { | |
| error: vi.fn(), | |
| }, | |
| getErrorMessage: (error: unknown) => String(error), | |
| homedir: () => path.join(os.tmpdir(), `gemini-home-${mocks.suffix}`), | |
| checkPathTrust: vi.fn(() => ({ isTrusted: false })), | |
| isHeadlessMode: vi.fn(() => true), | |
| }; | |
| }); | |
| describe('loadSettings', () => { | |
| const mockHomeDir = path.join(os.tmpdir(), `gemini-home-${mocks.suffix}`); | |
| const mockWorkspaceDir = path.join( | |
| os.tmpdir(), | |
| `gemini-workspace-${mocks.suffix}`, | |
| ); | |
| const mockGeminiHomeDir = path.join(mockHomeDir, '.gemini'); | |
| const mockGeminiWorkspaceDir = path.join(mockWorkspaceDir, '.gemini'); | |
| beforeEach(() => { | |
| vi.clearAllMocks(); | |
| // Create the directories using the real fs | |
| if (!fs.existsSync(mockGeminiHomeDir)) { | |
| fs.mkdirSync(mockGeminiHomeDir, { recursive: true }); | |
| } | |
| if (!fs.existsSync(mockGeminiWorkspaceDir)) { | |
| fs.mkdirSync(mockGeminiWorkspaceDir, { recursive: true }); | |
| } | |
| // Clean up settings files before each test | |
| if (fs.existsSync(USER_SETTINGS_PATH)) { | |
| fs.rmSync(USER_SETTINGS_PATH); | |
| } | |
| const workspaceSettingsPath = path.join( | |
| mockGeminiWorkspaceDir, | |
| 'settings.json', | |
| ); | |
| if (fs.existsSync(workspaceSettingsPath)) { | |
| fs.rmSync(workspaceSettingsPath); | |
| } | |
| }); | |
| afterEach(() => { | |
| try { | |
| if (fs.existsSync(mockHomeDir)) { | |
| fs.rmSync(mockHomeDir, { recursive: true, force: true }); | |
| } | |
| if (fs.existsSync(mockWorkspaceDir)) { | |
| fs.rmSync(mockWorkspaceDir, { recursive: true, force: true }); | |
| } | |
| } catch (e) { | |
| debugLogger.error('Failed to cleanup temp dirs', e); | |
| } | |
| vi.restoreAllMocks(); | |
| }); | |
| it('should load other top-level settings correctly', () => { | |
| const settings = { | |
| showMemoryUsage: true, | |
| tools: { | |
| core: ['tool1', 'tool2'], | |
| }, | |
| mcpServers: { | |
| server1: { | |
| command: 'cmd', | |
| args: ['arg'], | |
| }, | |
| }, | |
| fileFiltering: { | |
| respectGitIgnore: true, | |
| }, | |
| }; | |
| fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings)); | |
| const result = loadSettings(mockWorkspaceDir); | |
| expect(result.showMemoryUsage).toBe(true); | |
| expect(result.tools?.core).toEqual(['tool1', 'tool2']); | |
| expect(result.mcpServers).toHaveProperty('server1'); | |
| expect(result.fileFiltering?.respectGitIgnore).toBe(true); | |
| }); | |
| it('should load experimental settings correctly', () => { | |
| const settings = { | |
| experimental: { | |
| enableAgents: true, | |
| }, | |
| }; | |
| fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(settings)); | |
| const result = loadSettings(mockWorkspaceDir); | |
| expect(result.experimental?.enableAgents).toBe(true); | |
| }); | |
| it('should overwrite top-level settings from workspace (shallow merge)', () => { | |
| const userSettings = { | |
| showMemoryUsage: false, | |
| fileFiltering: { | |
| respectGitIgnore: true, | |
| enableRecursiveFileSearch: true, | |
| }, | |
| }; | |
| fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings)); | |
| const workspaceSettings = { | |
| showMemoryUsage: true, | |
| fileFiltering: { | |
| respectGitIgnore: false, | |
| }, | |
| }; | |
| const workspaceSettingsPath = path.join( | |
| mockGeminiWorkspaceDir, | |
| 'settings.json', | |
| ); | |
| fs.writeFileSync(workspaceSettingsPath, JSON.stringify(workspaceSettings)); | |
| const result = loadSettings(mockWorkspaceDir, true); | |
| // Primitive value overwritten | |
| expect(result.showMemoryUsage).toBe(true); | |
| // Object value completely replaced (shallow merge behavior) | |
| expect(result.fileFiltering?.respectGitIgnore).toBe(false); | |
| expect(result.fileFiltering?.enableRecursiveFileSearch).toBeUndefined(); | |
| }); | |
| describe('security', () => { | |
| it('should NOT load workspace settings if workspace is NOT trusted', () => { | |
| const userSettings = { showMemoryUsage: false }; | |
| fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings)); | |
| const workspaceSettings = { showMemoryUsage: true }; | |
| const workspaceSettingsPath = path.join( | |
| mockGeminiWorkspaceDir, | |
| 'settings.json', | |
| ); | |
| fs.writeFileSync( | |
| workspaceSettingsPath, | |
| JSON.stringify(workspaceSettings), | |
| ); | |
| // checkPathTrust is mocked to return isTrusted: false by default | |
| const result = loadSettings(mockWorkspaceDir); | |
| expect(result.showMemoryUsage).toBe(false); | |
| }); | |
| it('should load workspace settings if workspace IS trusted', () => { | |
| vi.mocked(checkPathTrust).mockReturnValueOnce({ | |
| isTrusted: true, | |
| source: 'file', | |
| }); | |
| const userSettings = { showMemoryUsage: false }; | |
| fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings)); | |
| const workspaceSettings = { showMemoryUsage: true }; | |
| const workspaceSettingsPath = path.join( | |
| mockGeminiWorkspaceDir, | |
| 'settings.json', | |
| ); | |
| fs.writeFileSync( | |
| workspaceSettingsPath, | |
| JSON.stringify(workspaceSettings), | |
| ); | |
| const result = loadSettings(mockWorkspaceDir); | |
| expect(result.showMemoryUsage).toBe(true); | |
| }); | |
| it('should NOT allow workspace settings to override adminPolicyPaths or policyPaths even if trusted', () => { | |
| vi.mocked(checkPathTrust).mockReturnValueOnce({ | |
| isTrusted: true, | |
| source: 'file', | |
| }); | |
| const userSettings = { | |
| adminPolicyPaths: ['/trusted/admin'], | |
| policyPaths: ['/trusted/user'], | |
| }; | |
| fs.writeFileSync(USER_SETTINGS_PATH, JSON.stringify(userSettings)); | |
| const workspaceSettings = { | |
| adminPolicyPaths: ['./malicious/admin'], | |
| policyPaths: ['./malicious/user'], | |
| showMemoryUsage: true, | |
| }; | |
| const workspaceSettingsPath = path.join( | |
| mockGeminiWorkspaceDir, | |
| 'settings.json', | |
| ); | |
| fs.writeFileSync( | |
| workspaceSettingsPath, | |
| JSON.stringify(workspaceSettings), | |
| ); | |
| const result = loadSettings(mockWorkspaceDir); | |
| expect(result.showMemoryUsage).toBe(true); | |
| expect(result.adminPolicyPaths).toEqual(['/trusted/admin']); | |
| expect(result.policyPaths).toEqual(['/trusted/user']); | |
| }); | |
| }); | |
| }); | |