import { jsx as _jsx } from "react/jsx-runtime";
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 *
 *
 * This test suite covers:
 * - Initial rendering and display state
 * - Keyboard navigation (arrows, vim keys, Tab)
 * - Settings toggling (Enter, Space)
 * - Focus section switching between settings and scope selector
 * - Scope selection and settings persistence across scopes
 * - Restart-required vs immediate settings behavior
 * - VimModeContext integration
 * - Complex user interaction workflows
 * - Error handling and edge cases
 * - Display values for inherited and overridden settings
 *
 */
import { render } from '../../test-utils/render.js';
import { waitFor } from '../../test-utils/async.js';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { SettingsDialog } from './SettingsDialog.js';
import { LoadedSettings, SettingScope } from '../../config/settings.js';
import { createMockSettings } from '../../test-utils/settings.js';
import { VimModeProvider } from '../contexts/VimModeContext.js';
import { KeypressProvider } from '../contexts/KeypressContext.js';
import { act } from 'react';
import { saveModifiedSettings, TEST_ONLY } from '../../utils/settingsUtils.js';
import { getSettingsSchema, } from '../../config/settingsSchema.js';
import { terminalCapabilityManager } from '../utils/terminalCapabilityManager.js';
// Mock the VimModeContext
const mockToggleVimEnabled = vi.fn().mockResolvedValue(undefined);
const mockSetVimMode = vi.fn();
vi.mock('../contexts/UIStateContext.js', () => ({
    useUIState: () => ({
        terminalWidth: 100, // Fixed width for consistent snapshots
    }),
}));
var TerminalKeys;
(function (TerminalKeys) {
    TerminalKeys["ENTER"] = "\r";
    TerminalKeys["TAB"] = "\t";
    TerminalKeys["UP_ARROW"] = "\u001B[A";
    TerminalKeys["DOWN_ARROW"] = "\u001B[B";
    TerminalKeys["LEFT_ARROW"] = "\u001B[D";
    TerminalKeys["RIGHT_ARROW"] = "\u001B[C";
    TerminalKeys["ESCAPE"] = "\u001B";
    TerminalKeys["BACKSPACE"] = "\b";
})(TerminalKeys || (TerminalKeys = {}));
vi.mock('../../config/settingsSchema.js', async (importOriginal) => {
    const original = await importOriginal();
    return {
        ...original,
        getSettingsSchema: vi.fn(original.getSettingsSchema),
    };
});
vi.mock('../contexts/VimModeContext.js', async () => {
    const actual = await vi.importActual('../contexts/VimModeContext.js');
    return {
        ...actual,
        useVimMode: () => ({
            vimEnabled: false,
            vimMode: 'INSERT',
            toggleVimEnabled: mockToggleVimEnabled,
            setVimMode: mockSetVimMode,
        }),
    };
});
vi.mock('../../utils/settingsUtils.js', async () => {
    const actual = await vi.importActual('../../utils/settingsUtils.js');
    return {
        ...actual,
        saveModifiedSettings: vi.fn(),
    };
});
// Shared test schemas
var StringEnum;
(function (StringEnum) {
    StringEnum["FOO"] = "foo";
    StringEnum["BAR"] = "bar";
    StringEnum["BAZ"] = "baz";
})(StringEnum || (StringEnum = {}));
const ENUM_SETTING = {
    type: 'enum',
    label: 'Theme',
    options: [
        {
            label: 'Foo',
            value: StringEnum.FOO,
        },
        {
            label: 'Bar',
            value: StringEnum.BAR,
        },
        {
            label: 'Baz',
            value: StringEnum.BAZ,
        },
    ],
    category: 'UI',
    requiresRestart: false,
    default: StringEnum.BAR,
    description: 'The color theme for the UI.',
    showInDialog: true,
};
const ENUM_FAKE_SCHEMA = {
    ui: {
        showInDialog: false,
        properties: {
            theme: {
                ...ENUM_SETTING,
            },
        },
    },
};
const TOOLS_SHELL_FAKE_SCHEMA = {
    tools: {
        type: 'object',
        label: 'Tools',
        category: 'Tools',
        requiresRestart: false,
        default: {},
        description: 'Tool settings.',
        showInDialog: false,
        properties: {
            shell: {
                type: 'object',
                label: 'Shell',
                category: 'Tools',
                requiresRestart: false,
                default: {},
                description: 'Shell tool settings.',
                showInDialog: false,
                properties: {
                    showColor: {
                        type: 'boolean',
                        label: 'Show Color',
                        category: 'Tools',
                        requiresRestart: false,
                        default: false,
                        description: 'Show color in shell output.',
                        showInDialog: true,
                    },
                    enableInteractiveShell: {
                        type: 'boolean',
                        label: 'Enable Interactive Shell',
                        category: 'Tools',
                        requiresRestart: true,
                        default: true,
                        description: 'Enable interactive shell mode.',
                        showInDialog: true,
                    },
                    pager: {
                        type: 'string',
                        label: 'Pager',
                        category: 'Tools',
                        requiresRestart: false,
                        default: 'cat',
                        description: 'The pager command to use for shell output.',
                        showInDialog: true,
                    },
                },
            },
        },
    },
};
// Helper function to render SettingsDialog with standard wrapper
const renderDialog = (settings, onSelect, options) => render(_jsx(KeypressProvider, { children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect, onRestartRequest: options?.onRestartRequest, availableTerminalHeight: options?.availableTerminalHeight }) }));
describe('SettingsDialog', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        vi.spyOn(terminalCapabilityManager, 'isKittyProtocolEnabled').mockReturnValue(true);
        mockToggleVimEnabled.mockRejectedValue(undefined);
    });
    afterEach(() => {
        TEST_ONLY.clearFlattenedSchema();
        vi.clearAllMocks();
        vi.resetAllMocks();
    });
    describe('Initial Rendering', () => {
        it('should render the settings dialog with default state', () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            const output = lastFrame();
            expect(output).toContain('Settings');
            expect(output).toContain('Apply To');
            // Use regex for more flexible help text matching
            expect(output).toMatch(/Enter.*select.*Esc.*close/);
        });
        it('should accept availableTerminalHeight prop without errors', () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect, {
                availableTerminalHeight: 20,
            });
            const output = lastFrame();
            // Should still render properly with the height prop
            expect(output).toContain('Settings');
            // Use regex for more flexible help text matching
            expect(output).toMatch(/Enter.*select.*Esc.*close/);
        });
        it('should render settings list with visual indicators', () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            const output = lastFrame();
            // Use snapshot to capture visual layout including indicators
            expect(output).toMatchSnapshot();
        });
        it('should use almost full height of the window but no more when the window height is 25 rows', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            // Render with a fixed height of 25 rows
            const { lastFrame } = renderDialog(settings, onSelect, {
                availableTerminalHeight: 25,
            });
            // Wait for the dialog to render
            await waitFor(() => {
                const output = lastFrame();
                expect(output).toBeDefined();
                const lines = output.split('\n');
                expect(lines.length).toBeGreaterThanOrEqual(24);
                expect(lines.length).toBeLessThanOrEqual(25);
            });
        });
    });
    describe('Setting Descriptions', () => {
        it('should render descriptions for settings that have them', () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            const output = lastFrame();
            // 'general.vimMode' has description 'Enable Vim keybindings' in settingsSchema.ts
            expect(output).toContain('Vim Mode');
            expect(output).toContain('Enable Vim keybindings');
            // 'general.enableAutoUpdate' has description 'Enable automatic updates.'
            expect(output).toContain('Enable Auto Update');
            expect(output).toContain('Enable automatic updates.');
        });
    });
    describe('Settings Navigation', () => {
        it.each([
            {
                name: 'arrow keys',
                down: TerminalKeys.DOWN_ARROW,
                up: TerminalKeys.UP_ARROW,
            },
            {
                name: 'vim keys (j/k)',
                down: 'j',
                up: 'k',
            },
        ])('should navigate with $name', async ({ down, up }) => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
            const initialFrame = lastFrame();
            expect(initialFrame).toContain('Vim Mode');
            // Navigate down
            act(() => {
                stdin.write(down);
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('Enable Auto Update');
            });
            // Navigate up
            act(() => {
                stdin.write(up);
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('Vim Mode');
            });
            unmount();
        });
        it('wraps around when at the top of the list', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
            // Try to go up from first item
            act(() => {
                stdin.write(TerminalKeys.UP_ARROW);
            });
            await waitFor(() => {
                // Should wrap to last setting (without relying on exact bullet character)
                expect(lastFrame()).toContain('Hook Notifications');
            });
            unmount();
        });
    });
    describe('Settings Toggling', () => {
        it('should toggle setting with Enter key', async () => {
            vi.mocked(saveModifiedSettings).mockClear();
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
            // Wait for initial render and verify we're on Preview Features (first setting)
            await waitFor(() => {
                expect(lastFrame()).toContain('Preview Features (e.g., models)');
            });
            // Navigate to Vim Mode setting and verify we're there
            act(() => {
                stdin.write(TerminalKeys.DOWN_ARROW);
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('Vim Mode');
            });
            // Toggle the setting
            act(() => {
                stdin.write(TerminalKeys.ENTER);
            });
            // Wait for the setting change to be processed
            await waitFor(() => {
                expect(vi.mocked(saveModifiedSettings).mock.calls.length).toBeGreaterThan(0);
            });
            // Wait for the mock to be called
            await waitFor(() => {
                expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalled();
            });
            expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalledWith(new Set(['general.vimMode']), expect.objectContaining({
                general: expect.objectContaining({
                    vimMode: true,
                }),
            }), expect.any(LoadedSettings), SettingScope.User);
            unmount();
        });
        describe('enum values', () => {
            it.each([
                {
                    name: 'toggles to next value',
                    initialValue: undefined,
                    expectedValue: StringEnum.BAZ,
                },
                {
                    name: 'loops back to first value when at end',
                    initialValue: StringEnum.BAZ,
                    expectedValue: StringEnum.FOO,
                },
            ])('$name', async ({ initialValue, expectedValue }) => {
                vi.mocked(saveModifiedSettings).mockClear();
                vi.mocked(getSettingsSchema).mockReturnValue(ENUM_FAKE_SCHEMA);
                const settings = createMockSettings();
                if (initialValue !== undefined) {
                    settings.setValue(SettingScope.User, 'ui.theme', initialValue);
                }
                const onSelect = vi.fn();
                const { stdin, unmount } = renderDialog(settings, onSelect);
                act(() => {
                    stdin.write(TerminalKeys.DOWN_ARROW);
                    stdin.write(TerminalKeys.ENTER);
                });
                await waitFor(() => {
                    expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalled();
                });
                expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalledWith(new Set(['ui.theme']), expect.objectContaining({
                    ui: expect.objectContaining({
                        theme: expectedValue,
                    }),
                }), expect.any(LoadedSettings), SettingScope.User);
                unmount();
            });
        });
        it('should handle vim mode setting specially', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Navigate to vim mode setting and toggle it
            // This would require knowing the exact position, so we'll just test that the mock is called
            act(() => {
                stdin.write(TerminalKeys.ENTER); // Enter key
            });
            // The mock should potentially be called if vim mode was toggled
            unmount();
        });
    });
    describe('Scope Selection', () => {
        it('should switch between scopes', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Switch to scope focus
            act(() => {
                stdin.write(TerminalKeys.TAB); // Tab key
                // Select different scope (numbers 1-3 typically available)
                stdin.write('2'); // Select second scope option
            });
            unmount();
        });
        it('should reset to settings focus when scope is selected', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, unmount } = renderDialog(settings, onSelect);
            // Wait for initial render
            await waitFor(() => {
                expect(lastFrame()).toContain('Vim Mode');
            });
            // The UI should show the settings section is active and scope section is inactive
            expect(lastFrame()).toContain('Vim Mode'); // Settings section active
            expect(lastFrame()).toContain('Apply To'); // Scope section (don't rely on exact spacing)
            // This test validates the initial state - scope selection behavior
            // is complex due to keypress handling, so we focus on state validation
            unmount();
        });
    });
    describe('Restart Prompt', () => {
        it('should show restart prompt for restart-required settings', async () => {
            const settings = createMockSettings();
            const onRestartRequest = vi.fn();
            const { unmount } = renderDialog(settings, vi.fn(), {
                onRestartRequest,
            });
            // This test would need to trigger a restart-required setting change
            // The exact steps depend on which settings require restart
            unmount();
        });
        it('should handle restart request when r is pressed', async () => {
            const settings = createMockSettings();
            const onRestartRequest = vi.fn();
            const { stdin, unmount } = renderDialog(settings, vi.fn(), {
                onRestartRequest,
            });
            // Press 'r' key (this would only work if restart prompt is showing)
            act(() => {
                stdin.write('r');
            });
            // If restart prompt was showing, onRestartRequest should be called
            unmount();
        });
    });
    describe('Escape Key Behavior', () => {
        it('should call onSelect with undefined when Escape is pressed', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, unmount } = renderDialog(settings, onSelect);
            // Wait for initial render
            await waitFor(() => {
                expect(lastFrame()).toContain('Vim Mode');
            });
            // Verify the dialog is rendered properly
            expect(lastFrame()).toContain('Settings');
            expect(lastFrame()).toContain('Apply To');
            // This test validates rendering - escape key behavior depends on complex
            // keypress handling that's difficult to test reliably in this environment
            unmount();
        });
    });
    describe('Settings Persistence', () => {
        it('should persist settings across scope changes', async () => {
            const settings = createMockSettings({ vimMode: true });
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Switch to scope selector and change scope
            act(() => {
                stdin.write(TerminalKeys.TAB); // Tab
                stdin.write('2'); // Select workspace scope
            });
            // Settings should be reloaded for new scope
            unmount();
        });
        it('should show different values for different scopes', () => {
            const settings = createMockSettings({
                user: {
                    settings: { vimMode: true },
                    originalSettings: { vimMode: true },
                    path: '',
                },
                system: {
                    settings: { vimMode: false },
                    originalSettings: { vimMode: false },
                    path: '',
                },
                workspace: {
                    settings: { autoUpdate: false },
                    originalSettings: { autoUpdate: false },
                    path: '',
                },
            });
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            // Should show user scope values initially
            const output = lastFrame();
            expect(output).toContain('Settings');
        });
    });
    describe('Error Handling', () => {
        it('should handle vim mode toggle errors gracefully', async () => {
            mockToggleVimEnabled.mockRejectedValue(new Error('Toggle failed'));
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Try to toggle a setting (this might trigger vim mode toggle)
            act(() => {
                stdin.write(TerminalKeys.ENTER); // Enter
            });
            // Should not crash
            unmount();
        });
    });
    describe('Complex State Management', () => {
        it('should track modified settings correctly', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Toggle a setting, then toggle another setting
            act(() => {
                stdin.write(TerminalKeys.ENTER); // Enter
                stdin.write(TerminalKeys.DOWN_ARROW); // Down
                stdin.write(TerminalKeys.ENTER); // Enter
            });
            // Should track multiple modified settings
            unmount();
        });
        it('should handle scrolling when there are many settings', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Navigate down many times to test scrolling
            act(() => {
                for (let i = 0; i < 10; i++) {
                    stdin.write(TerminalKeys.DOWN_ARROW); // Down arrow
                }
            });
            unmount();
        });
    });
    describe('VimMode Integration', () => {
        it('should sync with VimModeContext when vim mode is toggled', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = render(_jsx(VimModeProvider, { settings: settings, children: _jsx(KeypressProvider, { children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }) }));
            // Navigate to and toggle vim mode setting
            // This would require knowing the exact position of vim mode setting
            act(() => {
                stdin.write(TerminalKeys.ENTER); // Enter
            });
            unmount();
        });
    });
    describe('Specific Settings Behavior', () => {
        it('should show correct display values for settings with different states', () => {
            const settings = createMockSettings({
                user: {
                    settings: { vimMode: true, hideTips: false },
                    originalSettings: { vimMode: true, hideTips: false },
                    path: '',
                },
                system: {
                    settings: { hideWindowTitle: true },
                    originalSettings: { hideWindowTitle: true },
                    path: '',
                },
                workspace: {
                    settings: { ideMode: false },
                    originalSettings: { ideMode: false },
                    path: '',
                },
            });
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            const output = lastFrame();
            // Should contain settings labels
            expect(output).toContain('Settings');
        });
        it('should handle immediate settings save for non-restart-required settings', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Toggle a non-restart-required setting (like hideTips)
            act(() => {
                stdin.write(TerminalKeys.ENTER); // Enter - toggle current setting
            });
            // Should save immediately without showing restart prompt
            unmount();
        });
        it('should show restart prompt for restart-required settings', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, unmount } = renderDialog(settings, onSelect);
            // This test would need to navigate to a specific restart-required setting
            // Since we can't easily target specific settings, we test the general behavior
            // Should not show restart prompt initially
            await waitFor(() => {
                expect(lastFrame()).not.toContain('To see changes, Gemini CLI must be restarted');
            });
            unmount();
        });
        it('should clear restart prompt when switching scopes', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { unmount } = renderDialog(settings, onSelect);
            // Restart prompt should be cleared when switching scopes
            unmount();
        });
    });
    describe('Settings Display Values', () => {
        it('should show correct values for inherited settings', () => {
            const settings = createMockSettings({
                system: {
                    settings: { vimMode: true, hideWindowTitle: false },
                    originalSettings: { vimMode: true, hideWindowTitle: false },
                    path: '',
                },
            });
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            const output = lastFrame();
            // Settings should show inherited values
            expect(output).toContain('Settings');
        });
        it('should show override indicator for overridden settings', () => {
            const settings = createMockSettings({
                user: {
                    settings: { vimMode: false },
                    originalSettings: { vimMode: false },
                    path: '',
                },
                system: {
                    settings: { vimMode: true },
                    originalSettings: { vimMode: true },
                    path: '',
                },
            });
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            const output = lastFrame();
            // Should show settings with override indicators
            expect(output).toContain('Settings');
        });
    });
    describe('Race Condition Regression Tests', () => {
        it.each([
            {
                name: 'not reset sibling settings when toggling a nested setting multiple times',
                toggleCount: 5,
                shellSettings: {
                    showColor: false,
                    enableInteractiveShell: true,
                },
                expectedSiblings: {
                    enableInteractiveShell: true,
                },
            },
            {
                name: 'preserve multiple sibling settings in nested objects during rapid toggles',
                toggleCount: 3,
                shellSettings: {
                    showColor: false,
                    enableInteractiveShell: true,
                    pager: 'less',
                },
                expectedSiblings: {
                    enableInteractiveShell: true,
                    pager: 'less',
                },
            },
        ])('should $name', async ({ toggleCount, shellSettings, expectedSiblings }) => {
            vi.mocked(saveModifiedSettings).mockClear();
            vi.mocked(getSettingsSchema).mockReturnValue(TOOLS_SHELL_FAKE_SCHEMA);
            const settings = createMockSettings({
                tools: {
                    shell: shellSettings,
                },
            });
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            for (let i = 0; i < toggleCount; i++) {
                act(() => {
                    stdin.write(TerminalKeys.ENTER);
                });
            }
            await waitFor(() => {
                expect(vi.mocked(saveModifiedSettings).mock.calls.length).toBeGreaterThan(0);
            });
            const calls = vi.mocked(saveModifiedSettings).mock.calls;
            calls.forEach((call) => {
                const [modifiedKeys, pendingSettings] = call;
                if (modifiedKeys.has('tools.shell.showColor')) {
                    const shellSettings = pendingSettings.tools?.shell;
                    Object.entries(expectedSiblings).forEach(([key, value]) => {
                        expect(shellSettings?.[key]).toBe(value);
                        expect(modifiedKeys.has(`tools.shell.${key}`)).toBe(false);
                    });
                    expect(modifiedKeys.size).toBe(1);
                }
            });
            expect(calls.length).toBeGreaterThan(0);
            unmount();
        });
    });
    describe('Keyboard Shortcuts Edge Cases', () => {
        it('should handle rapid key presses gracefully', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Rapid navigation
            act(() => {
                for (let i = 0; i < 5; i++) {
                    stdin.write(TerminalKeys.DOWN_ARROW);
                    stdin.write(TerminalKeys.UP_ARROW);
                }
            });
            // Should not crash
            unmount();
        });
        it.each([
            { key: 'Ctrl+C', code: '\u0003' },
            { key: 'Ctrl+L', code: '\u000C' },
        ])('should handle $key to reset current setting to default', async ({ code }) => {
            const settings = createMockSettings({ vimMode: true });
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            act(() => {
                stdin.write(code);
            });
            // Should reset the current setting to its default value
            unmount();
        });
        it('should handle navigation when only one setting exists', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Try to navigate when potentially at bounds
            act(() => {
                stdin.write(TerminalKeys.DOWN_ARROW);
                stdin.write(TerminalKeys.UP_ARROW);
            });
            unmount();
        });
        it('should properly handle Tab navigation between sections', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, unmount } = renderDialog(settings, onSelect);
            // Wait for initial render
            await waitFor(() => {
                expect(lastFrame()).toContain('Vim Mode');
            });
            // Verify initial state: settings section active, scope section inactive
            expect(lastFrame()).toContain('Vim Mode'); // Settings section active
            expect(lastFrame()).toContain('Apply To'); // Scope section (don't rely on exact spacing)
            // This test validates the rendered UI structure for tab navigation
            // Actual tab behavior testing is complex due to keypress handling
            unmount();
        });
    });
    describe('Error Recovery', () => {
        it('should handle malformed settings gracefully', () => {
            // Create settings with potentially problematic values
            const settings = createMockSettings({
                user: {
                    settings: { vimMode: null },
                    originalSettings: { vimMode: null },
                    path: '',
                },
            });
            const onSelect = vi.fn();
            const { lastFrame } = renderDialog(settings, onSelect);
            // Should still render without crashing
            expect(lastFrame()).toContain('Settings');
        });
        it('should handle missing setting definitions gracefully', () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            // Should not crash even if some settings are missing definitions
            const { lastFrame } = renderDialog(settings, onSelect);
            expect(lastFrame()).toContain('Settings');
        });
    });
    describe('Complex User Interactions', () => {
        it('should handle complete user workflow: navigate, toggle, change scope, exit', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, unmount } = renderDialog(settings, onSelect);
            // Wait for initial render
            await waitFor(() => {
                expect(lastFrame()).toContain('Vim Mode');
            });
            // Verify the complete UI is rendered with all necessary sections
            expect(lastFrame()).toContain('Settings'); // Title
            expect(lastFrame()).toContain('Vim Mode'); // Active setting
            expect(lastFrame()).toContain('Apply To'); // Scope section
            expect(lastFrame()).toContain('User Settings'); // Scope options (no numbers when settings focused)
            // Use regex for more flexible help text matching
            expect(lastFrame()).toMatch(/Enter.*select.*Tab.*focus.*Esc.*close/);
            // This test validates the complete UI structure is available for user workflow
            // Individual interactions are tested in focused unit tests
            unmount();
        });
        it('should allow changing multiple settings without losing pending changes', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Toggle multiple settings
            act(() => {
                stdin.write(TerminalKeys.ENTER); // Enter
                stdin.write(TerminalKeys.DOWN_ARROW); // Down
                stdin.write(TerminalKeys.ENTER); // Enter
                stdin.write(TerminalKeys.DOWN_ARROW); // Down
                stdin.write(TerminalKeys.ENTER); // Enter
            });
            // The test verifies that all changes are preserved and the dialog still works
            // This tests the fix for the bug where changing one setting would reset all pending changes
            unmount();
        });
        it('should maintain state consistency during complex interactions', async () => {
            const settings = createMockSettings({ vimMode: true });
            const onSelect = vi.fn();
            const { stdin, unmount } = renderDialog(settings, onSelect);
            // Multiple scope changes
            act(() => {
                stdin.write(TerminalKeys.TAB); // Tab to scope
                stdin.write('2'); // Workspace
                stdin.write(TerminalKeys.TAB); // Tab to settings
                stdin.write(TerminalKeys.TAB); // Tab to scope
                stdin.write('1'); // User
            });
            // Should maintain consistent state
            unmount();
        });
        it('should handle restart workflow correctly', async () => {
            const settings = createMockSettings();
            const onRestartRequest = vi.fn();
            const { stdin, unmount } = renderDialog(settings, vi.fn(), {
                onRestartRequest,
            });
            // This would test the restart workflow if we could trigger it
            act(() => {
                stdin.write('r'); // Try restart key
            });
            // Without restart prompt showing, this should have no effect
            expect(onRestartRequest).not.toHaveBeenCalled();
            unmount();
        });
    });
    describe('Restart and Search Conflict Regression', () => {
        it('should prioritize restart request over search text box when showRestartPrompt is true', async () => {
            vi.mocked(getSettingsSchema).mockReturnValue(TOOLS_SHELL_FAKE_SCHEMA);
            const settings = createMockSettings();
            const onRestartRequest = vi.fn();
            const { stdin, lastFrame, unmount } = renderDialog(settings, vi.fn(), {
                onRestartRequest,
            });
            // Wait for initial render
            await waitFor(() => expect(lastFrame()).toContain('Show Color'));
            // Navigate to "Enable Interactive Shell" (second item in TOOLS_SHELL_FAKE_SCHEMA)
            act(() => {
                stdin.write(TerminalKeys.DOWN_ARROW);
            });
            // Wait for navigation to complete
            await waitFor(() => expect(lastFrame()).toContain('● Enable Interactive Shell'));
            // Toggle it to trigger restart required
            act(() => {
                stdin.write(TerminalKeys.ENTER);
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('To see changes, Gemini CLI must be restarted');
            });
            // Press 'r' - it should call onRestartRequest, NOT be handled by search
            act(() => {
                stdin.write('r');
            });
            await waitFor(() => {
                expect(onRestartRequest).toHaveBeenCalled();
            });
            unmount();
        });
        it('should hide search box when showRestartPrompt is true', async () => {
            vi.mocked(getSettingsSchema).mockReturnValue(TOOLS_SHELL_FAKE_SCHEMA);
            const settings = createMockSettings();
            const { stdin, lastFrame, unmount } = renderDialog(settings, vi.fn());
            // Search box should be visible initially (searchPlaceholder)
            expect(lastFrame()).toContain('Search to filter');
            // Navigate to "Enable Interactive Shell" and toggle it
            act(() => {
                stdin.write(TerminalKeys.DOWN_ARROW);
            });
            await waitFor(() => expect(lastFrame()).toContain('● Enable Interactive Shell'));
            act(() => {
                stdin.write(TerminalKeys.ENTER);
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('To see changes, Gemini CLI must be restarted');
            });
            // Search box should now be hidden
            expect(lastFrame()).not.toContain('Search to filter');
            unmount();
        });
    });
    describe('String Settings Editing', () => {
        it('should allow editing and committing a string setting', async () => {
            let settings = createMockSettings({ 'a.string.setting': 'initial' });
            const onSelect = vi.fn();
            const { stdin, unmount, rerender } = render(_jsx(KeypressProvider, { children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
            // Navigate to the last setting
            act(() => {
                for (let i = 0; i < 20; i++) {
                    stdin.write('j'); // Down
                }
            });
            // Press Enter to start editing, type new value, and commit
            act(() => {
                stdin.write('\r'); // Start editing
                stdin.write('new value');
                stdin.write('\r'); // Commit
            });
            settings = createMockSettings({
                user: {
                    settings: { 'a.string.setting': 'new value' },
                    originalSettings: { 'a.string.setting': 'new value' },
                    path: '',
                },
            });
            rerender(_jsx(KeypressProvider, { children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
            // Press Escape to exit
            act(() => {
                stdin.write('\u001B');
            });
            await waitFor(() => {
                expect(onSelect).toHaveBeenCalledWith(undefined, 'User');
            });
            unmount();
        });
    });
    describe('Search Functionality', () => {
        it('should display text entered in search', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, stdin, unmount } = renderDialog(settings, onSelect);
            // Wait for initial render and verify that search is not active
            await waitFor(() => {
                expect(lastFrame()).not.toContain('> Search:');
            });
            expect(lastFrame()).toContain('Search to filter');
            // Press '/' to enter search mode
            act(() => {
                stdin.write('/');
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('/');
                expect(lastFrame()).not.toContain('Search to filter');
            });
            unmount();
        });
        it('should show search query and filter settings as user types', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, stdin, unmount } = renderDialog(settings, onSelect);
            act(() => {
                stdin.write('yolo');
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('yolo');
                expect(lastFrame()).toContain('Disable YOLO Mode');
            });
            unmount();
        });
        it('should exit search settings when Escape is pressed', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, stdin, unmount } = renderDialog(settings, onSelect);
            act(() => {
                stdin.write('vim');
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('vim');
            });
            // Press Escape
            act(() => {
                stdin.write(TerminalKeys.ESCAPE);
            });
            await waitFor(() => {
                // onSelect is called with (settingName, scope).
                // undefined settingName means "close dialog"
                expect(onSelect).toHaveBeenCalledWith(undefined, expect.anything());
            });
            unmount();
        });
        it('should handle backspace to modify search query', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, stdin, unmount } = renderDialog(settings, onSelect);
            act(() => {
                stdin.write('vimm');
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('vimm');
            });
            // Press backspace
            act(() => {
                stdin.write(TerminalKeys.BACKSPACE);
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('vim');
                expect(lastFrame()).toContain('Vim Mode');
                expect(lastFrame()).not.toContain('Hook Notifications');
            });
            unmount();
        });
        it('should display nothing when search yields no results', async () => {
            const settings = createMockSettings();
            const onSelect = vi.fn();
            const { lastFrame, stdin, unmount } = renderDialog(settings, onSelect);
            // Type a search query that won't match any settings
            act(() => {
                stdin.write('nonexistentsetting');
            });
            await waitFor(() => {
                expect(lastFrame()).toContain('nonexistentsetting');
                expect(lastFrame()).toContain('');
                expect(lastFrame()).not.toContain('Vim Mode'); // Should not contain any settings
                expect(lastFrame()).not.toContain('Enable Auto Update'); // Should not contain any settings
            });
            unmount();
        });
    });
    describe('Snapshot Tests', () => {
        /**
         * Snapshot tests for SettingsDialog component using ink-testing-library.
         * These tests capture the visual output of the component in various states.
         * The snapshots help ensure UI consistency and catch unintended visual changes.
         */
        it.each([
            {
                name: 'default state',
                userSettings: {},
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
            {
                name: 'various boolean settings enabled',
                userSettings: {
                    general: {
                        vimMode: true,
                        enableAutoUpdate: false,
                        debugKeystrokeLogging: true,
                        enablePromptCompletion: true,
                    },
                    ui: {
                        hideWindowTitle: true,
                        hideTips: true,
                        showMemoryUsage: true,
                        showLineNumbers: true,
                        showCitations: true,
                        accessibility: {
                            enableLoadingPhrases: false,
                            screenReader: true,
                        },
                    },
                    ide: {
                        enabled: true,
                    },
                    context: {
                        loadMemoryFromIncludeDirectories: true,
                        fileFiltering: {
                            respectGitIgnore: true,
                            respectGeminiIgnore: true,
                            enableRecursiveFileSearch: true,
                            enableFuzzySearch: true,
                        },
                    },
                    tools: {
                        enableInteractiveShell: true,
                        useRipgrep: true,
                    },
                    security: {
                        folderTrust: {
                            enabled: true,
                        },
                    },
                },
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
            {
                name: 'mixed boolean and number settings',
                userSettings: {
                    general: {
                        vimMode: false,
                        enableAutoUpdate: false,
                    },
                    ui: {
                        showMemoryUsage: true,
                        hideWindowTitle: false,
                    },
                    tools: {
                        truncateToolOutputThreshold: 50000,
                        truncateToolOutputLines: 1000,
                    },
                    context: {
                        discoveryMaxDirs: 500,
                    },
                    model: {
                        maxSessionTurns: 100,
                        skipNextSpeakerCheck: false,
                    },
                },
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
            {
                name: 'focused on scope selector',
                userSettings: {},
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: (stdin) => {
                    act(() => {
                        stdin.write('\t');
                    });
                },
            },
            {
                name: 'accessibility settings enabled',
                userSettings: {
                    ui: {
                        accessibility: {
                            enableLoadingPhrases: false,
                            screenReader: true,
                        },
                        showMemoryUsage: true,
                        showLineNumbers: true,
                    },
                    general: {
                        vimMode: true,
                    },
                },
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
            {
                name: 'file filtering settings configured',
                userSettings: {
                    context: {
                        fileFiltering: {
                            respectGitIgnore: false,
                            respectGeminiIgnore: true,
                            enableRecursiveFileSearch: false,
                            enableFuzzySearch: false,
                        },
                        loadMemoryFromIncludeDirectories: true,
                        discoveryMaxDirs: 100,
                    },
                },
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
            {
                name: 'tools and security settings',
                userSettings: {
                    tools: {
                        enableInteractiveShell: true,
                        useRipgrep: true,
                        truncateToolOutputThreshold: 25000,
                        truncateToolOutputLines: 500,
                    },
                    security: {
                        folderTrust: {
                            enabled: true,
                        },
                    },
                    model: {
                        maxSessionTurns: 50,
                        skipNextSpeakerCheck: true,
                    },
                },
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
            {
                name: 'all boolean settings disabled',
                userSettings: {
                    general: {
                        vimMode: false,
                        enableAutoUpdate: true,
                        debugKeystrokeLogging: false,
                        enablePromptCompletion: false,
                    },
                    ui: {
                        hideWindowTitle: false,
                        hideTips: false,
                        showMemoryUsage: false,
                        showLineNumbers: false,
                        showCitations: false,
                        accessibility: {
                            enableLoadingPhrases: true,
                            screenReader: false,
                        },
                    },
                    ide: {
                        enabled: false,
                    },
                    context: {
                        loadMemoryFromIncludeDirectories: false,
                        fileFiltering: {
                            respectGitIgnore: false,
                            respectGeminiIgnore: false,
                            enableRecursiveFileSearch: false,
                            enableFuzzySearch: true,
                        },
                    },
                    tools: {
                        enableInteractiveShell: false,
                        useRipgrep: false,
                    },
                    security: {
                        folderTrust: {
                            enabled: false,
                        },
                    },
                },
                systemSettings: {},
                workspaceSettings: {},
                stdinActions: undefined,
            },
        ])('should render $name correctly', ({ userSettings, systemSettings, workspaceSettings, stdinActions }) => {
            const settings = createMockSettings({
                user: {
                    settings: userSettings,
                    originalSettings: userSettings,
                    path: '',
                },
                system: {
                    settings: systemSettings,
                    originalSettings: systemSettings,
                    path: '',
                },
                workspace: {
                    settings: workspaceSettings,
                    originalSettings: workspaceSettings,
                    path: '',
                },
            });
            const onSelect = vi.fn();
            const { lastFrame, stdin } = renderDialog(settings, onSelect);
            if (stdinActions) {
                stdinActions(stdin);
            }
            expect(lastFrame()).toMatchSnapshot();
        });
    });
});
//# sourceMappingURL=SettingsDialog.test.js.map