fix(config): Enable type checking for config tests (#11436)

This commit is contained in:
Sandy Tao
2025-10-17 22:39:53 -07:00
committed by GitHub
parent 725b312032
commit dd42893df7
4 changed files with 70 additions and 73 deletions

View File

@@ -8,14 +8,12 @@ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { tmpdir } from 'node:os';
import type {
ConfigParameters,
ContentGeneratorConfig,
} from '@google/gemini-cli-core';
import type { ConfigParameters } from '@google/gemini-cli-core';
import {
Config,
DEFAULT_FILE_FILTERING_OPTIONS,
} from '@google/gemini-cli-core';
import type { Settings } from './settingsSchema.js';
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
@@ -36,12 +34,6 @@ afterAll(() => {
const CLEARCUT_URL = 'https://play.googleapis.com/log';
const TEST_CONTENT_GENERATOR_CONFIG: ContentGeneratorConfig = {
apiKey: 'test-key',
model: 'test-model',
userAgent: 'test-agent',
};
// Mock file discovery service and tool registry
vi.mock('@google/gemini-cli-core', async () => {
const actual = await vi.importActual('@google/gemini-cli-core');
@@ -75,13 +67,13 @@ describe('Configuration Integration Tests', () => {
describe('File Filtering Configuration', () => {
it('should load default file filtering settings', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFilteringRespectGitIgnore: undefined, // Should default to DEFAULT_FILE_FILTERING_OPTIONS
};
const config = new Config(configParams);
@@ -93,10 +85,11 @@ describe('Configuration Integration Tests', () => {
it('should load custom file filtering settings from configuration', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFiltering: {
@@ -111,10 +104,11 @@ describe('Configuration Integration Tests', () => {
it('should merge user and workspace file filtering settings', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFiltering: {
@@ -131,10 +125,11 @@ describe('Configuration Integration Tests', () => {
describe('Configuration Integration', () => {
it('should handle partial configuration objects gracefully', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFiltering: {
@@ -150,10 +145,11 @@ describe('Configuration Integration Tests', () => {
it('should handle empty configuration objects gracefully', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFiltering: {},
@@ -169,10 +165,11 @@ describe('Configuration Integration Tests', () => {
it('should handle missing configuration sections gracefully', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
// Missing fileFiltering configuration
@@ -190,10 +187,11 @@ describe('Configuration Integration Tests', () => {
describe('Real-world Configuration Scenarios', () => {
it('should handle a security-focused configuration', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFiltering: {
@@ -208,10 +206,11 @@ describe('Configuration Integration Tests', () => {
it('should handle a CI/CD environment configuration', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
fileFiltering: {
@@ -228,10 +227,11 @@ describe('Configuration Integration Tests', () => {
describe('Checkpointing Configuration', () => {
it('should enable checkpointing when the setting is true', async () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
checkpointing: true,
@@ -246,10 +246,11 @@ describe('Configuration Integration Tests', () => {
describe('Extension Context Files', () => {
it('should have an empty array for extension context files by default', () => {
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
};
@@ -260,10 +261,11 @@ describe('Configuration Integration Tests', () => {
it('should correctly store and return extension context file paths', () => {
const contextFiles = ['/path/to/file1.txt', '/path/to/file2.js'];
const configParams: ConfigParameters = {
sessionId: 'test-session',
cwd: '/tmp',
contentGeneratorConfig: TEST_CONTENT_GENERATOR_CONFIG,
model: 'test-model',
embeddingModel: 'test-embedding-model',
sandbox: false,
sandbox: undefined,
targetDir: tempDir,
debugMode: false,
extensionContextFilePaths: contextFiles,
@@ -274,11 +276,11 @@ describe('Configuration Integration Tests', () => {
});
describe('Approval Mode Integration Tests', () => {
let parseArguments: typeof import('./config').parseArguments;
let parseArguments: typeof import('./config.js').parseArguments;
beforeEach(async () => {
// Import the argument parsing function for integration testing
const { parseArguments: parseArgs } = await import('./config');
const { parseArguments: parseArgs } = await import('./config.js');
parseArguments = parseArgs;
});

View File

@@ -16,12 +16,7 @@ import {
type GeminiCLIExtension,
SHELL_TOOL_NAME,
} from '@google/gemini-cli-core';
import {
loadCliConfig,
loadHierarchicalGeminiMemory,
parseArguments,
type CliArgs,
} from './config.js';
import { loadCliConfig, parseArguments, type CliArgs } from './config.js';
import type { Settings } from './settings.js';
import * as ServerConfig from '@google/gemini-cli-core';
import { isWorkspaceTrusted } from './trustedFolders.js';
@@ -681,6 +676,9 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
// 3. Spies on console functions (for logger output) are correctly set up if needed.
// Example of a previously failing test structure:
it.skip('should correctly use mocked homedir for global path', async () => {
// This test is skipped because mockFs and fsPromises are not properly imported/mocked
// TODO: Fix this test by properly setting up mock-fs and fs/promises mocks
/*
const MOCK_GEMINI_DIR_LOCAL = path.join(
'/mock/home/user',
ServerConfig.GEMINI_DIR,
@@ -699,6 +697,7 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
MOCK_GLOBAL_PATH_LOCAL,
'utf-8',
);
*/
});
});
@@ -2567,8 +2566,11 @@ describe('loadCliConfig fileFiltering', () => {
vi.restoreAllMocks();
});
type FileFilteringSettings = NonNullable<
NonNullable<Settings['context']>['fileFiltering']
>;
const testCases: Array<{
property: keyof NonNullable<Settings['fileFiltering']>;
property: keyof FileFilteringSettings;
getter: (config: ServerConfig.Config) => boolean;
value: boolean;
}> = [

View File

@@ -46,7 +46,6 @@ import {
afterEach,
type Mocked,
type Mock,
fail,
} from 'vitest';
import * as fs from 'node:fs'; // fs will be mocked separately
import stripJsonComments from 'strip-json-comments'; // Will be mocked separately
@@ -1266,7 +1265,7 @@ describe('Settings Loading and Merging', () => {
try {
loadSettings(MOCK_WORKSPACE_DIR);
fail('loadSettings should have thrown a FatalConfigError');
throw new Error('loadSettings should have thrown a FatalConfigError');
} catch (e) {
expect(e).toBeInstanceOf(FatalConfigError);
const error = e as FatalConfigError;
@@ -1336,9 +1335,10 @@ describe('Settings Loading and Merging', () => {
expect((settings.workspace.settings as TestSettings)['endpoint']).toBe(
'workspace_endpoint_from_env/api',
);
expect(
(settings.workspace.settings as TestSettings)['nested']['value'],
).toBe('workspace_endpoint_from_env');
const nested = (settings.workspace.settings as TestSettings)[
'nested'
] as Record<string, unknown>;
expect(nested['value']).toBe('workspace_endpoint_from_env');
expect((settings.merged as TestSettings)['endpoint']).toBe(
'workspace_endpoint_from_env/api',
);
@@ -1586,21 +1586,14 @@ describe('Settings Loading and Merging', () => {
(settings.user.settings as TestSettings)['undefinedVal'],
).toBeUndefined();
expect(
(settings.user.settings as TestSettings)['nestedObj']['nestedNull'],
).toBeNull();
expect(
(settings.user.settings as TestSettings)['nestedObj']['nestedBool'],
).toBe(true);
expect(
(settings.user.settings as TestSettings)['nestedObj']['nestedNum'],
).toBe(0);
expect(
(settings.user.settings as TestSettings)['nestedObj']['nestedString'],
).toBe('literal');
expect(
(settings.user.settings as TestSettings)['nestedObj']['anotherEnv'],
).toBe('env_string_nested_value');
const nestedObj = (settings.user.settings as TestSettings)[
'nestedObj'
] as Record<string, unknown>;
expect(nestedObj['nestedNull']).toBeNull();
expect(nestedObj['nestedBool']).toBe(true);
expect(nestedObj['nestedNum']).toBe(0);
expect(nestedObj['nestedString']).toBe('literal');
expect(nestedObj['anotherEnv']).toBe('env_string_nested_value');
delete process.env['MY_ENV_STRING'];
delete process.env['MY_ENV_STRING_NESTED'];
@@ -2136,14 +2129,14 @@ describe('Settings Loading and Merging', () => {
vimMode: false,
},
model: {
maxSessionTurns: 0,
maxSessionTurns: -1,
},
context: {
includeDirectories: [],
},
security: {
folderTrust: {
enabled: null,
enabled: undefined,
},
},
};
@@ -2152,9 +2145,13 @@ describe('Settings Loading and Merging', () => {
expect(v1Settings).toEqual({
vimMode: false,
maxSessionTurns: 0,
maxSessionTurns: -1,
includeDirectories: [],
folderTrust: null,
security: {
folderTrust: {
enabled: undefined,
},
},
});
});
@@ -2342,9 +2339,9 @@ describe('Settings Loading and Merging', () => {
});
describe('migrateDeprecatedSettings', () => {
let mockFsExistsSync: Mocked<typeof fs.existsSync>;
let mockFsReadFileSync: Mocked<typeof fs.readFileSync>;
let mockDisableExtension: Mocked<typeof disableExtension>;
let mockFsExistsSync: Mock;
let mockFsReadFileSync: Mock;
let mockDisableExtension: Mock;
beforeEach(() => {
vi.resetAllMocks();

View File

@@ -17,10 +17,6 @@
"node_modules",
"dist",
// TODO(5691): Fix type errors and remove excludes.
"src/config/config.integration.test.ts",
"src/config/config.test.ts",
"src/config/extension.test.ts",
"src/config/settings.test.ts",
"src/nonInteractiveCli.test.ts",
"src/services/FileCommandLoader.test.ts",
"src/services/prompt-processors/argumentProcessor.test.ts",