mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-04 00:44:05 -07:00
feat(cli): Allow themes to be specified as file paths (#6828)
Co-authored-by: Bryan Morgan <bryanmorgan@google.com>
This commit is contained in:
@@ -9,9 +9,22 @@ if (process.env['NO_COLOR'] !== undefined) {
|
||||
delete process.env['NO_COLOR'];
|
||||
}
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
import { themeManager, DEFAULT_THEME } from './theme-manager.js';
|
||||
import { CustomTheme } from './theme.js';
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import type * as osActual from 'node:os';
|
||||
|
||||
vi.mock('node:fs');
|
||||
vi.mock('node:os', async (importOriginal) => {
|
||||
const actualOs = await importOriginal<typeof osActual>();
|
||||
return {
|
||||
...actualOs,
|
||||
homedir: vi.fn(),
|
||||
platform: vi.fn(() => 'linux'),
|
||||
};
|
||||
});
|
||||
|
||||
const validCustomTheme: CustomTheme = {
|
||||
type: 'custom',
|
||||
@@ -38,6 +51,10 @@ describe('ThemeManager', () => {
|
||||
themeManager.setActiveTheme(DEFAULT_THEME.name);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should load valid custom themes', () => {
|
||||
themeManager.loadCustomThemes({ MyCustomTheme: validCustomTheme });
|
||||
expect(themeManager.getCustomThemeNames()).toContain('MyCustomTheme');
|
||||
@@ -96,4 +113,69 @@ describe('ThemeManager', () => {
|
||||
process.env['NO_COLOR'] = original;
|
||||
}
|
||||
});
|
||||
|
||||
describe('when loading a theme from a file', () => {
|
||||
const mockThemePath = './my-theme.json';
|
||||
const mockTheme: CustomTheme = {
|
||||
...validCustomTheme,
|
||||
name: 'My File Theme',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.mocked(os.homedir).mockReturnValue('/home/user');
|
||||
vi.spyOn(fs, 'realpathSync').mockImplementation((p) => p as string);
|
||||
});
|
||||
|
||||
it('should load a theme from a valid file path', () => {
|
||||
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
|
||||
vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(mockTheme));
|
||||
|
||||
const result = themeManager.setActiveTheme('/home/user/my-theme.json');
|
||||
|
||||
expect(result).toBe(true);
|
||||
const activeTheme = themeManager.getActiveTheme();
|
||||
expect(activeTheme.name).toBe('My File Theme');
|
||||
expect(fs.readFileSync).toHaveBeenCalledWith(
|
||||
expect.stringContaining('my-theme.json'),
|
||||
'utf-8',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not load a theme if the file does not exist', () => {
|
||||
vi.spyOn(fs, 'existsSync').mockReturnValue(false);
|
||||
|
||||
const result = themeManager.setActiveTheme(mockThemePath);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(themeManager.getActiveTheme().name).toBe(DEFAULT_THEME.name);
|
||||
});
|
||||
|
||||
it('should not load a theme from a file with invalid JSON', () => {
|
||||
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
|
||||
vi.spyOn(fs, 'readFileSync').mockReturnValue('invalid json');
|
||||
|
||||
const result = themeManager.setActiveTheme(mockThemePath);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(themeManager.getActiveTheme().name).toBe(DEFAULT_THEME.name);
|
||||
});
|
||||
|
||||
it('should not load a theme from an untrusted file path and log a message', () => {
|
||||
vi.spyOn(fs, 'existsSync').mockReturnValue(true);
|
||||
vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(mockTheme));
|
||||
const consoleWarnSpy = vi
|
||||
.spyOn(console, 'warn')
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const result = themeManager.setActiveTheme('/untrusted/my-theme.json');
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(themeManager.getActiveTheme().name).toBe(DEFAULT_THEME.name);
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining('is outside your home directory'),
|
||||
);
|
||||
|
||||
consoleWarnSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user