diff --git a/ui/tests/unit/ui/pages/settings/settings-page.test.tsx b/ui/tests/unit/ui/pages/settings/settings-page.test.tsx
new file mode 100644
index 00000000..651a3adb
--- /dev/null
+++ b/ui/tests/unit/ui/pages/settings/settings-page.test.tsx
@@ -0,0 +1,87 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import type { ReactNode } from 'react';
+import { render, screen } from '@tests/setup/test-utils';
+
+const mocks = vi.hoisted(() => ({
+ useSettingsTab: vi.fn(),
+ useRawConfig: vi.fn(),
+ setActiveTab: vi.fn(),
+ fetchRawConfig: vi.fn(),
+ copyToClipboard: vi.fn(),
+}));
+
+vi.mock('@/pages/settings/hooks', () => ({
+ useSettingsTab: mocks.useSettingsTab,
+ useRawConfig: mocks.useRawConfig,
+}));
+
+vi.mock('react-resizable-panels', () => ({
+ PanelGroup: ({ children }: { children: ReactNode }) =>
{children}
,
+ Panel: ({ children }: { children: ReactNode }) =>
{children}
,
+ PanelResizeHandle: () =>
,
+}));
+
+vi.mock('@/components/shared/code-editor', () => ({
+ CodeEditor: ({ value }: { value: string }) => (
+
+ ),
+}));
+
+vi.mock('@/pages/settings/sections/websearch', () => ({
+ default: () =>
WebSearch Section
,
+}));
+
+vi.mock('@/pages/settings/sections/channels', () => ({
+ default: () =>
Channels Section
,
+}));
+
+vi.mock('@/pages/settings/sections/globalenv-section', () => ({
+ default: () =>
Global Env Section
,
+}));
+
+vi.mock('@/pages/settings/sections/thinking', () => ({
+ default: () =>
Thinking Section
,
+}));
+
+vi.mock('@/pages/settings/sections/proxy', () => ({
+ default: () =>
Proxy Section
,
+}));
+
+vi.mock('@/pages/settings/sections/auth-section', () => ({
+ default: () =>
Auth Section
,
+}));
+
+vi.mock('@/pages/settings/sections/backups-section', () => ({
+ default: () =>
Backups Section
,
+}));
+
+import { SettingsPage } from '@/pages/settings';
+
+describe('SettingsPage raw config panel', () => {
+ beforeEach(() => {
+ mocks.setActiveTab.mockReset();
+ mocks.fetchRawConfig.mockReset();
+ mocks.copyToClipboard.mockReset();
+
+ mocks.useSettingsTab.mockReturnValue({
+ activeTab: 'websearch',
+ setActiveTab: mocks.setActiveTab,
+ });
+ });
+
+ it('keeps the current config editor visible while raw config refreshes', async () => {
+ mocks.useRawConfig.mockReturnValue({
+ rawConfig: 'websearch:\n enabled: true\n',
+ loading: true,
+ copied: false,
+ fetchRawConfig: mocks.fetchRawConfig,
+ copyToClipboard: mocks.copyToClipboard,
+ });
+
+ render(
);
+
+ expect(await screen.findAllByText('WebSearch Section')).toHaveLength(2);
+ expect(screen.getByLabelText('config editor')).toHaveValue('websearch:\n enabled: true\n');
+ expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
+ });
+});