Download packages/cli/src/ui/contexts/SettingsContext.test.tsx from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 4.65 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/contexts/SettingsContext.test.tsx
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/cli/src/ui/contexts/SettingsContext.test.tsx
-
curl -L -o SettingsContext.test.tsx https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/cli/src/ui/contexts/SettingsContext.test.tsx
4.65 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import type React from 'react'; | |
| import { Component, type ReactNode, act } from 'react'; | |
| import { renderHook, render } from '../../test-utils/render.js'; | |
| import { describe, it, expect, vi, beforeEach } from 'vitest'; | |
| import { SettingsContext, useSettingsStore } from './SettingsContext.js'; | |
| import { | |
| SettingScope, | |
| createTestMergedSettings, | |
| type LoadedSettings, | |
| type LoadedSettingsSnapshot, | |
| type SettingsFile, | |
| } from '../../config/settings.js'; | |
| const createMockSettingsFile = (path: string): SettingsFile => ({ | |
| path, | |
| settings: {}, | |
| originalSettings: {}, | |
| }); | |
| const mockSnapshot: LoadedSettingsSnapshot = { | |
| system: createMockSettingsFile('/system'), | |
| systemDefaults: createMockSettingsFile('/defaults'), | |
| user: createMockSettingsFile('/user'), | |
| workspace: createMockSettingsFile('/workspace'), | |
| isTrusted: true, | |
| errors: [], | |
| merged: createTestMergedSettings({ | |
| ui: { theme: 'default-theme' }, | |
| }), | |
| }; | |
| class ErrorBoundary extends Component< | |
| { children: ReactNode; onError: (error: Error) => void }, | |
| { hasError: boolean } | |
| > { | |
| constructor(props: { children: ReactNode; onError: (error: Error) => void }) { | |
| super(props); | |
| this.state = { hasError: false }; | |
| } | |
| static getDerivedStateFromError(_error: Error) { | |
| return { hasError: true }; | |
| } | |
| override componentDidCatch(error: Error) { | |
| this.props.onError(error); | |
| } | |
| override render() { | |
| if (this.state.hasError) { | |
| return null; | |
| } | |
| return this.props.children; | |
| } | |
| } | |
| const TestHarness = () => { | |
| useSettingsStore(); | |
| return null; | |
| }; | |
| describe('SettingsContext', () => { | |
| let mockLoadedSettings: LoadedSettings; | |
| let listeners: Array<() => void> = []; | |
| beforeEach(() => { | |
| listeners = []; | |
| mockLoadedSettings = { | |
| subscribe: vi.fn((listener: () => void) => { | |
| listeners.push(listener); | |
| return () => { | |
| listeners = listeners.filter((l) => l !== listener); | |
| }; | |
| }), | |
| getSnapshot: vi.fn(() => mockSnapshot), | |
| setValue: vi.fn(), | |
| } as unknown as LoadedSettings; | |
| }); | |
| const wrapper = ({ children }: { children: React.ReactNode }) => ( | |
| <SettingsContext.Provider value={mockLoadedSettings}> | |
| {children} | |
| </SettingsContext.Provider> | |
| ); | |
| it('should provide the correct initial state', async () => { | |
| const { result } = await renderHook(() => useSettingsStore(), { wrapper }); | |
| expect(result.current.settings.merged).toEqual(mockSnapshot.merged); | |
| expect(result.current.settings.isTrusted).toBe(true); | |
| }); | |
| it('should allow accessing settings for a specific scope', async () => { | |
| const { result } = await renderHook(() => useSettingsStore(), { wrapper }); | |
| const userSettings = result.current.settings.forScope(SettingScope.User); | |
| expect(userSettings).toBe(mockSnapshot.user); | |
| const workspaceSettings = result.current.settings.forScope( | |
| SettingScope.Workspace, | |
| ); | |
| expect(workspaceSettings).toBe(mockSnapshot.workspace); | |
| }); | |
| it('should trigger re-renders when settings change (external event)', async () => { | |
| const { result } = await renderHook(() => useSettingsStore(), { wrapper }); | |
| expect(result.current.settings.merged.ui?.theme).toBe('default-theme'); | |
| const newSnapshot = { | |
| ...mockSnapshot, | |
| merged: { ui: { theme: 'new-theme' } }, | |
| }; | |
| ( | |
| mockLoadedSettings.getSnapshot as ReturnType<typeof vi.fn> | |
| ).mockReturnValue(newSnapshot); | |
| // Trigger the listeners (simulate coreEvents emission) | |
| act(() => { | |
| listeners.forEach((l) => l()); | |
| }); | |
| expect(result.current.settings.merged.ui?.theme).toBe('new-theme'); | |
| }); | |
| it('should call store.setValue when setSetting is called', async () => { | |
| const { result } = await renderHook(() => useSettingsStore(), { wrapper }); | |
| act(() => { | |
| result.current.setSetting(SettingScope.User, 'ui.theme', 'dark'); | |
| }); | |
| expect(mockLoadedSettings.setValue).toHaveBeenCalledWith( | |
| SettingScope.User, | |
| 'ui.theme', | |
| 'dark', | |
| ); | |
| }); | |
| it('should throw error if used outside provider', async () => { | |
| const onError = vi.fn(); | |
| // Suppress console.error (React logs error boundary info) | |
| const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); | |
| await render( | |
| <ErrorBoundary onError={onError}> | |
| <TestHarness /> | |
| </ErrorBoundary>, | |
| ); | |
| expect(onError).toHaveBeenCalledWith( | |
| expect.objectContaining({ | |
| message: 'useSettingsStore must be used within a SettingsProvider', | |
| }), | |
| ); | |
| consoleSpy.mockRestore(); | |
| }); | |
| }); | |