mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-25 12:34:38 -07:00
Refactor to defer initialization. (#8925)
This commit is contained in:
@@ -44,8 +44,10 @@ vi.mock('./config/config.js', () => ({
|
||||
loadCliConfig: vi.fn().mockResolvedValue({
|
||||
getSandbox: vi.fn(() => false),
|
||||
getQuestion: vi.fn(() => ''),
|
||||
isInteractive: () => false,
|
||||
} as unknown as Config),
|
||||
parseArguments: vi.fn().mockResolvedValue({}),
|
||||
isDebugMode: vi.fn(() => false),
|
||||
}));
|
||||
|
||||
vi.mock('read-package-up', () => ({
|
||||
@@ -76,18 +78,20 @@ vi.mock('./utils/sandbox.js', () => ({
|
||||
start_sandbox: vi.fn(() => Promise.resolve()), // Mock as an async function that resolves
|
||||
}));
|
||||
|
||||
vi.mock('./utils/relaunch.js', () => ({
|
||||
relaunchAppInChildProcess: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('./config/sandboxConfig.js', () => ({
|
||||
loadSandboxConfig: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('gemini.tsx main function', () => {
|
||||
let originalEnvGeminiSandbox: string | undefined;
|
||||
let originalEnvSandbox: string | undefined;
|
||||
let initialUnhandledRejectionListeners: NodeJS.UnhandledRejectionListener[] =
|
||||
[];
|
||||
|
||||
const processExitSpy = vi
|
||||
.spyOn(process, 'exit')
|
||||
.mockImplementation((code) => {
|
||||
throw new MockProcessExitError(code);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// Store and clear sandbox-related env variables to ensure a consistent test environment
|
||||
originalEnvGeminiSandbox = process.env['GEMINI_SANDBOX'];
|
||||
@@ -123,7 +127,73 @@ describe('gemini.tsx main function', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('verifies that we dont load the config before relaunchAppInChildProcess', async () => {
|
||||
const processExitSpy = vi
|
||||
.spyOn(process, 'exit')
|
||||
.mockImplementation((code) => {
|
||||
throw new MockProcessExitError(code);
|
||||
});
|
||||
const { relaunchAppInChildProcess } = await import('./utils/relaunch.js');
|
||||
const { loadCliConfig } = await import('./config/config.js');
|
||||
const { loadSettings } = await import('./config/settings.js');
|
||||
const { loadSandboxConfig } = await import('./config/sandboxConfig.js');
|
||||
vi.mocked(loadSandboxConfig).mockResolvedValue(undefined);
|
||||
|
||||
const callOrder: string[] = [];
|
||||
vi.mocked(relaunchAppInChildProcess).mockImplementation(async () => {
|
||||
callOrder.push('relaunch');
|
||||
});
|
||||
vi.mocked(loadCliConfig).mockImplementation(async () => {
|
||||
callOrder.push('loadCliConfig');
|
||||
return {
|
||||
isInteractive: () => false,
|
||||
getQuestion: () => '',
|
||||
getSandbox: () => false,
|
||||
getDebugMode: () => false,
|
||||
getListExtensions: () => false,
|
||||
getMcpServers: () => ({}),
|
||||
initialize: vi.fn(),
|
||||
getIdeMode: () => false,
|
||||
getExperimentalZedIntegration: () => false,
|
||||
getScreenReader: () => false,
|
||||
getGeminiMdFileCount: () => 0,
|
||||
getProjectRoot: () => '/',
|
||||
} as unknown as Config;
|
||||
});
|
||||
vi.mocked(loadSettings).mockReturnValue({
|
||||
errors: [],
|
||||
merged: {
|
||||
advanced: { autoConfigureMemory: true },
|
||||
security: { auth: {} },
|
||||
ui: {},
|
||||
},
|
||||
setValue: vi.fn(),
|
||||
forScope: () => ({ settings: {}, originalSettings: {}, path: '' }),
|
||||
} as never);
|
||||
try {
|
||||
await main();
|
||||
} catch (e) {
|
||||
// Mocked process exit throws an error.
|
||||
if (!(e instanceof MockProcessExitError)) throw e;
|
||||
}
|
||||
|
||||
// It is critical that we call relaunch before loadCliConfig to avoid
|
||||
// loading config in the outer process when we are going to relaunch.
|
||||
// By ensuring we don't load the config we also ensure we don't trigger any
|
||||
// operations that might require loading the config such as such as
|
||||
// initializing mcp servers.
|
||||
// For the sandbox case we still have to load a partial cli config.
|
||||
// we can authorize outside the sandbox.
|
||||
expect(callOrder).toEqual(['relaunch', 'loadCliConfig']);
|
||||
processExitSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should log unhandled promise rejections and open debug console on first error', async () => {
|
||||
const processExitSpy = vi
|
||||
.spyOn(process, 'exit')
|
||||
.mockImplementation((code) => {
|
||||
throw new MockProcessExitError(code);
|
||||
});
|
||||
const appEventsMock = vi.mocked(appEvents);
|
||||
const rejectionError = new Error('Test unhandled rejection');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user