mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-17 01:21:10 -07:00
168 lines
4.6 KiB
TypeScript
168 lines
4.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import { renderHook } from '../../test-utils/render.js';
|
|
import { useTerminalTheme } from './useTerminalTheme.js';
|
|
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { makeFakeConfig, type Config } from '@google/gemini-cli-core';
|
|
import os from 'node:os';
|
|
|
|
// Mocks
|
|
const mockWrite = vi.fn();
|
|
const mockSubscribe = vi.fn();
|
|
const mockUnsubscribe = vi.fn();
|
|
const mockHandleThemeSelect = vi.fn();
|
|
|
|
vi.mock('ink', async () => ({
|
|
useStdout: () => ({
|
|
stdout: {
|
|
write: mockWrite,
|
|
},
|
|
}),
|
|
}));
|
|
|
|
vi.mock('../contexts/TerminalContext.js', () => ({
|
|
useTerminalContext: () => ({
|
|
subscribe: mockSubscribe,
|
|
unsubscribe: mockUnsubscribe,
|
|
}),
|
|
}));
|
|
|
|
const mockSettings = {
|
|
merged: {
|
|
ui: {
|
|
theme: 'default', // DEFAULT_THEME.name
|
|
autoThemeSwitching: true,
|
|
terminalBackgroundPollingInterval: 60,
|
|
},
|
|
},
|
|
};
|
|
|
|
vi.mock('../contexts/SettingsContext.js', () => ({
|
|
useSettings: () => mockSettings,
|
|
}));
|
|
|
|
vi.mock('../themes/theme-manager.js', async () => {
|
|
const actual = await vi.importActual('../themes/theme-manager.js');
|
|
return {
|
|
...actual,
|
|
themeManager: {
|
|
isDefaultTheme: (name: string) =>
|
|
name === 'default' || name === 'default-light',
|
|
},
|
|
DEFAULT_THEME: { name: 'default' },
|
|
};
|
|
});
|
|
|
|
vi.mock('../themes/default-light.js', () => ({
|
|
DefaultLight: { name: 'default-light' },
|
|
}));
|
|
|
|
describe('useTerminalTheme', () => {
|
|
let config: Config;
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
config = makeFakeConfig({
|
|
targetDir: os.tmpdir(),
|
|
});
|
|
// Set initial background to ensure the hook passes the startup check.
|
|
config.setTerminalBackground('#000000');
|
|
// Spy on future updates.
|
|
vi.spyOn(config, 'setTerminalBackground');
|
|
|
|
mockWrite.mockClear();
|
|
mockSubscribe.mockClear();
|
|
mockUnsubscribe.mockClear();
|
|
mockHandleThemeSelect.mockClear();
|
|
// Reset any settings modifications
|
|
mockSettings.merged.ui.autoThemeSwitching = true;
|
|
mockSettings.merged.ui.theme = 'default';
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it('should subscribe to terminal background events on mount', () => {
|
|
renderHook(() => useTerminalTheme(mockHandleThemeSelect, config));
|
|
expect(mockSubscribe).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should unsubscribe on unmount', () => {
|
|
const { unmount } = renderHook(() =>
|
|
useTerminalTheme(mockHandleThemeSelect, config),
|
|
);
|
|
unmount();
|
|
expect(mockUnsubscribe).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should poll for terminal background', () => {
|
|
renderHook(() => useTerminalTheme(mockHandleThemeSelect, config));
|
|
|
|
// Fast-forward time (1 minute)
|
|
vi.advanceTimersByTime(60000);
|
|
expect(mockWrite).toHaveBeenCalledWith('\x1b]11;?\x1b\\');
|
|
});
|
|
|
|
it('should not poll if terminal background is undefined at startup', () => {
|
|
config.getTerminalBackground = vi.fn().mockReturnValue(undefined);
|
|
renderHook(() => useTerminalTheme(mockHandleThemeSelect, config));
|
|
|
|
// Poll should not happen
|
|
vi.advanceTimersByTime(60000);
|
|
expect(mockWrite).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should switch to light theme when background is light', () => {
|
|
renderHook(() => useTerminalTheme(mockHandleThemeSelect, config));
|
|
|
|
const handler = mockSubscribe.mock.calls[0][0];
|
|
|
|
// Simulate light background response (white)
|
|
handler('rgb:ffff/ffff/ffff');
|
|
|
|
expect(config.setTerminalBackground).toHaveBeenCalledWith('#ffffff');
|
|
expect(mockHandleThemeSelect).toHaveBeenCalledWith(
|
|
'default-light',
|
|
expect.anything(),
|
|
);
|
|
});
|
|
|
|
it('should switch to dark theme when background is dark', () => {
|
|
// Start with light theme
|
|
mockSettings.merged.ui.theme = 'default-light';
|
|
|
|
renderHook(() => useTerminalTheme(mockHandleThemeSelect, config));
|
|
|
|
const handler = mockSubscribe.mock.calls[0][0];
|
|
|
|
// Simulate dark background response (black)
|
|
handler('rgb:0000/0000/0000');
|
|
|
|
expect(config.setTerminalBackground).toHaveBeenCalledWith('#000000');
|
|
expect(mockHandleThemeSelect).toHaveBeenCalledWith(
|
|
'default',
|
|
expect.anything(),
|
|
);
|
|
|
|
// Reset theme
|
|
mockSettings.merged.ui.theme = 'default';
|
|
});
|
|
|
|
it('should not switch theme if autoThemeSwitching is disabled', () => {
|
|
mockSettings.merged.ui.autoThemeSwitching = false;
|
|
renderHook(() => useTerminalTheme(mockHandleThemeSelect, config));
|
|
|
|
// Poll should not happen
|
|
vi.advanceTimersByTime(60000);
|
|
expect(mockWrite).not.toHaveBeenCalled();
|
|
|
|
mockSettings.merged.ui.autoThemeSwitching = true;
|
|
});
|
|
});
|