Make merged settings non-nullable and fix all lints related to that. (#16647)

This commit is contained in:
Jacob Richman
2026-01-15 09:26:10 -08:00
committed by GitHub
parent 2b6bfe4097
commit f7f38e2b9e
59 changed files with 964 additions and 744 deletions
+127 -108
View File
@@ -23,8 +23,30 @@ import {
import os from 'node:os';
import v8 from 'node:v8';
import { type CliArgs } from './config/config.js';
import { type LoadedSettings } from './config/settings.js';
import {
type LoadedSettings,
type Settings,
createTestMergedSettings,
} from './config/settings.js';
import { appEvents, AppEvent } from './utils/events.js';
function createMockSettings(
overrides: Record<string, unknown> = {},
): LoadedSettings {
const merged = createTestMergedSettings(
(overrides['merged'] as Partial<Settings>) || {},
);
return {
system: { settings: {} },
systemDefaults: { settings: {} },
user: { settings: {} },
workspace: { settings: {} },
errors: [],
...overrides,
merged,
} as unknown as LoadedSettings;
}
import {
type Config,
type ResumedSessionData,
@@ -108,26 +130,19 @@ class MockProcessExitError extends Error {
}
// Mock dependencies
vi.mock('./config/settings.js', () => ({
loadSettings: vi.fn().mockReturnValue({
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
}),
migrateDeprecatedSettings: vi.fn(),
SettingScope: {
User: 'user',
Workspace: 'workspace',
System: 'system',
SystemDefaults: 'system-defaults',
},
}));
vi.mock('./config/settings.js', async (importOriginal) => {
const actual = await importOriginal<typeof import('./config/settings.js')>();
return {
...actual,
loadSettings: vi.fn().mockImplementation(() => ({
merged: actual.getDefaultsFromSchema(),
workspace: { settings: {} },
errors: [],
})),
saveModelChange: vi.fn(),
getDefaultsFromSchema: actual.getDefaultsFromSchema,
};
});
vi.mock('./ui/utils/terminalCapabilityManager.js', () => ({
terminalCapabilityManager: {
@@ -443,17 +458,15 @@ describe('gemini.tsx main function kitty protocol', () => {
getProjectTempDir: vi.fn().mockReturnValue('/tmp/gemini-test'),
},
} as unknown as Config);
vi.mocked(loadSettings).mockReturnValue({
errors: [],
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
} as never);
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
}),
);
vi.mocked(parseArguments).mockResolvedValue({
model: undefined,
sandbox: undefined,
@@ -505,17 +518,18 @@ describe('gemini.tsx main function kitty protocol', () => {
throw new MockProcessExitError(code);
});
vi.mocked(loadSettings).mockReturnValue({
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
}),
);
vi.mocked(parseArguments).mockResolvedValue({
promptInteractive: false,
@@ -594,17 +608,18 @@ describe('gemini.tsx main function kitty protocol', () => {
promptInteractive: false,
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue({
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: {
advanced: {},
security: { auth: {} },
ui: {},
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
}),
);
const mockConfig = {
isInteractive: () => false,
@@ -665,17 +680,18 @@ describe('gemini.tsx main function kitty protocol', () => {
throw new MockProcessExitError(code);
});
vi.mocked(loadSettings).mockReturnValue({
merged: {
advanced: {},
security: { auth: {} },
ui: { theme: 'non-existent-theme' },
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: {
advanced: {},
security: { auth: {} },
ui: { theme: 'non-existent-theme' },
},
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
}),
);
vi.mocked(parseArguments).mockResolvedValue({
promptInteractive: false,
@@ -753,13 +769,14 @@ describe('gemini.tsx main function kitty protocol', () => {
});
const emitFeedbackSpy = vi.spyOn(coreEvents, 'emitFeedback');
vi.mocked(loadSettings).mockReturnValue({
merged: { advanced: {}, security: { auth: {} }, ui: { theme: 'test' } },
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: { advanced: {}, security: { auth: {} }, ui: { theme: 'test' } },
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
}),
);
vi.mocked(parseArguments).mockResolvedValue({
promptInteractive: false,
@@ -839,13 +856,14 @@ describe('gemini.tsx main function kitty protocol', () => {
throw new MockProcessExitError(code);
});
vi.mocked(loadSettings).mockReturnValue({
merged: { advanced: {}, security: { auth: {} }, ui: {} },
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: { advanced: {}, security: { auth: {} }, ui: {} },
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
}),
);
vi.mocked(parseArguments).mockResolvedValue({
promptInteractive: false,
@@ -918,13 +936,14 @@ describe('gemini.tsx main function kitty protocol', () => {
throw new MockProcessExitError(code);
});
vi.mocked(loadSettings).mockReturnValue({
merged: { advanced: {}, security: { auth: {} }, ui: {} },
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
errors: [],
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: { advanced: {}, security: { auth: {} }, ui: {} },
workspace: { settings: {} },
setValue: vi.fn(),
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
}),
);
vi.mocked(parseArguments).mockResolvedValue({
promptInteractive: false,
@@ -1034,10 +1053,11 @@ describe('gemini.tsx main function exit codes', () => {
);
const { loadSettings } = await import('./config/settings.js');
vi.mocked(loadCliConfig).mockResolvedValue({} as Config);
vi.mocked(loadSettings).mockReturnValue({
merged: { security: { auth: {} }, ui: {} },
errors: [],
} as never);
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: { security: { auth: {} }, ui: {} },
}),
);
vi.mocked(parseArguments).mockResolvedValue({
promptInteractive: true,
} as unknown as CliArgs);
@@ -1066,14 +1086,13 @@ describe('gemini.tsx main function exit codes', () => {
vi.mocked(loadCliConfig).mockResolvedValue({
refreshAuth: vi.fn().mockRejectedValue(new Error('Auth failed')),
} as unknown as Config);
vi.mocked(loadSettings).mockReturnValue({
merged: {
security: { auth: { selectedType: 'google', useExternal: false } },
ui: {},
},
workspace: { settings: {} },
errors: [],
} as never);
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: {
security: { auth: { selectedType: 'google', useExternal: false } },
},
}),
);
vi.mocked(parseArguments).mockResolvedValue({} as unknown as CliArgs);
vi.mock('./config/auth.js', () => ({
validateAuthMethod: vi.fn().mockReturnValue(null),
@@ -1131,11 +1150,11 @@ describe('gemini.tsx main function exit codes', () => {
getProjectTempDir: vi.fn().mockReturnValue('/tmp/gemini-test'),
},
} as unknown as Config);
vi.mocked(loadSettings).mockReturnValue({
merged: { security: { auth: {} }, ui: {} },
workspace: { settings: {} },
errors: [],
} as never);
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: { security: { auth: {} }, ui: {} },
}),
);
vi.mocked(parseArguments).mockResolvedValue({
resume: 'invalid-session',
} as unknown as CliArgs);
@@ -1200,11 +1219,11 @@ describe('gemini.tsx main function exit codes', () => {
},
getRemoteAdminSettings: () => undefined,
} as unknown as Config);
vi.mocked(loadSettings).mockReturnValue({
merged: { security: { auth: {} }, ui: {} },
workspace: { settings: {} },
errors: [],
} as never);
vi.mocked(loadSettings).mockReturnValue(
createMockSettings({
merged: { security: { auth: {} }, ui: {} },
}),
);
vi.mocked(parseArguments).mockResolvedValue({} as unknown as CliArgs);
Object.defineProperty(process.stdin, 'isTTY', {
value: true, // Simulate TTY so it doesn't try to read stdin