mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-30 15:04:16 -07:00
Make default settings apply (#15354)
This commit is contained in:
@@ -35,6 +35,14 @@ vi.mock('./trustedFolders.js', () => ({
|
||||
.mockReturnValue({ isTrusted: true, source: 'file' }),
|
||||
}));
|
||||
|
||||
vi.mock('./settingsSchema.js', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('./settingsSchema.js')>();
|
||||
return {
|
||||
...actual,
|
||||
getSettingsSchema: vi.fn(actual.getSettingsSchema),
|
||||
};
|
||||
});
|
||||
|
||||
// NOW import everything else, including the (now effectively re-exported) settings.js
|
||||
import path, * as pathActual from 'node:path'; // Restored for MOCK_WORKSPACE_SETTINGS_PATH
|
||||
import {
|
||||
@@ -65,10 +73,16 @@ import {
|
||||
SettingScope,
|
||||
saveSettings,
|
||||
type SettingsFile,
|
||||
getDefaultsFromSchema,
|
||||
} from './settings.js';
|
||||
import { FatalConfigError, GEMINI_DIR } from '@google/gemini-cli-core';
|
||||
import { ExtensionManager } from './extension-manager.js';
|
||||
import { updateSettingsFilePreservingFormat } from '../utils/commentJson.js';
|
||||
import {
|
||||
getSettingsSchema,
|
||||
MergeStrategy,
|
||||
type SettingsSchema,
|
||||
} from './settingsSchema.js';
|
||||
|
||||
const MOCK_WORKSPACE_DIR = '/mock/workspace';
|
||||
// Use the (mocked) GEMINI_DIR for consistency
|
||||
@@ -149,14 +163,6 @@ describe('Settings Loading and Merging', () => {
|
||||
});
|
||||
|
||||
describe('loadSettings', () => {
|
||||
it('should load empty settings if no files exist', () => {
|
||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||
expect(settings.system.settings).toEqual({});
|
||||
expect(settings.user.settings).toEqual({});
|
||||
expect(settings.workspace.settings).toEqual({});
|
||||
expect(settings.merged).toEqual({});
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
scope: 'system',
|
||||
@@ -201,7 +207,7 @@ describe('Settings Loading and Merging', () => {
|
||||
expect(
|
||||
settings[scope as 'system' | 'user' | 'workspace'].settings,
|
||||
).toEqual(content);
|
||||
expect(settings.merged).toEqual(content);
|
||||
expect(settings.merged).toMatchObject(content);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -265,7 +271,7 @@ describe('Settings Loading and Merging', () => {
|
||||
expect(settings.system.settings).toEqual(systemSettingsContent);
|
||||
expect(settings.user.settings).toEqual(userSettingsContent);
|
||||
expect(settings.workspace.settings).toEqual(workspaceSettingsContent);
|
||||
expect(settings.merged).toEqual({
|
||||
expect(settings.merged).toMatchObject({
|
||||
ui: {
|
||||
theme: 'system-theme',
|
||||
},
|
||||
@@ -318,7 +324,7 @@ describe('Settings Loading and Merging', () => {
|
||||
|
||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||
|
||||
expect(settings.merged).toEqual({
|
||||
expect(settings.merged).toMatchObject({
|
||||
ui: {
|
||||
theme: 'legacy-dark',
|
||||
},
|
||||
@@ -443,10 +449,33 @@ describe('Settings Loading and Merging', () => {
|
||||
expect(settings.merged.advanced?.excludedEnvVars).toEqual(
|
||||
expect.arrayContaining(['USER_VAR', 'WORKSPACE_VAR']),
|
||||
);
|
||||
expect(settings.merged.advanced?.excludedEnvVars).toHaveLength(2);
|
||||
expect(settings.merged.advanced?.excludedEnvVars).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('should merge all settings files with the correct precedence', () => {
|
||||
// Mock schema to test defaults application
|
||||
const mockSchema = {
|
||||
ui: { type: 'object', default: {}, properties: {} },
|
||||
tools: { type: 'object', default: {}, properties: {} },
|
||||
context: {
|
||||
type: 'object',
|
||||
default: {},
|
||||
properties: {
|
||||
discoveryMaxDirs: { type: 'number', default: 200 },
|
||||
includeDirectories: {
|
||||
type: 'array',
|
||||
default: [],
|
||||
mergeStrategy: MergeStrategy.CONCAT,
|
||||
},
|
||||
},
|
||||
},
|
||||
mcpServers: { type: 'object', default: {} },
|
||||
};
|
||||
|
||||
(getSettingsSchema as Mock).mockReturnValue(
|
||||
mockSchema as unknown as SettingsSchema,
|
||||
);
|
||||
|
||||
(mockFsExistsSync as Mock).mockReturnValue(true);
|
||||
const systemDefaultsContent = {
|
||||
ui: {
|
||||
@@ -510,7 +539,7 @@ describe('Settings Loading and Merging', () => {
|
||||
expect(settings.workspace.settings).toEqual(workspaceSettingsContent);
|
||||
expect(settings.merged).toEqual({
|
||||
context: {
|
||||
fileName: 'WORKSPACE_CONTEXT.md',
|
||||
discoveryMaxDirs: 200,
|
||||
includeDirectories: [
|
||||
'/system/defaults/dir',
|
||||
'/user/dir1',
|
||||
@@ -518,14 +547,12 @@ describe('Settings Loading and Merging', () => {
|
||||
'/workspace/dir',
|
||||
'/system/dir',
|
||||
],
|
||||
fileName: 'WORKSPACE_CONTEXT.md',
|
||||
},
|
||||
mcpServers: {},
|
||||
ui: { theme: 'system-theme' },
|
||||
tools: { sandbox: false },
|
||||
telemetry: false,
|
||||
tools: {
|
||||
sandbox: false,
|
||||
},
|
||||
ui: {
|
||||
theme: 'system-theme',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -660,7 +687,7 @@ describe('Settings Loading and Merging', () => {
|
||||
},
|
||||
expected: {
|
||||
key: 'advanced.excludedEnvVars',
|
||||
value: ['DEBUG', 'NODE_ENV', 'CUSTOM_VAR'],
|
||||
value: ['DEBUG', 'DEBUG_MODE', 'NODE_ENV', 'CUSTOM_VAR'],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -671,7 +698,7 @@ describe('Settings Loading and Merging', () => {
|
||||
},
|
||||
expected: {
|
||||
key: 'advanced.excludedEnvVars',
|
||||
value: ['WORKSPACE_DEBUG', 'WORKSPACE_VAR'],
|
||||
value: ['DEBUG', 'DEBUG_MODE', 'WORKSPACE_DEBUG', 'WORKSPACE_VAR'],
|
||||
},
|
||||
},
|
||||
])(
|
||||
@@ -734,6 +761,7 @@ describe('Settings Loading and Merging', () => {
|
||||
]);
|
||||
expect(settings.merged.advanced?.excludedEnvVars).toEqual([
|
||||
'DEBUG',
|
||||
'DEBUG_MODE',
|
||||
'NODE_ENV',
|
||||
'USER_VAR',
|
||||
'WORKSPACE_DEBUG',
|
||||
@@ -814,8 +842,8 @@ describe('Settings Loading and Merging', () => {
|
||||
(fs.readFileSync as Mock).mockReturnValue('{}');
|
||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||
expect(settings.merged.telemetry).toBeUndefined();
|
||||
expect(settings.merged.ui).toBeUndefined();
|
||||
expect(settings.merged.mcpServers).toBeUndefined();
|
||||
expect(settings.merged.ui).toBeDefined();
|
||||
expect(settings.merged.mcpServers).toEqual({});
|
||||
});
|
||||
|
||||
it('should merge MCP servers correctly, with workspace taking precedence', () => {
|
||||
@@ -941,7 +969,7 @@ describe('Settings Loading and Merging', () => {
|
||||
(mockFsExistsSync as Mock).mockReturnValue(false); // No settings files exist
|
||||
(fs.readFileSync as Mock).mockReturnValue('{}');
|
||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||
expect(settings.merged.mcpServers).toBeUndefined();
|
||||
expect(settings.merged.mcpServers).toEqual({});
|
||||
});
|
||||
|
||||
it('should merge MCP servers from system, user, and workspace with system taking precedence', () => {
|
||||
@@ -1075,10 +1103,10 @@ describe('Settings Loading and Merging', () => {
|
||||
expected: 0.8,
|
||||
},
|
||||
{
|
||||
description: 'should be undefined if not in any settings file',
|
||||
description: 'should be default if not in any settings file',
|
||||
userContent: {},
|
||||
workspaceContent: {},
|
||||
expected: undefined,
|
||||
expected: 0.5,
|
||||
},
|
||||
])('$description', ({ userContent, workspaceContent, expected }) => {
|
||||
(mockFsExistsSync as Mock).mockReturnValue(true);
|
||||
@@ -1590,7 +1618,7 @@ describe('Settings Loading and Merging', () => {
|
||||
);
|
||||
expect(settings.system.path).toBe(MOCK_ENV_SYSTEM_SETTINGS_PATH);
|
||||
expect(settings.system.settings).toEqual(systemSettingsContent);
|
||||
expect(settings.merged).toEqual({
|
||||
expect(settings.merged).toMatchObject({
|
||||
...systemSettingsContent,
|
||||
});
|
||||
});
|
||||
@@ -1692,8 +1720,9 @@ describe('Settings Loading and Merging', () => {
|
||||
'DEBUG',
|
||||
]);
|
||||
expect(settings.merged.advanced?.excludedEnvVars).toEqual([
|
||||
'NODE_ENV',
|
||||
'DEBUG',
|
||||
'DEBUG_MODE',
|
||||
'NODE_ENV',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -1732,6 +1761,7 @@ describe('Settings Loading and Merging', () => {
|
||||
]);
|
||||
expect(settings.merged.advanced?.excludedEnvVars).toEqual([
|
||||
'DEBUG',
|
||||
'DEBUG_MODE',
|
||||
'NODE_ENV',
|
||||
'USER_VAR',
|
||||
'WORKSPACE_DEBUG',
|
||||
@@ -2444,4 +2474,42 @@ describe('Settings Loading and Merging', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultsFromSchema', () => {
|
||||
it('should extract defaults from a schema', () => {
|
||||
const mockSchema = {
|
||||
prop1: {
|
||||
type: 'string',
|
||||
default: 'default1',
|
||||
label: 'Prop 1',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
},
|
||||
nested: {
|
||||
type: 'object',
|
||||
label: 'Nested',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
default: {},
|
||||
properties: {
|
||||
prop2: {
|
||||
type: 'number',
|
||||
default: 42,
|
||||
label: 'Prop 2',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const defaults = getDefaultsFromSchema(mockSchema as SettingsSchema);
|
||||
expect(defaults).toEqual({
|
||||
prop1: 'default1',
|
||||
nested: {
|
||||
prop2: 42,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user